Dan's MEGA65 Digest : Dan Sanderson
Dan's MEGA65 Digest : Dan Sanderson

Dan's MEGA65 Digest : Dan Sanderson

Dan Sanderson

Overview
Episodes

Details

What's new with the MEGA65 personal computer

Recent Episodes

Hosting Update 2025
FEB 11, 2025
Hosting Update 2025

Greetings MEGA65 fans! I am updating the hosting situation of this newsletter. Hopefully this will be automatic for nearly everyone, and you don’t need to do anything. Here’s what you need to know.

As I mentioned in last month’s Digest, I am updating the hosting situation of this newsletter. Based on many recommendations from friends and my experiences with other newsletters, I have chosen Buttondown for email subscriptions. They’re featureful, reasonably priced, and best of all, you don’t need to create an account to be an email subscriber.

In most cases, you don’t have to do anything in response to this change. Here are the details.

Email:

  • Email subscriptions should update automatically.
  • You may need to confirm that you are receiving emails from Buttondown correctly. (Check your spam folder, etc.) If you received this by email, then it’s working.
  • To change your email subscription, see the link at the bottom of every email.

Podcast:

  • Podcast subscriptions should update automatically. We’ll see what happens with the next episode. 😄
  • Apple Podcasts has been updated with the new feed URL, and the old feed URL has been set to redirect to the new one.
  • To subscribe to the podcast in your podcast player, search for “Dan’s MEGA65 Digest,” or add the RSS feed directly.

RSS feed readers and the Substack app:

  • If you read the Digest with an RSS feed reader, make sure you are subscribed to the RSS feed on my website, not Substack’s feed.
  • If you read the Digest through the Substack app, consider subscribing by email, or use an RSS feed reader.
  • New issues will not be posted to Substack.

Substack paid subscriptions:

  • If you support the Digest with a paid Substack subscription, thank you for your support!
  • Your subscription is still active. You should be able to manage your subscription through Buttondown, or directly through Stripe. Substack no longer takes a cut.
  • Feel free to move your patronage subscription to Ko-fi: https://ko-fi.com/dddaaannn

All issues of the Digest are on my website: dansanderson.com/mega65/ For now, I will leave copies of past issues on Substack’s website to preserve links. New issues will be posted exclusively to my website, and distributed by email and these feeds.

Thank you for your patience as I work out the kinks in the new tools! Please let me know if you have any questions, concerns, or feedback.

— Dan

play-circle icon
-1 MIN
Disassembling Crossroads, part 2
FEB 1, 2025
Disassembling Crossroads, part 2
<p><a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-1/">In last November’s Digest</a>, we started a project to dissect the classic C64 title <em>Crossroads</em>, published by Compute!’s Gazette magazine in December 1987. We got a handle on how the game works by playing it, and by inspecting the running game state in <a target="_blank" href="https://github.com/slajerek/RetroDebugger">Retro Debugger</a>, a C64 emulator with memory visualization features. In this issue, we’ll get up close and personal with the <em>Crossroads</em> machine code, using a tool called a <em>disassembler</em>. Combined with what we’ve learned, and some world knowledge of Commodore programs, we can begin to produce human-readable assembly language source code for the game.</p><p><em>Crossroads</em> was so popular that Compute! commissioned a sequel, <em>Crossroads II: Pandemonium</em>, which was published in December 1988. I did some searching to see if anyone has disassembled the <em>Crossroads</em> games already, and discovered <a target="_blank" href="https://github.com/hyphz/crossroads-2-disassembly/tree/master">an excellent disassembly of Crossroads II</a> by Github user hyphz. For the sake of the exercise, I did not look closely at this disassembly at first, but I do expect the original <em>Crossroads</em> to be similar in many ways.</p><p>We won’t do a full disassembly of <em>Crossroads</em> in a single newsletter, but we’ll answer some of the most important questions. Before we do that, let’s see what everyone else is up to!</p><p>PET core pre-release</p><p>Olaf “Rhialto” Seibert is working on a Commodore PET core for the MEGA65, and has <a target="_blank" href="https://files.mega65.org/?id=468325ae-7e27-475d-80e7-a0f0af409446">invited everyone to help test a pre-release version</a>. The Filehost download includes core builds for R3 and R6 boards, and a copy of the necessary ROM files that you install on the SD card in a folder named pet/.</p><p>Do keep in mind that this is a pre-release and may be missing features. Check out <a target="_blank" href="https://github.com/Rhialto/PET_MEGA65">the Commodore PET core on Github</a> to see source files and file bugs. Many thanks to Rhialto for this exciting project!</p><p>Gaplus arcade core</p><p>muse continues to deliver arcade core goodness! This month, it’s Gaplus, the third game in the Galaga series from Namco. As usual, you will need to <a target="_blank" href="https://files.mega65.org/?id=a87ab90e-06bc-40bb-8257-6988345d7784">download the Gaplus core</a>, locate MAME ROMs on the Internet, then <a target="_blank" href="https://github.com/sho3string/GaplusMEGA65_R3_R6/blob/master/README.md">follow the set-up instructions</a> to produce the files for the SD card. The Gaplus core is available for both R3 and R6 mainboards.</p><p>I encountered an issue with the R6 version when using HDMI video where after a few seconds the game video becomes a static screen of vertical bars. This does not occur over VGA, or with the version for the R3 mainboard. A fix is in progress.</p><p>Goodwell’s QR code generator</p><p>Goodwell, aka <a target="_blank" href="https://www.youtube.com/@the8bittheory">The 8 Bit Theory on YouTube</a>, recently attempted an experiment to write a <a target="_blank" href="https://en.wikipedia.org/wiki/QR_code">QR code</a> generator for multiple vintage Commodore computers in multiple languages, including BASIC 2, BASIC 7, C, 6502 assembly language—and BASIC 65 for the MEGA65. <a target="_blank" href="https://www.youtube.com/watch?v=VD_FmrHzkIA">The video</a> about the experience discusses implementation techniques and performance characteristics of these implementations. Definitely check it out, it’s worth watching the whole thing.</p><p>Goodwell <a target="_blank" href="https://files.mega65.org/?id=1b586270-24e0-4800-b66b-89567c83541f">uploaded the MEGA65 version to Filehost</a>, and is continuing to refine it. It might even get added to the MEGA65 Intro Disk menu system, to make it easier to share URLs in the menu text. <a target="_blank" href="https://github.com/the8bittheory/qr128">The Github repo</a> for the QR code generator has all of the versions of the experiment, as source code.</p><p>Don’t miss Goodwell’s follow-up video about <a target="_blank" href="https://www.youtube.com/watch?v=1xj2Fj3SjUk">the MEGA65’s technical design</a>, based on his early experiences developing for the computer.</p><p>MegaMage by SirGeldi</p><p>Hot off the presses! SirGeldi on Forum64.de has posted <a target="_blank" href="https://www.forum64.de/index.php?thread/153356-megamage/">MEGAMage</a>, a <a target="_blank" href="https://en.wikipedia.org/wiki/Roguelike">Roguelike</a> adventure game written entirely in BASIC. Adorable character graphics and fast map scrolling enhance the gameplay. Even better, SirGeldi built the tools used to develop the graphics, map, and object and monster metadata for the game on the MEGA65 in BASIC, and has included these tools on the disk!</p><p>Download the .zip file from SirGeldi’s message post, unpack it, and transfer the D81 disk image to your MEGA65. To start the game, mount the disk image, then:</p><p>RUN "MEGAMAGE"</p><p>Even more Featured Files!</p><p><a target="_blank" href="https://files.mega65.org/?id=c7911dff-a85d-4be7-b205-8f4728d7185d">Soccer</a>, by SirLazarus, is a new soccer-themed paddle game. It is written in BASIC, and requires the <a target="_blank" href="https://files.mega65.org/?ar=145591dd-deb6-4bd0-aa89-8e39cd021470">latest ROM beta version</a> 920409 because it uses recently added features. (This ROM update will be included in the next stable release package.) Grab your paddle controllers and check it out!</p><p><a target="_blank" href="https://files.mega65.org/?id=ba8f56fb-bace-4428-b828-ce2c9fdce379">Jotto 2020</a>, by ToneDeF, is a word puzzle game similar to Mastermind. It plays something like Wordle, though its invention pre-dates Wordle by a year. ToneDeF originally wrote this for other micros, and made this new version for the MEGA65 in BASIC.</p><p><a target="_blank" href="https://files.mega65.org/?id=925c3538-99a0-4f8f-9cc4-0f68d4f39549">Pac-man in BASIC demo</a>, by xlar54. This playable demo sports many features of the arcade classic, including music, sound, and polished graphics. xlar insists this is just a demo, but only a few features are missing (most notably power pellets). And yes, this too is implemented entirely in BASIC 65.</p><p><a target="_blank" href="https://files.mega65.org/?id=59f31c44-8664-4b6a-927b-b4cf6566a156">Opal Dance</a>, by lochmana, is a colorful puzzle and maze game. Match colored pieces by walking into them, but think before you move! Each match of two pieces replaces the first piece with a wall, and removes the second piece. Clear as much of the level as you can.</p><p><a target="_blank" href="https://files.mega65.org/?id=b1ba53df-1987-4789-9000-57690ef65678">Mega65 Perpetual Calendar</a>, by gcastel (MiddleAgedCoder on Discord). Generate calendars for any month of any year. Developed for BASIC 65 with Eleven, you can get <a target="_blank" href="https://github.com/gcastel/mega65-cal">the source code from Github</a>.</p><p><a target="_blank" href="https://files.mega65.org/html/main.php?id=444fb932-a9b9-4a2f-b114-69353e5ffa89">Xemu keyboard layout reference</a> for Windows, by Discord user Digger. Windows users, keep this handy app open alongside the Xemu emulator to remember how to replicate MEGA65 keystrokes on the PC keyboard. See also <a target="_blank" href="https://only8bit.de/xemukeyboard/">the project homepage</a> (in German), and the README file (in English) included with the download.</p><p>mouSTer back in stock</p><p><a target="_blank" href="https://retrohax.net/shop/modulesandparts/mouster/">mouSTer</a>, the USB-to-Commodore DB9 adapter for modern USB mice and game controllers, is back in stock after a long hiatus. This is one of the best ways to use a modern USB mouse with the MEGA65. It even works with wireless mice that use USB dongles. Get one while you can!</p><p>See <a target="_blank" href="https://retrohax.net/the-mouster-project-20-12-2024-update/">RetroHax’s update from December 30, 2024</a> for details.</p><p>Digest administrative note</p><p>I am considering migrating the Digest to a new email newsletter service. As Substack evolves their business model and practices, I want to make sure the Digest is hosted on services that remain open and compatible with the values of the MEGA65 project. I’ll let everyone know in advance before I make changes.</p><p>The change should be fully automatic, including migrating donations made through the Substack interface as paid subscriptions. Hopefully I can migrate the read-aloud podcast feed URL automatically as well, but this will depend on how your podcast app is subscribed. I’ll try to figure it out and let you know. If anyone has any feedback on this change, <a target="_blank" href="mailto:[email protected]">please let me know</a>. I know a couple of you are using the Substack app to read it, which should be the only case affected by a migration.</p><p>You can always find all issues of the Digest <a target="_blank" href="https://dansanderson.com/mega65/">on my website</a> and <a target="_blank" href="https://dansanderson.com/mega65/index.xml">subscribe to it using an RSS feed reader</a>. You can also <a target="_blank" href="https://ko-fi.com/dddaaannn">become a patron of the Digest at ko-fi.com/dddaaannn</a>.</p><p>The art of disassembly</p><p>A quick recap: A computer’s CPU performs instructions encoded as bytes in the computer’s memory. This machine code is difficult to work with as a list of numbers, so when we humans want to write a program, we use a programming language, and a tool that converts that language to machine code for the computer to execute. Assembly language is a human language that most closely resembles the machine code, with human-readable names for each machine code instruction. The corresponding conversion tool is called an assembler.</p><p>There’s a simple assembler built into the MEGA65’s machine language monitor. You can start the monitor by entering the MONITOR command at the READY prompt. Try doing this now, and use the A command to assemble this short program:</p><p>MONITOR A1600 LDA #$01 STA $D020 LDA #$00 STA $D021 RTS</p><p>After the last line, press <strong>Return</strong> on a line by itself to stop the assembler.</p><p>As you type each line, the monitor converts the instruction to the corresponding machine code. It stores the machine code at the requested address in memory, and also prints the address and machine code bytes to the screen, as hexadecimal values.</p><p>A 1600 A9 01 LDA #$01 A 1602 8D 20 D0 STA $D020 A 1605 A9 00 LDA #$00 A 1607 8D 21 D0 STA $D021 A 160A 60 RTS</p><p>The monitor can also reverse this process, to show you which instructions are represented by bytes in memory. This process is known as <em>disassembly.</em> Use the D command followed by the address:</p><p>D1600</p><p>Sure enough, the program you just entered is right where you put it, at address $1600. There’s also a bunch of other stuff after the last instruction you typed starting at address $160B, maybe garbage data or something left behind by another program. These bytes may or may not represent machine code instructions, but the disassembler diligently tries to interpret them as instructions either way. These instructions are what the CPU <em>would</em> perform if you told it to treat that memory as code.</p><p>The number of bytes used to encode an instruction differs depending on the instruction. Some instructions, like RTS, are encoded as a single byte. Others, like LDA #$01, use two bytes. Still others such as STA $D020 require three bytes. Anything trying to interpret bytes as machine code—whether that’s a disassembler or the CPU itself—needs to know the address of the first byte of the first instruction, or it could get very confused.</p><p>Try using the disassemble (D) command again, this time with a starting address of $1601:</p><p>D1601</p><p>The monitor tries to disassemble some of the memory of the program you entered, but the result looks nothing like the program. $1601 is the address of the second byte of the LDA instruction, $01, which to the disassembler (and the CPU) looks like a version of the ORA instruction that uses two bytes. At address $1603, the next byte $20 looks like a three-byte JSR instruction. Coincidentally, the next incorrect instruction gets the disassembler back on track, aligned with the correct first instruction byte at address $1607. But by now, a CPU trying to execute this code will get very lost, and probably crash.</p><p>Disassemblers are not magic, and they need help from the operator—that’s you—to convert machine code back into human-readable assembly language. The disassembly process requires research, maybe some guessing and checking, taking notes, and labeling addresses and values once you’ve figured out what they mean. A modern disassembly tool can make this process surprisingly easy.</p><p>Introducing Ghidra</p><p><a target="_blank" href="https://ghidra-sre.org/">Ghidra</a> is a powerful disassembler and reverse engineering multi-tool. It supports many types of CPU machine code, including the 6502, and supports extensions to add more. Ghidra was originally developed by the United States National Security Agency (NSA), and has been released as open source and free of cost.</p><p>I want to credit two YouTube videos on the topic of using Ghidra for reverse engineering Commodore 64 programs: <a target="_blank" href="https://youtu.be/3wW1una5Pgg?si=48McDKRrIA6kfK1D">Introduction to Ghidra</a> by David Youd, and <a target="_blank" href="https://www.youtube.com/watch?v=xNFswb9CVkg">How to start a new C64 project in Ghidra</a> by Jarkko Lehti. These are worth watching when you get a chance, and we’ll be using Lehti’s configuration files in a moment.</p><p>Setting up Ghidra</p><p>As of this writing, the latest version of Ghidra is v11.2.1. It’s a Java-based application, and it requires a recent version of <a target="_blank" href="https://www.oracle.com/java/technologies/downloads/">the Java runtime</a> (21 or later), which you may need to install or upgrade. Ghidra will tell you if your Java is too old. Properly installed, Windows users can double-click on ghidraRun.bat to start the program, and macOS and Linux users invoke the ghidraRun shell script.</p><p>As usual, macOS will refuse to run the scripts and tools until you have blessed them in the Privacy & Security panel. You probably know the drill by now. Attempt to start ghidraRun, dismiss the complaint, open macOS Settings: Privacy & Security, scroll down, click Open Anyway. If you use Ghidra for other stuff later, you’ll need to similarly bless some internal components, which you can do in the Terminal app on the command line:</p><p>xattr -cr ./Ghidra/Features/FileFormats/os/mac_arm_64/lzfse xattr -cr ./Ghidra/Features/Decompiler/os/mac_arm_64/decompile xattr -cr ./Ghidra/Features/Decompiler/os/mac_arm_64/sleigh xattr -cr ./GPL/DemanglerGnu/os/mac_arm_64/demangler_gnu_v2_*</p><p>When you run Ghidra for the first time, it will ask for the path to the Java home directory. This will depend on your operating system. On macOS using Java 23 from Oracle, the path is:</p><p>/Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home</p><p>Ghidra opens its main window, from which you create or select a project, and open tools.</p><p>Creating the project</p><p>Let’s start a new project using the crossroads.prg file that we extracted from the disk image in last month’s Digest.</p><p>Create a new project:</p><p>* Open the File menu, select New Project.</p><p>* Select “Non-Shared Project,” click Next.</p><p>* Create a new folder for the project, and select it. Enter a project name, such as “Crossroads.” Click Finish. The dialog window closes, and the project is created.</p><p>Next, import the crossroads.prg file:</p><p>* Open the File menu, select Import File.</p><p>* Navigate to the file crossroads.prg, then Select File To Import.</p><p>* Leave the Format set to “Raw Binary.”</p><p>* Click the ... button next to Language. Select “6502,” which is at the top of the list for this version of Ghidra. Click OK.</p><p>* Leave everything else at default settings, then click OK. Another window opens with some information about the file. Dismiss this with OK.</p><p>Finally, double-click on the crossroads.prg file in the project to open it in the CodeBrowser tool. The first time you do this, Ghidra will offer to analyze the file. Say Yes. Leave the default set of analyzers selected, then click Analyze. The analysis doesn’t produce spectacular results just yet, but it’s usually worth doing.</p><p>Here is crossroads.prg in all its glory, in the CodeBrowser window. These are the same bytes we saw in the hex dump, but now they’re listed one per line. We will use this interface to massage the data as we learn what each part of it means.</p><p>Commenting the code</p><p>Let’s start by telling Ghidra the C64 memory address where this data gets loaded. Because this is a PRG file, it begins with two bytes that are not loaded into memory. We could have gone through an extra step to remove these bytes before importing the data, but for our purposes, it’s enough to just take these into account when telling Ghidra where everything lives.</p><p>This data gets loaded into a single block of memory that starts at address $0801. Minus the two PRG header bytes, we can tell Ghidra to start counting addresses at $07FF:</p><p>* In the Window menu of the CodeBrowser window, select Memory Map. The Memory Map window opens, showing one “RAM” segment that starts at address 0000.</p><p>* Select the “RAM” line, then locate the button whose tooltip reads “Move a block to another address,” a blue arrow-cross icon.</p><p>* For the New Start Address, type 07ff. Click OK.</p><p>* Close the Memory Map window.</p><p>Notice that the data is now lined up with the memory addresses. The first byte of the BASIC bootstrap is at $0801, and the two-byte end-of-BASIC terminator is at $080B. (We peeked at this in <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-1/">the previous Digest</a>.)</p><p>Let’s add a comment describing this data. Right-click on the line for $0801 to open the context menu. Select Comments > Set EOL Comment
 In the window that opens, type a useful description, such as: “Start of BASIC bootstrap.” You may wish to add a similar comment on $080C, for “End of BASIC bootstrap.”</p><p>Initiating disassembly</p><p>The BASIC bootstrap uses the SYS command to invoke machine code starting at decimal address 2300. Ghidra even shows the “2300” characters next to the byte listing, guessing that we might be interested in what these look like as ASCII characters. In hexadecimal, this address is $08FC.</p><p>Navigate to this address in the byte listing. Here’s a quick way: press “G” (for “go”), then enter the address in hexadecimal (08fc).</p><p>Start the disassembly at this address: press “D” (for “disassemble”).</p><p>Ghidra has just done a bunch of work for us! It took our word for it that the bytes starting at $08fc are machine code: $a9 $ff represent the LDA #$ff instruction, which Ghidra spells LDA #0xff, and updated the code listing accordingly. It proceeded to the next instruction, and kept going as long as it was reasonably certain that the CPU would treat those bytes as instructions as it executed.</p><p>Scroll down, and notice that Ghidra stopped disassembly at address $0cab, where it found an RTS instruction. The bytes starting at $0cac may be more CPU instructions, but Ghidra doesn’t know this for sure. In fact, we can see evidence that it may be data and not instructions: the bytes from $0cb1 to $0cba spell out “CROSSROADS” in ASCII. Ghidra doesn’t know this is more likely to be PETSCII and not ASCII, but it displays the ASCII letters for our benefit, just in case.</p><p>Keep scrolling, down to $0dc5. Ghidra found more code! Starting with the first address we gave it, Ghidra decoded each instruction, and when it found a branching instruction or subroutine call, it continued disassembly at that location, filling everything in. It assigned some temporary labels for things that look like functions, such as FUN_0dc5. As we try to understand what the program does, we can replace these labels with more intuitive names. In the end, we’ll have a fully human-readable assembly language program. (Or as human readable as assembly language gets, anyway.)</p><p>Ghidra made similar attempts to highlight data locations referenced in the code, assigning labels such as DAT_08b0. Everything referenced by something else is annotated with the cross references. For example, the byte at address $08b0 is read by an instruction at address $0a7a, so it lists 0a7a(R) (“R” for “read”) next to $08b0.</p><p>We can add our own labels. Let’s do this for our entry point, $08fc:</p><p>* Press “G” for go. Enter 08fc.</p><p>* Press “L” for label. Enter a label name of start. Because this is the entry point of the program, select the “Entry Point” property. Click OK.</p><p>Importing C64 symbols</p><p>Ghidra has invented labels for all of the data and code referenced by the disassembled code. The addresses within the imported data range have blue labels and cross references.</p><p>Where the code references an address not in the imported range, Ghidra also generated a label, and colored it red. Consider the first few instructions of the program, starting at $08fc:</p><p>LDA #0xff STA DAT_d40e STA DAT_d40f</p><p>This loads $ff into the accumulator, and stores that value to addresses $d40e and $d40f. If these were just memory locations, we would assume that these are variables used by the game for storing game state, like the player’s position. In this case, we can apply some knowledge of how the Commodore 64 works: addresses in the range $d000-$dfff are input-output registers that control, or are controlled by, the computer’s hardware. We can look up what these registers do in <a target="_blank" href="https://sta.c64.org/cbm64mem.html">a Commodore 64 technical reference</a>.</p><p>In this case, these registers belong to the SID sound chip, specifically the frequency of the oscillator on voice #3. We don’t yet know why the program does this, but we do know that’s what it does. The next two instructions and a bit more knowledge of C64 programming gives us a hint:</p><p>LDA #0x80 STA DAT_d412</p><p>The technical reference says $d412 is the SID voice #3 control register. Setting bit 7 like this tells it to use the “noise” waveform. <em>Crossroads</em> is certainly a noisy game, but it’s probably setting this up to use as a random number generator, or at least a seed for one. We’ll have to keep our eye out for something that samples a value from voice #3.</p><p>Now that we’ve identified DAT_d40e et al., we could update the labels to something that describes their functions. To do this, you would right-click on the label and select Edit Label
 (or move the cursor onto the label and press “L”).</p><p>Considering that the C64 I/O registers always do the same thing in every program, it would be nice if Ghidra could automatically recognize all of them and give them useful names. The following is one way to do this, based on <a target="_blank" href="https://voidhole.com/~grue/ghidra/c64_symbols/">the files supplied by Jarkko Lehti</a> to accompany <a target="_blank" href="https://www.youtube.com/watch?v=xNFswb9CVkg">his YouTube video</a> on the subject.</p><p>Download these C64 symbol files:</p><p>* <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-2/IO.txt">IO.txt</a>: the I/O registers</p><p>* <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-2/KERNAL.txt">KERNAL.txt</a>: the KERNAL jump table subroutines</p><p>* <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-2/RAM.txt">RAM.txt</a>: commonly used C64 internal KERNAL variables</p><p>* <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-2/IO_d000.bin">IO_d000.bin</a>: a binary snapshot of the initial values of C64 I/O registers</p><p>* <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-2/kernal_e000.bin">kernal_e000.bin</a>: a binary snapshot of the C64 KERNAL</p><p>The .txt files tell Ghidra to apply certain labels to certain addresses when they appear in the code. The .bin files fill in the memory ranges themselves in the Ghidra project, so you can get some idea of what’s actually there in the C64’s memory.</p><p>In your project, the IO and KERNAL data will exist as <em>overlays</em>. An overlay is a portion of memory that may contain different things at different times, based on system state. With the Commodore 64, I/O registers and KERNAL ROM occupy addresses that can also refer to RAM, based on the memory banking register. Ghidra can only see that an instruction accesses an address, not the memory map of the computer at the time the instruction is called. Telling Ghidra that these memory regions are overlays accounts for the possibility that a given reference to an address may refer either to I/O and ROM, or the underlying RAM.</p><p>To create the IO overlay:</p><p>* From the CodeBrowser window, open the File menu, Add To Program
</p><p>* Select IO_d000.bin, click Add To Program.</p><p>* In the Add To Program dialog, click Options
 Select Overlay, use a Block Name of IO, and set the Base Address to d000. Click OK in the Options dialog, then click OK in the Add To Program dialog. Dismiss the Import Results window.</p><p>To create the KERNAL overlay, repeat these steps with the kernal_e000.bin file, using a Block Name of KERNAL and a Base Address of e000.</p><p>Now we can import the symbols that describe addresses in these regions. Ghidra is a highly scriptable application environment, and we can use a script that comes with Ghidra to import the .txt symbols files.</p><p>To import the symbols:</p><p>* From the Window menu, select Script Manager.</p><p>* Scroll down to find ImportSymbolsScript.py. Double-click it to run it.</p><p>* When prompted, select the IO.txt file. Click “Go baby go!”</p><p>* Repeat these steps for the KERNAL.txt file, and again for the RAM.txt file.</p><p>Ghidra now knows about the I/O registers via an overlay with sensibly named symbols. Ghidra still doesn’t know which references refer to RAM and which refer to I/O. We have to tell it.</p><p>Go (“G”) back to the STA instruction at $08fe. Its destination is still the red symbol DAT_d40e. Click on it, then press “R” to edit the reference. In the pop-up window, double-click the reference, then change the dropdown menu that says “RAM:” to “IO:”. Click Update, and close the reference editor. The symbol has changed to D40E_FRQ_3_LO. That’s
 better.</p><p>It’s unusual for a C64 game to un-bank the I/O registers, so it’s a little inconvenient that each label needs to be applied like this. I haven’t found a good way to automatically declare all references to be for the IO overlay. One possibility might be to add IO_d000.bin as a non-overlay region, then edit the IO.txt symbols file to remove the IO:: part of each address. For now, I like keeping IO as an overlay, because it accurately describes how the C64 works.</p><p>I did find a reasonably fast way to update all of the labels manually using Ghidra’s search feature. In the Search menu, select Program Text
 Prepare a search for DAT_d in All Fields of the Listing Display, and click Search All. A window opens with the search results, and clicking on a result causes the Listing display to jump to that location. I got 38 results, and it only took me a few minutes to update all of the references to use the IO labels. It’s not the most fun I’ve ever had with a computer, but it didn’t take so long that I regretted not automating it.</p><p>Getting some answers</p><p>Now that we have at least some idea of what we’re looking at, let’s try to answer a few questions that will help us understand how <em>Crossroads</em> works. These are just questions that occurred to me, in the order I thought to ask them. They may not be the best questions, or in the best order. But let’s see what happens.</p><p>Does the program call the KERNAL jump table?</p><p>This is an easy one. A call to the KERNAL jump table would look like a JSR to a hexadecimal address beginning with an f. Ghidra will have generated a label like FUN_ffd2 prior to me updating it to use the KERNAL overlay’s symbols, so just like we used a search of DAT_d to find I/O register references, we can search for FUN_f to find calls to KERNAL routines. I get no results from this search, so I’m fairly confident that <em>Crossroads</em> does not call KERNAL routines. Alas, we don’t get to use our KERNAL overlay. Maybe next time.</p><p>Does the program use KERNAL vectors?</p><p>As we’ve discussed in previous issues of the Digest, most games drive their game loop using <a target="_blank" href="https://dansanderson.com/mega65/racing-the-beam/">CPU interrupts</a>. There are two ways to set up an interrupt handler: replace the KERNAL’s interrupt handlers in $fffa-$ffff, or use a <a target="_blank" href="https://dansanderson.com/mega65/kernal-of-truth/">KERNAL vector</a> to add a custom subroutine to the KERNAL’s interrupt handler. Let’s check the latter option first, because it’s more common for simple C64 games.</p><p>The designers of the Commodore ROM wanted people to use the VECTOR KERNAL call to read and update the KERNAL vector table, and that’s still a best practice for MEGA65 programs. Even early on, C64 programmers skipped over that part of the manual, and just wrote to the C64 vector table at $0314-$0333. We can search for the string 0314 to find any direct references to the IRQ vector.</p><p>Yup, there it is. The instructions at $0ba8-$0bb1 are writing address $11c4 to the KERNAL IRQ vector $0314-$0315.</p><p>LDA #0xc4 STA 0314_IRQ_VECTOR_LO LDA #0x11 STA 0315_IRQ_VECTOR_HI</p><p>This appears to be the only vector touched, and it is only set in this one location in the code that Ghidra has disassembled. Let’s go to the address being written to the vector and check it out: “G”, then 11c4.</p><p>Hoo boy, Ghidra hasn’t disassembled this yet! This is because the main routine, which sets up the game and installs the IRQ vector, doesn’t actually call the IRQ handler directly. We have a bit more work to do. Press “D” to start disassembly from this address. Also, press “L” to add an entry point label, with a name such as irq.</p><p>We’ll have to re-do our searches for I/O register labels and KERNAL calls now that we have more disassembled code. That’s just how it goes. I found 8 more I/O registers, but still no KERNAL calls.</p><p>Does the program do any C64 CPU bank switching?</p><p>I mentioned that most games leave I/O registers banked to $d000-$dfff, the initial state of the C64. We can double-check that by looking for references to <a target="_blank" href="https://www.c64-wiki.com/wiki/Bank_Switching">the C64 bank switching register</a>, address $0001.</p><p>A search for DAT_0001 does produce two results in the start-up routine, so it’s worth taking a closer look. Starting at address $09f9, the routine sets this to $73, or binary %01110011. According to C64 technical documentation, this setting makes sure the C64 character ROM—the graphics data for the PETSCII font—is visible at $d000-$dfff instead of the I/O registers. It’s not that way for long, though. Just below, at address $0a10, the banking register gets set to $77, or binary %01110111, which switches the I/O registers back in.</p><p>While the character ROM is visible, a short loop copies the first 472 bytes of PETSCII graphics data to address $2000.</p><p> LDX #0x0 LAB_09ff: LDA DAT_d000,X STA 0x2000,X LDA DAT_d0ec,X STA 0x20ec,X INX CPX #0xec BNE LAB_09ff</p><p>Now that we know what this does, we can rename the LAB_09ff label to something like copy_char_loop, and add explanatory comments to the bank switching instructions. We can also relabel DAT_0001 while we’re at it.</p><p>Does the program use any self-modifying code?</p><p>From our perspective as reverse engineers, one of the scariest things a program can do is modify its own code. The program is entirely within its right to do this—code is just data in memory—but it means that the disassembler may not be seeing the code in the form it is executed.</p><p>To find places where the program might be modifying itself, we have to look for attempts to store values in locations that Ghidra believes are inside subroutine code. I bet there’s a way to get Ghidra to make a list of such places, but I haven’t found one yet. I did notice, however, that Ghidra refers to such addresses by the name of the function, plus an offset, like this example near the entry point:</p><p>LDA #0x0 STA FUN_0b4a+1 LDA #0x28 STA FUN_0b4a+2</p><p>These address expressions appear in a grey color. From visual inspection, I found only a few examples of this. Thankfully, they were all short subroutines that were easy to understand, and all of the self-modifications were to addresses for LDA and STA instructions.</p><p>Several of these appear to be simple utility functions for using addresses from variables together with indirect addressing. For example, FUN_0b4a is simply the STA instruction in absolute Y-indexed addressing mode, followed by an RTS. To use this routine, the program writes an address into the STA instruction, sets the A and Y CPU registers, then calls the subroutine:</p><p>FUN_0b4a STA 0x0000,Y RTS</p><p>This probably saved the developer some headache, using a single self-modifying mechanism instead of having every subroutine modify its own instructions. The initialization routine near the entry point uses this mechanism as part of a loop to fill some memory with zeroes.</p><p>Is there any more code?</p><p>We found the entry point and the IRQ vector routine, and we identified self-modifying code and confirmed that it’s not doing something crazy like dynamically writing JMP instructions to memory at run time. It looks like Ghidra has found most of the code in the program. Are we safe to conclude that the remaining unidentified regions are static data, or perhaps initialized variable space?</p><p>This requires a bit of judgement, a bit of guesswork, and a willingness to change our minds later, but we can start to form some conclusions from a visual inspection of Ghidra’s analysis. Here’s what I see so far:</p><p>* $080d-$08fb: I see some repeating numeric patterns that are unlikely to be instructions. Ghidra found cross-references into this memory starting at $08b0, and they’re all read-only references from the initialization routine. The program must refer to some of this data with dynamically calculated addresses that Ghidra can’t see. It’s not conclusive, but with no obvious writes to this memory, this is probably static data, such as graphics patterns.</p><p>* $0cac-$0dc4: Ghidra is displaying obvious patterns in the ASCII decoding that match text displayed on the game’s screen, with strings such as “CROSSROADS” and “1PLAYER,” and many space characters ($20). There are only a few explicit read-only references. This is probably character data for the static parts of the display.</p><p>* $0f65-$11c3 and $15fe-$1693: These are less obvious to me just from staring at them. Some of it is clearly data, but I don’t yet know how to interpret patches of it. Once again, there are no explicit instructions writing to these areas.</p><p>For now at least, I feel confident that these regions are static data and not code, and that Ghidra has found all of the code in the program.</p><p>What’s in the data?</p><p>We can learn more about the suspected data regions by double-clicking on the cross-references and digging around the code that refers to them. We can also make some guesses about how the data is encoded, and try to decode it to see if we recognize any patterns, similar to how we identified text strings with Ghidra’s built-in ASCII decoding.</p><p>I’m especially interested to find the character graphics data that gives <em>Crossroads</em> its special flair. This is likely to take the form of monochrome character pixel data, where each byte represents a row of 8 pixels, and consecutive bytes are stacked, usually in a square of 8 rows. If we visualized the bytes in suspicious data regions this way, would the <em>Crossroads</em> cast of characters jump out at us?</p><p>Ghidra has extensive features for visualizing data structures. Once we have a guess as to how data should be interpreted, we can paint data types onto the bytes and see if they make sense. For example, to visualize a byte as a binary number:</p><p>* Locate address $080f. The byte value is $44. Ghidra doesn’t know how to interpret this, so it displays a type of ??, its hex value, and its ASCII value.</p><p>* Right-click on it to open the context menu, navigate to Data, and select the byte type. Ghidra updates ?? to db.</p><p>* Right-click again, navigate to Data, and now select the Settings
 option that has appeared now that the value has a type. Change Format to “binary” and Padding to “padded.” Click OK. Ghidra updates the visualization to a padded binary value: 01000100b.</p><p>Let’s try this for a chunk of the data region $080d-$08f9. (We can always undo it later.) Click-drag with the mouse, or move the cursor to the first line and hold Shift while cursoring down, to select lines. Use the Data context menu to make them all bytes displayed as padded binary.</p><p>083d ff db 11111111b ; ######## 083e 8f db 10001111b ; # #### 083f ff db 11111111b ; ######## 0840 3c db 00111100b ; #### 0841 7e db 01111110b ; ###### 0842 7e db 01111110b ; ###### 0843 ee db 11101110b ; ### ### 0844 87 db 10000111b ; # ### </p><p>It’s a little difficult to make out when displayed as 0’s and 1’s, but I see some familiar faces. Going eight bytes at a time, I see two frames of animation for each of an enemy missile ($080d), a bullet ($081d), the Human/player ($082d), the Purple Rubberhead ($083d), and more. I have to squint to see the rest, but if each of the nine enemies gets 16 bytes starting at $083d, it feels safe to say these are graphics tiles up to at least $08cd.</p><p>How does the program set up character graphics data?</p><p>We have a rough idea that the game keeps its graphics assets starting at $080d, and establishes its custom character font at $2000 with some combination of this data and PETSCII characters from character ROM. We’ve already found where the set-up routine ($08fc) copies the character ROM to $2000. What else does it do?</p><p>It’s relatively easy to see that a big chunk of the set-up routine is messing around in the $2000 memory region. Starting from the beginning, it sets a few registers, then immediately dives into the work of rendering the character data, with various loops and STA instructions indexing into this memory.</p><p>The characters of <em>Crossroads</em> walk in four directions, with two frames of animation. We only found two frames of animation in the graphics data, with the characters facing to the right. Can you guess where it gets the graphics for the other three directions?</p><p>To achieve the full effect, the set-up loop takes the 8x8 right-facing creature graphics and writes it into character graphics memory. Then it flips each byte horizontally and writes the left-facing copy. Then it rotates it 90 degrees one way for up-facing, and 90 degrees the other way for down-facing.</p><p>Moreover, the second step of each character’s animation is drawn across <em>two</em> character tiles, for that slick grid-breaking animation. The creature takes up two characters on the 40x25 screen for this half step, and no other creature or item is allowed in either tile at this moment. The set-up routine renders these half-steps dynamically from the 8x8 pixel data, using bit shifting instructions to produce half-tile images. I see groups of four bit shifting instructions at $0a5d and $0a6d that might be involved in this process.</p><p>Just after setting up the character data at $2000, the program sets VIC register $d018 to $18. This establishes how the VIC uses memory, and indeed, it sets the character memory pointer to $2000. It also sets the screen memory location to $0400. The VIC-II can only see 16 KB of the address space at a time, and which 16 KB is selected by a register at $dd00. <em>Crossroads</em> does not appear to change this register from its default setting.</p><p>Future possibilities with Ghidra</p><p>That’s a good start, and plenty for a single newsletter. Ghidra is a very powerful tool and I’m still learning about all it can do.</p><p>Ghidra is highly extensible, and there is substantial potential for extensions and scripts to support C64 and MEGA65 development and reverse engineering. In <a target="_blank" href="https://www.youtube.com/watch?v=xNFswb9CVkg">his video</a>, Jarkko Lehti is using <a target="_blank" href="https://github.com/grue74/ghidra-c64helpers">his own Ghidra fork</a> with a few nice features such as PETSCII string visualization.</p><p>When I was squinting at the character set data, I was wishing for a bit of tool support for visualizing bitfields as graphics, much like how Retro Debugger lets you view memory contents in different ways. I wonder if Ghidra can do custom inline data visualizers like this, or if a feature like this is already available.</p><p>The annotated disassembly can be exported in multiple formats, but none of them resemble something that could be re-assembled by a tool such as Acme assembler. A custom export tool or post-processing script would be handy for that, and would be easy to write.</p><p>Of course, the thought naturally occurs to someday use Ghidra to disassemble MEGA65 machine code programs. It’d take some effort, but it is possible to write an extension to provide 45GS02 CPU support to the disassembler. Ghidra has an entire language for specifying new processors called <a target="_blank" href="https://spinsel.dev/assets/2020-06-17-ghidra-brainfuck-processor-1/ghidra_docs/language_spec/html/sleigh.html">SLEIGH</a>.</p><p>It’d also be good to generate symbols files and overlays for all of the MEGA65’s I/O register personalities. <a target="_blank" href="https://github.com/dansanderson/mega65-symbols">I already have symbol generator scripts</a> that could be tweaked to produce something that Ghidra can import.</p><p>In practice, most MEGA65 machine code programs that exist today have friendly authors that have open sourced their code. It’s still fun to think about.</p><p>I chose <em>Crossroads</em> for this demonstration for a few reasons. For one, it really was one of my favorite games, so I was excited to play with it. But also, I had a suspicion that its internals were straightforward enough to understand through disassembly. As fast and seamless as <em>Crossroads</em> is to play, you only need to know a few things about C64 programming to start to make guesses about how it works just from looking at it.</p><p>Many C64 games and demos use data compression techniques to limit disk space and loading times. This can make disassembly more difficult, because you can’t just load the PRG into Ghidra directly. One possible technique is to run the program in Retro Debugger, let it decompress everything into memory, then take a snapshot of the memory of the running program. You can then apply disassembly techniques to the snapshot. I suspected that <em>Crossroads</em> did not use compression for code, and felt comfortable just loading the PRG file directly into Ghidra.</p><p>If you’re interested in writing programs for the MEGA65, it’s worth studying C64 programs. The Commodore 65 was designed as a true technological successor to the C64, and many C64 programming techniques apply to C65 and MEGA65 programs. The original source code for many C64 programs have been lost to time, but we can use tools like Retro Debugger and Ghidra to pull them apart and reconstruct their secrets.</p><p>There’s one more tool that we can use to reverse engineer C64 programs—and it’s sitting right beside you. The MEGA65 can run many C64 programs in its GO64 mode, and you can use the MEGA65 core’s serial debugger, along with a powerful frontend like <a target="_blank" href="https://github.com/MEGA65/m65dbg">m65dbg</a>, to analyze a running program. We’ll have to revisit this in a future Digest.</p><p>Onward into the new year!</p><p>— Dan</p> <br/><br/>Get full access to Dan’s MEGA65 Digest at <a href="https://m65digest.substack.com/subscribe?utm_medium=podcast&#38;utm_campaign=CTA_4">m65digest.substack.com/subscribe</a>
play-circle icon
51 MIN
Santa's Souped-Up MEGA65
DEC 13, 2024
Santa's Souped-Up MEGA65
<p>Hey everyone! I hope you’re all ready for some end-of-the-year relaxation, maybe some time off work, spent with family, in whatever temperature extreme you’re experiencing in your hemisphere. I also hope you’ll get some time to play with your MEGA65, because you’re gonna need it!</p><p>There are so many project announcements this month that I’ve decided to dedicate this entire issue to new downloads, to celebrate everyone’s talent and enthusiasm, and to give thanks for our wonderful community. We will finish our <em>Crossroads</em> disassembly project in January.</p><p>SidPlay65</p><p>There’s a new way to make music with your MEGA65, thanks to MEGA65 developer LightTangent! <a target="_blank" href="https://files.mega65.org/?id=04708d59-c6d0-4319-9728-b0dba44a878a">SidPlay65</a> is a MEGA65 program that re-implements the <a target="_blank" href="https://sidplayer.org/">SIDPlayer music system</a> from Compute! Publishing. It plays single-SID and dual-SID songs, and supports some advanced SIDPlayer format features like colorful PETSCII banner displays and karaoke lyrics.</p><p>SIDPlayer was one of several major tentpole products for the Commodore 64 from Compute!, along with <em>Crossroads</em> and the hit word processing package <em>SpeedScript</em>. The initial version of SIDPlayer appeared as a type-in in the book <a target="_blank" href="https://archive.org/details/All_About_the_Commodore_64_Volume_Two_1985_COMPUTE_Publications"><em>All About the Commodore 64, Volume Two</em></a> by Craig Chamberlain. It included rudimentary music editing software, and a player routine that could be embedded in your BASIC or machine language programs. Chamberlain revised the system and published the Enhanced SIDPlayer in the book <a target="_blank" href="https://archive.org/details/Computes_Music_System_for_the_Commodore_128_and_64"><em>COMPUTE!’s Music System for the Commodore 128 & 64</em></a>, this time with a companion floppy disk instead of type-in code.</p><p>The SIDPlayer system was a huge hit in the United States, and C64 owners produced thousands of songs and shared them on online services like <a target="_blank" href="https://en.wikipedia.org/wiki/Delphi_(online_service)">Delphi</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/Quantum_Link">Quantum Link</a>. Some SIDPlayer songs were written to be played on two SID chips simultaneously for a total of six simultaneous voices, made possible by either having two C64s, hacking a C64 to add a second SID chip, or using the <em>SID Symphony Stereo Cartridge</em> from Dr. Evil Laboratories. Today, this legacy lives on in the <a target="_blank" href="https://www.c64music.co.uk/">Compute!’s Gazette SID Collection</a> (CGSC). You can download the whole set to play on your C64 or MEGA65, or browse and play the collection in a web browser with the website <a target="_blank" href="https://deepsid.chordian.net/">DeepSID</a>.</p><p>LightTangent <a target="_blank" href="https://gitlab.com/fptech/rev-sidplayer">disassembled the original SIDPlayer program</a>, and used the findings to write SidPlay65. Many thanks to LightTangent for this ambitious project!</p><p>Full-color full-motion video demos by MirageBD</p><p>MirageBD has been researching methods for streaming full-color full-motion video from the SD card. So far, Mirage has produced two brilliant demos: <a target="_blank" href="https://files.mega65.org/?id=1b20b366-9177-4739-8420-c74f911a7202">HyperBallad</a>, the Björk music video masterpiece (1995), and <a target="_blank" href="https://files.mega65.org/?id=44fbe834-7f60-4134-956b-a2feff3eee34">Duel</a>, a scene from the movie <a target="_blank" href="https://www.imdb.com/title/tt0087197/"><em>Electric Dreams</em></a> (1984). Both demos launch from a D81 disk image, and stream data directly from a large file on the SD card.</p><p><strong>Important note:</strong> Running these demos requires a fast SD card, very likely an SD card <em>faster</em> than the one that was included with your MEGA65. As lydon explained on Discord, the bundled cards are optimized for a longer lifespan, at the expense of some speed. If these demos glitch out after the first couple of seconds, consider getting a SanDisk Ultra brand microSD card.</p><p>COPA65 by Bananzi</p><p>Ever wanted to copy and paste text in the MEGA65 screen editor? Now you can, with this clever extension by Bananzi! <a target="_blank" href="https://files.mega65.org/?id=d9a62fc3-6881-4116-b7f1-66110ded147a">COPA65</a> adds a text clipboard to the built-in editor experience, as well as both keyboard and mouse methods for selecting text.</p><p>With COPA65 installed, simply press <strong>Ctrl</strong> + <strong>C</strong> to wake it up, then press one of the command keys. For example, use the C command (press <strong>Ctrl</strong> + <strong>C</strong>, then press <strong>C</strong>) to set the start of a selection, move the cursor to the end of the selection, then use the C command again to copy the text. Finally, move the cursor to where you wish to paste, then use the V command.</p><p>Other commands can quickly select characters, words, and lines, and can insert pasted text instead of overwriting. See the detailed manual included with the download for instructions on installation and use.</p><p>COPA65 requires ROM beta version 920398 or later, which is when we formalized the extension mechanism being used. This is newer than the ROM included in release package v0.96. You can <a target="_blank" href="https://files.mega65.org/?ar=145591dd-deb6-4bd0-aa89-8e39cd021470">update to the latest ROM beta version</a>, or wait for the v0.97 release package, which hopefully will be out soon.</p><p>Really amazing work, Bananzi!</p><p>Midnight Mega by nobruinfo</p><p>Bruno (nobruinfo on Discord) has been working on a powerful file browser, which he calls <a target="_blank" href="https://files.mega65.org/?id=f3cc7335-48ad-4099-ae99-d870e5dfc156">Midnight Mega</a>. You can use Midnight Mega to browse your SD card, mount disk images, and view and copy files.</p><p>Midnight Mega is still in a beta testing release, and it is recommended to back up your data regularly. Please <a target="_blank" href="https://github.com/nobruinfo/midnightmega/issues">report any issues you find</a>, and join the discussion on the #midnight-mega channel of the MEGA65 Discord. Also note that it only supports disk images and the internal floppy drive; it does not yet support external IEC drives.</p><p>Gurce disassembles Sea Wolf</p><p>My series on disassembling <em>Crossroads</em> is directly inspired by Gurce, who recently disassembled another classic C64 game, <a target="_blank" href="https://en.wikipedia.org/wiki/Sea_Wolf_(video_game)"><em>Sea Wolf</em></a>. In this submarine battle game, you (and an optional second player) use paddle controls to maneuver submarines to fire missiles at battleships. The game’s lineage goes all the way back to the electro-mechanical arcade game <a target="_blank" href="https://en.wikipedia.org/wiki/Periscope_(arcade_game)"><em>Periscope</em></a> by Sega (1966), followed by a similar electro-mechanical version by Midway called <em>Sea Devil</em>. Midway launched a video arcade version under the name <em>Sea Wolf</em> in 1976. Commodore International produced a home version for the VIC-20 and C64 in 1982.</p><p>Gurce made two videos about his disassembly project. <a target="_blank" href="https://www.youtube.com/watch?v=WwZNy4HIL0k">Part 1</a> introduces the game and the project, and presents a few findings. The extended <a target="_blank" href="https://youtu.be/2CkLBIRiCV0?si=iKYhKNXchjm1WT4E">part 2</a> presents the entire project, with live demos and slides. You can read <a target="_blank" href="https://github.com/gurcei/petwolf/blob/main/SEA%20WOLF%20DISASSEMBLY.txt">Gurce’s complete notes</a> and <a target="_blank" href="https://github.com/gurcei/petwolf/blob/main/seawolf.asm">the final disassembly</a> on Github. With disassembly in hand, Gurce was able to modify the game to support four players, with two paddles on each of the two joystick ports.</p><p>Disassembling classic games is a great way to learn about programming for the C64 and the MEGA65. What game would you disassemble?</p><p>Featured Files Cornucopia!</p><p>muse has given us another arcade core! <a target="_blank" href="https://files.mega65.org/?id=fb977a9b-3979-4420-99f2-c683f52070b7">Stargate</a> is the 1981 sequel to the arcade classic <em>Defender</em>, a fast-paced horizontal shooter. As with other arcade cores, you will need to search for ROM data files and follow <a target="_blank" href="https://github.com/sho3string/StargateMEGA65_R3_R6">the installation instructions</a>. The core is available for both R3 and R6 mainboards.</p><p><a target="_blank" href="https://files.mega65.org/?id=e824b00d-706b-4d1c-a5e9-3ffd94e326cb">Fireplace</a> is a short BASIC demo by Urban Lindeskog, featuring PETSCII flames and crackling sound effects. Drag your MEGA65 out to the living room and run this for the holidays to keep your family warm.</p><p>RobH developed an <a target="_blank" href="https://files.mega65.org/?id=1775e66c-d8b5-4af4-9c00-4ca03a6e681e">example of sprite to character collision detection</a> in BASIC, then followed up with <a target="_blank" href="https://files.mega65.org/?id=f52f6ecf-3ad3-463b-87c4-77423b26b03b">a Lode Runner-like ladder climbing demo</a>. These demos show off how to implement several game mechanics with this technique, including a player sprite, walls, collectibles, ladders, and doors. Both include well-commented BASIC source code.</p><p><a target="_blank" href="https://files.mega65.org/?id=99494f19-0605-4e52-96a3-20fad28e221e">Alpha Burst</a> is a brief graphics-only demo by Drex, with brilliant colors and a borderless display. Run this on real hardware for full effect.</p><p><a target="_blank" href="https://files.mega65.org/?id=81fd9a5d-1ced-4e13-af78-5ba90c81de80">Disk Doctor Mega</a> by tundra/C is a low-level disk viewer and editor for both physical floppy disks and virtual D81 disk images. Inspect your disk tracks and sectors, and potentially recover data from damaged disks.</p><p><a target="_blank" href="https://files.mega65.org/?id=77e4a95b-cfc1-4170-9b3b-b1f27bcf8d8a">Unelite Part 1</a> by mk9 is a text adventure game with PETSCII graphics. Use the joystick to select options in this branching sci-fi narrative.</p><p>45GS02 Quick Reference, and other media</p><p>I brought a few gifts to the party as well. You can still <a target="_blank" href="https://www.zazzle.com/store/m65digest">buy the 45GS02 quick reference</a> as a mousepad or a poster. If you’d prefer a digital copy, you can now <a target="_blank" href="https://files.mega65.org/?id=ac9cf203-5276-430e-a491-dab7787ca79c">download the 45GS02 Quick Reference PDF</a> for free. I also uploaded the <a target="_blank" href="https://files.mega65.org/?id=b14f0473-5358-4460-b98f-4536dc732b36">BASIC65 Quick Reference PDF</a> from the User’s Guide for similar convenience.</p><p>When I took my MEGA65s to computer shows earlier this year, I made some paper items to keep at the table to help show it off. I have uploaded these designs to Filehost, in case anyone else wants to use them. The <a target="_blank" href="https://files.mega65.org/?id=1654a0b1-1117-4a9d-8a63-84830161f630">MEGA65 Conference Table standee design</a> is designed to be printed professionally on a 11" x 17" sign, and has facts and figures about the computer. The <a target="_blank" href="https://files.mega65.org/?id=c8143477-dded-470a-b719-a0a64c3e3e75">MEGA65 Demo Booklet</a> prints in landscape orientation on 8-1/2" x 11" paper, suitable for spiral binding on the top long edge, and features diagrams, screenshots, and very brief instructions intended for someone unfamiliar with the computer to try it out in just a few minutes. Accompany this with an SD card pre-loaded with the mentioned disk images for full effect.</p><p>Here we are wrapping up another calendar year! I am grateful for everyone who has supported this newsletter over the previous two years, both with recurring donations and with kind words. If you haven’t already, please consider setting up a recurring donation to keep this resource sustainable. Visit: <a target="_blank" href="https://ko-fi.com/dddaaannn/">https://ko-fi.com/dddaaannn/</a></p><p>Have a great holiday! See you next year.</p><p>— Dan</p><p>Santa called his elves togetherTo soup up his old sleighSo Rudolph and the other reindeerCould rest on Christmas day</p><p>He’s got a million miles to travelAnd to do it in one dayAnd that’s why Santa ClausHas a souped-up Santa sleigh</p><p>Got a rocket burnin’ mighty quickTurnin’ Santa’s souped-up sleighComes in like a streak of lightAnd it goes out the same way</p><p>When you hear that rocket roarYou know Santa’s on his wayBut he’ll be back again next yearIn his souped-up Santa sleigh</p><p>— “Santa’s Souped-up Sleigh,” <em>from the film</em> Melvin & Howard, <em>dir. Jonathan Demme</em></p><p></p> <br/><br/>Get full access to Dan’s MEGA65 Digest at <a href="https://m65digest.substack.com/subscribe?utm_medium=podcast&#38;utm_campaign=CTA_4">m65digest.substack.com/subscribe</a>
play-circle icon
11 MIN
Disassembling Crossroads, part 1
NOV 15, 2024
Disassembling Crossroads, part 1
<p>One of my all-time favorite games for the Commodore 64—and I know I’m not alone in this—is <em>Crossroads,</em> the single-screen maze shoot’em’up by Steve Harter, published in <a target="_blank" href="https://en.wikipedia.org/wiki/Compute!%27s_Gazette">Compute!’s Gazette magazine</a> as a type-in program in December 1987. The game features dozens of enemies of a variety of types and colors, all fighting each other in a cacophony of attacks and explosions. You’re dropped into the fray to collect items called “spars,” which provide you some protection against attacks, and which the enemies also consume. The game supports one or two players on joysticks, and both players battle for survival simultaneously.</p><p>Some people like to say that typing in programs from magazines and books helped them learn how to write programs of their own. I can see how that might be true for BASIC programs, though I can’t honestly say I learned anything from type-ins when I was in grade school. For programs written in languages other than BASIC, Compute! offered no way to learn. In <a target="_blank" href="https://web.archive.org/web/20231231051645/https://kirk.is/2006/04/13">this interview with Steve Harter</a> by Kirk Israel, Steve says he wrote <em>Crossroads</em> in assembly language, but Compute! never published assembly language listings for full programs in magazines. Instead, Compute! published such programs as columns of numbers, along with a helper program that assisted with keying these values directly into memory. The most you could learn from these type-ins was data entry, and perseverance.</p><p>(As an aside: I’m aware of only two cases where Compute! published full assembly language program listings for the C64, both as books: the <a target="_blank" href="https://archive.org/details/sboml">LADS assembler</a> and the <a target="_blank" href="https://archive.org/details/Computes_Speedscript">SpeedScript word processor</a>. Steve wrote <em>Crossroads</em> using LADS.)</p><p>Over the next two issues of this Digest, we’ll crack open the original Crossroads program and see what we can learn, using two modern reverse engineering tools for your PC. This month, we’ll take a look at <a target="_blank" href="https://github.com/slajerek/RetroDebugger">Retro Debugger</a>, a C64 emulator with real-time memory visualization features. To keep this newsletter to a reasonable length (😬) we’ll discuss just enough to get started, and ask a few specific questions of interest about the game.</p><p>As always, let us begin with some MEGA65 news!</p><p>New Filehost feature: high score tables</p><p>Filehost has a fun new feature for competitive MEGA65 gaming: high score tables! When you upload your game to Filehost, you can choose to enable “Highscore submission.” This allows players to submit their high scores by clicking the plus ("+") button on your game’s Filehost detail page, uploading a screenshot as evidence. All score submissions must be approved by you before appearing on the page. You will receive a message when a player submits a score for your game.</p><p>Check out <a target="_blank" href="https://files.mega65.org/?id=3549b82b-b851-41ec-a8d9-918996a4d2ea">the high score table on Classy</a> as an example.</p><p>Thanks as always to Tayger for the Filehost innovations! Everyone go out and rack up those high scores!</p><p>Galaga, Ghosts’n’Goblins, and Xevious now available for R6 boards; TI-99/4A now available for R3 boards</p><p>Over the last year or so, muse has given us alternate cores for the arcade games <a target="_blank" href="https://files.mega65.org/?id=8bc248e3-c29c-4ba8-b8c3-6018a995a9ea">Galaga</a>, <a target="_blank" href="https://dansanderson.com/mega65/crossroads-part-1/(https://files.mega65.org?id=e563df76-e12f-47de-9bb2-cca4ebe1e18d)">Ghosts’n’Goblins</a>, and <a target="_blank" href="https://files.mega65.org/?id=d32474e9-6f30-48f8-bba3-167cad4bbc4f">Xevious</a>, originally released for the R3 mainboard. Now, thanks to Robert Jaremczak (rjaremczak), there are R6 versions for these cores: <a target="_blank" href="https://files.mega65.org/?id=1672149c-66d3-4df7-9128-e9c83095c49a">Galaga R6</a>, <a target="_blank" href="https://files.mega65.org/?id=f66965dc-4006-4ebe-8fde-eed9bc60d3aa">Ghosts’n’Goblins R6</a>, and <a target="_blank" href="https://files.mega65.org/?id=c67076de-8dd5-4877-8c95-7a01d2cae441">Xevious R6</a>. See the original installation instructions for the R3 cores, which also apply to the R6 versions.</p><p>zeldin has updated the <a target="_blank" href="https://kugelblitz360.github.io/m65-altcores/computer-cores.html#ti-994a">TI-99/4A core</a> several times since its initial release, and as of version 1.3, the core is available for the R3 mainboard as well as R6. <a target="_blank" href="https://files.mega65.org/html/main.php?id=a25ce133-ed07-4ef7-8495-179d69c43ed0">Go grab the latest</a>, and be sure to <a target="_blank" href="https://github.com/zeldin/Mega99/issues">file any bugs you find</a>.</p><p>I had a few people respond to <a target="_blank" href="https://dansanderson.com/mega65/up-up-down-down/">last’s month’s Digest</a> to point out that core availability is currently a sticking point with regards to mainboard revisions, with some cores only available for R3 and others only for R6. Core developers must put in additional effort to support both mainboards, and not everybody owns both boards for testing. If you’re working on a core and need assistance building it for a board revision that you do not own, please reach out to the MEGA65 community on Discord or by email. We will eagerly connect you with resources for building and testing your core on both revisions.</p><p>Thank you Robert and zeldin for working on cores!</p><p>Last call for R3 Real-Time Clock replacements (Grove RTC)</p><p>Back in 2022, we noticed that a small but significant percentage of R3 mainboards had faulty Real-Time Clock (RTC) chips. Paul quickly put together a workaround involving a core update and an <a target="_blank" href="https://www.aliexpress.us/item/2251832636105970.html?algo_pvid=26a281a9-a207-475f-9c56-de8ce11cea57&#38;algo_exp_id=26a281a9-a207-475f-9c56-de8ce11cea57-0&#38;pdp_ext_f=%7B%22sku_id%22:%2210000000337849443%22%7D&#38;pdp_npi=2@dis!USD!2.27!2.0!!!!!@2101e9d116652918520047406e6ac3!10000000337849443!sea&#38;curPageLogUid=S6c2J0uTS2Tp&#38;gatewayAdapt=4itemAdapt">inexpensive RTC breakout board</a> and <a target="_blank" href="https://core-electronics.com.au/grove-4-pin-male-jumper-to-grove-4-pin-conversion-cable-5-pcs-per-pack.html">Grove connector</a>. This requires a soldering iron to put together, but no expertise: it’s just four wires. Nevertheless, I wanted to make sure that everyone who needed one could get one easily, so I built a bunch of them and <a target="_blank" href="https://files.mega65.org/?ar=ff484da0-d942-4e9b-adf1-3b5a77acaa25">made them available for the cost of shipping</a>. The MEGA65 team also supported this effort financially out of their own pockets.</p><p>I will be ending my distribution offer at the end of 2024. I have about a dozen units remaining, and am willing to send them out to anyone who needs them. If you have an R3 mainboard and believe your Real-Time Clock is faulty, please follow <a target="_blank" href="https://files.mega65.org/?ar=ff484da0-d942-4e9b-adf1-3b5a77acaa25">these instructions for testing your RTC and requesting a unit</a>. I will email you with instructions to send me the shipping cost by PayPal, then get one out to you, while supplies last.</p><p>Please do not request one if you don’t need one. Only a fraction of the MEGA65s delivered in 2022 have this issue. Follow the instructions to test your MEGA65 before requesting a replacement. If you discover you need one later than the end of this year, consider ordering the parts and cooking one up yourself. These are easy to build!</p><p>The sega-adapter is great actually</p><p>This isn’t news so much as just boasting, but last month I mentioned <a target="_blank" href="https://github.com/eyvind/sega-adapter/tree/master">the sega-adapter project</a> as a fun way to connect Sega Genesis-style game controllers to Commodore computers. Since I sent newsletter, I had some boards printed, got the parts together, and assembled a few. Chat, I can heartily recommend it, especially when used with the <a target="_blank" href="https://www.8bitdo.com/retro-receiver-genesis-mega-drive/">8bitDo Retro Receiver for Sega Genesis</a> (<a target="_blank" href="https://www.amazon.com/8Bitdo-Retro-Bluetooth-Receiver-Original-Genesis/dp/B07MSWGSJY">$16 on Amazon</a>). The 8bitDo Retro Receiver pairs with almost any modern Bluetooth game controller, including Nintendo, Playstation, and older Xbox controllers (but not newer Bluetooth LE Xbox controllers). 8bitDo also makes a Bluetooth Sega Genesis gamepad; be sure to get the <a target="_blank" href="https://www.amazon.com/dp/B07MSN1NPC">M30 Bluetooth model</a>, not the “M30 2.4G wireless” model. I got my Nintendo Switch Pro controller to be a 3-button game controller for my MEGA65!</p><p>The sega-adapter is a pretty simple project, with the following parts:</p><p>* A 9-pin male connector, for the incoming Sega Genesis controller signal (such as the 8bitDo Retro Receiver)</p><p>* A PIC microcontroller</p><p>* A capacitor</p><p>* Header pins, and a “pigtail” cable for the 9-pin female connector that goes to the MEGA65 (or what have you)</p><p>* Optional header pins and jumper to switch between C64 and Amiga modes—or you can just use solder to set it to C64 mode permanently</p><p>That’s it. If you buy <a target="_blank" href="https://github.com/eyvind/sega-adapter/tree/master/kicad#bom">the exact parts recommended by the project</a>, everything goes together using a soldering iron, and something to apply crimping force to the pigtail’s ribbon cable. You also need an inexpensive PIC microcontroller programmer such as a generic “PICKit3” device; I bought one for <a target="_blank" href="https://www.amazon.com/dp/B07PHPBP3Y">$33 on Amazon</a>. I got the boards from <a target="_blank" href="https://oshpark.com/">OSHPark</a> and parts from <a target="_blank" href="https://www.digikey.com/">Digikey</a>, for a total unit cost of about $16 each for a batch of ten adapters. The recommended 9-pin connectors were the most expensive parts, and you might be able to find cheaper ones in different form factors.</p><p>I’d never worked with PIC microcontrollers before! For software, I only needed the free version of <a target="_blank" href="https://www.microchip.com/en-us/tools-resources/develop/mplab-x-ide">Microchip MPLAB X IDE</a> and the <a target="_blank" href="https://github.com/eyvind/sega-adapter/releases">pre-built release of the sega-adapter .hex file</a>.</p><p>To program the PIC, put it on a breadboard, then connect five of the wires of the PICKit3 to pins of the PIC, as described in the pinout diagrams (which I’m including below). Leave the sixth wire disconnected. You also need to apply about 5 volts of DC power across the PIC power pins. The PICKit3 does <em>not</em> supply power the microcontroller, and it needs to be powered to accept programming. You can use a little battery box, a wall wart of appropriate voltage, or a bench power supply.</p><p>I’m <em>not</em> selling these, I’m just showing off. It was a fun afternoon project, with a satisfying result, and because I made ten I have my holiday gifts all sorted.</p><p>Playing Crossroads</p><p>The first step to reverse engineering anything is to understand what the thing does. We can learn a lot about <em>Crossroads</em> just from playing it.</p><p><a target="_blank" href="https://archive.org/">Archive.org</a> has complete scans of Compute!’s Gazette magazine, and <em>Crossroads</em> is in <a target="_blank" href="https://archive.org/details/1987-12-computegazette">issue 54, December 1987</a>. An amusingly nostalgic way to acquire the <em>Crossroads</em> program would be to enter the “MLX” data entry program listed in the magazine, then use MLX to enter the 6,676 hexadecimal numbers for the game. (That’s 5,935 program bytes, plus error checking digits.) I recommend simply downloading <a target="_blank" href="https://commodore.software/downloads/download/732-compute-s-gazette-associated-disks/15337-compute-s-gazette-all-disk-images">the Compute!’s Gazette cover disk image archive</a>. The disk image for the December 1987 issue is named 1987-12.d64. This disk image works great with the C64 core for the MEGA65. (Alas, I could not get it to run in GO64 mode. Maybe later we can figure out why.)</p><p>We can learn some useful things about Crossroads even before we run it. If we browse the disk directory, we can see that there are many files from this issue of the magazine, but the game likely consists of a single PRG file named CROSSROADS.</p><p>LOAD "$",8 LIST</p><p>We can load this file from disk into memory, using the ,8,1 arguments to LOAD to tell it to use whatever memory start address that CROSSROADS prefers:</p><p>LOAD "CROSSROADS",8,1</p><p>The program loads, and we’re back at the READY. prompt. Because the game didn’t do anything fancy to start automatically, we can guess that the program has loaded to the start of BASIC memory, and probably begins with a BASIC bootstrap program that invokes the machine code, like <a target="_blank" href="https://dansanderson.com/mega65/cross-development/">we’ve done for our own programs</a>. Let’s confirm this:</p><p>LIST</p><p>Sure enough, there is a one-line BASIC program in memory:</p><p>10 SYS2300</p><p>Connect a joystick to port 2 (first player), then start the program with the RUN command. The game starts without any further disk activity, which confirms our hypothesis that this is a single-file game.</p><p>If you’ve never played <em>Crossroads</em> before, take some time to enjoy it! Shoot bullets at monsters by pressing the fire button, and collect the white spinning “spars” to gain shields and progress to the end of the level. Connect a second joystick and invite a friend!</p><p>Observing the game</p><p>As you play, try to make some guesses about how the game works, and come up with some questions you would like answered. Your own questions and hypotheses will guide your reverse engineering process.</p><p>Here are just a few things I noticed that might be worth exploring:</p><p><strong>Program states.</strong> The game starts with an “attract mode” where a bunch of enemies duke it out on a maze without a player present, and with a scrolling message across the top of the screen. Like many vintage arcade games, attract mode appears very similar to gameplay, and likely reuses the game’s logic with minor changes. The game starts the first level when the player presses the fire button. Each level starts with an introductory animation where creatures appear with special graphical and sound effects. The players are the last to arrive. Then play begins. A level ends when a player collects a number of spars, at which point the game pauses until a key is pressed, and the game restarts at the next level. The game ends when both players are out of lives.</p><p><strong>Creature properties.</strong> Creatures and players have a number of shields that protect them from attacks. Each attack deducts a shield, and the creature is destroyed when attacked without shields. A creature or a player gains a shield by picking up a spar. The player’s shield count appears at the top of the screen, under the “S.” Other creatures also have shield counts, but these are not visible. Player actions are controlled by joystick inputs; creature actions are controlled by algorithms. Each creature is of one of nine types, and the type describes their action patterns, reactions to collisions with bullets and other creatures, and the initial number of shields.</p><p><strong>Character graphics.</strong> The maze and the creatures appear to occupy a grid in the same shape as the C64’s 40 x 25 character mode, and every element appears to be the size of a single character. It’s likely that at least some of these graphical elements are using VIC-II character graphics, where the glyphs of some letters, numbers, and symbols in the PETSCII typeface have been replaced with these designs. Each element is of a single color and high resolution, 8 x 8 pixels per character.</p><p><strong>Creature half-steps.</strong> Even though creatures are the size of a single grid tile, they appear to traverse the screen in half-tile steps! If creatures are implemented with character graphics, the game must be doing something interesting to allow a creature to appear this way.</p><p><strong>Sprites.</strong> There appear to be too many creatures and bullets on the screen at one time for the game to be using the eight VIC sprites to draw them. While advanced techniques like sprite multiplexing (which we <a target="_blank" href="https://dansanderson.com/mega65/racing-the-beam/">discussed previously</a>) could use sprites to draw more than eight objects at a time, there’s nothing in the design of this game that prevents more than eight objects from appearing on the same scan line, so this seems unlikely. However, there is an explosion effect that occurs when a creature takes damage, and this appears to overlay the character graphics. This suggests that this effect might be done with sprites.</p><p><strong>Sound.</strong> The soundscape of <em>Crossroads</em> consists entirely of sound effects that represent activity on the screen: creatures appearing at the start of the level, player bullets firing, enemy bullets firing, shields absorbing damage, creatures and bullets being destroyed, and spars getting collected. There’s so much going on early in the level that each sound may be difficult to pick out, and it’s a bit easier after the screen is mostly clear. I’ll be interested to see how sounds are allocated to the three SID channels, especially when there are more than three events causing sound at a time.</p><p>In <a target="_blank" href="https://web.archive.org/web/20231231051645/https://kirk.is/2006/04/13">that interview with the developer</a> that I mentioned earlier, Steve confirms that the creatures use character graphics, and the explosions use sprites. Steve also mentions that the sprite images for the explosion animations are generated randomly.</p><p>Examining the PRG</p><p>We want to use modern PC tools to examine the program, so we need to extract the PRG file from the disk image. Graphical tools like <a target="_blank" href="https://style64.org/dirmaster">DirMaster</a> (Windows only) or <a target="_blank" href="https://droid64.sourceforge.net/">DroiD64</a> (Java, multi-platform) work nicely, or you can use the c1541 command included with the <a target="_blank" href="https://vice-emu.sourceforge.io/">VICE emulator</a>:</p><p>c1541 1987-12.d64 -read crossroads crossroads.prg</p><p>You can use a tool called a <em>hex viewer</em> to examine the bytes of the PRG file. I like a terminal-based hex viewer called <a target="_blank" href="https://github.com/sharkdp/hexyl">hexyl</a>, and there are many others to choose from. We won’t spend more than a minute staring at raw bytes, but we can use this to get our bearings. Here are the first few dozen bytes of the PRG file:</p><p>00000000 01 08 0b 08 0a 00 9e 32 33 30 30 00 00 00 00 00 |.......2300.....| 00000010 44 aa aa 11 00 00 00 00 11 aa aa 44 00 00 00 00 |D..........D....| 00000020 00 3c 3c 00 00 00 00 00 00 3c 3c 00 00 00 38 38 |.<<......<<...88| 00000030 30 7f be 68 ce ec 38 38 30 7f 76 30 30 38 ff 8f |0..h..880.v008..| ...</p><p><a target="_blank" href="https://dansanderson.com/mega65/cross-development/">As we’ve seen before</a>, a PRG file starts with two bytes that specify the load address for the program. In this case, the first two bytes are $01 and $08, specifying the Commodore 64 BASIC start address of $0801 hexadecimal, or 2049 decimal. The PRG address bytes are not written to memory, they only tell the BASIC command LOAD "CROSSROADS",8,1 where to put the rest of the data.</p><p>The subsequent bytes describe the one-line BASIC program we saw earlier:</p><p>* $0b $08: The address of the next line. In this case, it’s the end-of-program marker: $080b.</p><p>* $0a $00: The line number. $000a = 10 decimal.</p><p>* $9e: The C64 BASIC token for SYS.</p><p>* $32 $33 $30 $30: PETSCII for 2300.</p><p>* $00: End of line.</p><p>* $00 $00: End of program. If you count from $0801, you’ll see this is at address $080b, from the first bytes of the first line.</p><p>These 12 bytes start at address 2049, which means the rest of the program data starts at address 2061 ($080d). Interestingly, the SYS command uses address 2300 ($08fc). The data starting at address 2061 might be code, or it might be something else. We don’t know yet. We only know that the byte at address 2300 is the beginning of a machine code instruction, and that it’s the first instruction executed by the program.</p><p>It’s amusing to compare this hex dump to the listing in the magazine. (Well I think it’s amusing.) Note that Compute!’s Gazette program listings have nine bytes on a line, but only the first eight bytes are part of the program. The ninth byte is a <em>checksum</em>, which the MLX program uses to verify that you entered the line correctly. If it didn’t do this, entering these programs would be a nightmare, as opposed to merely a nuisance.</p><p>Introducing Retro Debugger</p><p>If programming is the art of telling a computer what to do, debugging is the art of figuring out why it’s not doing what you meant. One of the best ways to do that is to peek inside the computer’s memory as it steps through your instructions, and try to line up the evolving state of the computer with your own mental model. This process is often so opaque and frustrating that I sometimes wish I could just rip the top off the chips and look inside as the program is running. Thanks to high fidelity emulators running on modern computers, this fantasy is now a reality.</p><p><a target="_blank" href="https://github.com/slajerek/RetroDebugger">Retro Debugger</a> by Marcin Skoczylas is an emulator for the C64, Atari XL/XE, and Nintendo Entertainment System, with some powerful real-time debugging tools. As the emulator runs, you see the C64 screen in one window, and use other windows to render the memory in different useful ways: as hex values, as machine code instructions, as graphics in common VIC-supported formats, and as a color-coded memory map. All of this is updated as the emulation runs at full speed, and you can pause execution and manipulate system state as a program runs.</p><p>Let’s use Retro Debugger to inspect <em>Crossroads</em>, and follow up on a few of our assumptions about how the game does graphics.</p><p>Setting up Retro Debugger</p><p><a target="_blank" href="https://github.com/slajerek/RetroDebugger/releases">Download the latest Retro Debugger release</a> for your platform (Windows, macOS, or Linux). You also need the original C64 ROM and 1541 DOS code. Retro Debugger opted not to include these in the distribution, but you can get them directly by installing the <a target="_blank" href="https://vice-emu.sourceforge.io/">VICE</a> emulator. You’ll have to dig around the VICE folder for the appropriate .bin files. On my Mac, I found them here:</p><p>./VICE.app/Contents/Resources/share/vice/C64/ ./VICE.app/Contents/Resources/share/vice/DRIVES/</p><p>Retro Debugger needs the ROM files to be in a single folder, with specific filenames. Create a new folder for these (such as inside the Retro Debugger folder), make duplicates of the files from VICE, and rename them as shown:</p><p>* .../C64/basic-901226-01.bin -> basic</p><p>* .../C64/chargen-901225-01.bin -> chargen</p><p>* .../C64/kernal-901227-03.bin -> kernal</p><p>* .../DRIVES/dos1541-325302-01+901229-05.bin -> dos1541</p><p>* .../DRIVES/dos1541ii-251968-03.bin -> dos1541II</p><p>When you start Retro Debugger for the first time, you need to tell it where to find the ROM files. Open the Settings menu, select C64, then Select C64 ROMs folder. Navigate to the folder you created with the ROM files in it. Retro Debugger loads the ROMs and starts the emulation. If it complains, make sure the ROM files are in the right place and have been renamed as expected.</p><p>Behold, the insides of the C64! You can see the CPU bouncing around the instructions for blinking the cursor at the READY prompt, and all of the memory and register updates that go with it. With the “C64 Screen” window active, you can interact with the C64 as you would with VICE, typing BASIC commands and whatnot.</p><p>Retro Debugger starts with some of its tools visible, but there are many more. With the cursor still at the READY prompt, open the VIC Editor menu, and select C64 Charset. The C64 Charset window opens. At this point, you should see what the VIC is currently using for its character set, which at the moment is standard C64 PETSCII. Resize the window to make the characters easier to see.</p><p>On my computer, I need to make the text bigger to be useful. Some windows, like the C64 Screen and Charset windows, have fixed-sized content, and you can drag the window corners to resize. In other windows, to increase the text size, right-click on the window, then adjust the Font Size slider. These windows can also be resized to display more information. The app will remember your window layout between sessions.</p><p>Retro Debugger is based on VICE, and has all of its debugging features. To pause the emulator, press <strong>F10</strong> (or open the Code menu, then select Pause). While paused, press <strong>F10</strong> repeatedly to advance by one instruction at a time. Press <strong>F11</strong> to resume full speed. You can also set <em>breakpoints</em> on instructions, set <em>watchpoints</em> on memory locations, and can navigate to instructions that access specific memory addresses. You can even rewind the emulation to the instruction that last accessed a memory address.</p><p>For more information on features and keyboard shortcuts, see <a target="_blank" href="https://github.com/slajerek/RetroDebugger/blob/master/docs/README-C64-65XE-NES-Debugger.txt">docs/README-C64-65XE-NES_Debugger.txt</a>, included with the program.</p><p>Playing Crossroads in the emulator</p><p>There are two ways to get <em>Crossroads</em> running in the emulator. One method is to open the D64 disk image, then type the BASIC commands to load and run the game, as you would on a C64. Because <em>Crossroads</em> is a single PRG file, you can also just open the PRG file that we extracted earlier. Opening the PRG is often faster, especially if you need to reset the program.</p><p>Open the File menu, then select Open. Select the crossroads.prg file. This will load and run the game immediately, so prepare your speaker or headphones volume for the game’s violent introduction.</p><p>Next, open the Settings menu, then Joystick #2, and select a configuration for the joystick. With the joystick set to “Keyboard,” the cursor keys move the stick, and the right Alt key is the fire button. Or you can connect any PC-compatible game controller. If a controller is connected, its device name will appear in the menu.</p><p>Select the C64 Screen window, then press fire to start a game. Good luck!</p><p>Investigating character graphics</p><p>We have a hypothesis about how <em>Crossroads</em> uses character graphics. Let’s see if we can confirm this hypothesis in Retro Debugger.</p><p>When you started the game, it installed a new character set and told the VIC to use it. The Charset window now shows new graphics tiles: a limited set of PETSCII letters and numbers, and nearly all of the graphics for the game. You can see four types of maze wall, the “spar,” and various images for each of the creature types and bullets facing all four directions. Each of these are unique <em>tiles</em> of 8-by-8 pixels, and the tiles can be placed anywhere on the 40-by-25 tile grid.</p><p>We’ve made a discovery! The spar appears to be animating directly inside the Charset window! While <em>Crossroads</em> animates creatures using multiple static tile definitions, it animates the spar simply by continuously updating its single tile definition. This conserves charset tiles, at the expense of some CPU time.</p><p>If we squint, we can start to see how the game achieves its “half step” effect for creatures. When a creature is standing fully on a tile position, it is drawn as a single tile based on which direction it is facing. When a creature is walking between two tile grid spaces, it occupies both space, with a tile for each half of the image. There is a tile pair for each of the four directions. Each creature has two animation frames, and it appears that <em>Crossroads</em> stores both frames as single tiles, and uses only the second frame for the half-step tiles, for a total of 16 tile definitions per creature.</p><p>How the VIC finds character sets</p><p>The Charset window determines the memory location of the character set data that the VIC is using based on hardware registers, then draws the data it finds as characters. We can use some Commodore 64 knowledge to figure out where in memory this character set is stored.</p><p>The way the VIC-II accesses memory is <a target="_blank" href="https://www.c64-wiki.com/wiki/VIC_bank">a little bit complicated</a>. The VIC can only access one of the four 16 KB banks at a time. Additionally, the C64 architecture makes a special accommodation so the VIC can access the PETSCII character set from an upper bank of ROM even when a lower bank is selected. This configuration for how the VIC sees memory is managed by the second of the C64’s two CIA chips. This is controlled by the lowest two bits of the CIA data register at $DD00.</p><p>In Retro Debugger, select the C64 Memory window. With this window selected, you can use either the Page Up/Page Down keys or your mouse’s scroll wheel to browse memory. You can also jump directly to an address by pressing Ctrl+G (or on macOS, Command+G), then typing the address in hexadecimal. Use this to jump to the register address $DD00.</p><p><strong>Tip:</strong> Be careful what you type when the Memory window is active. If the cursor is on a memory value, typing hexadecimal digits will modify memory. When you type Ctrl+G (or Command+G) to go to an address, double-check that the cursor has moved into the address column before typing the address.</p><p>With <em>Crossroads</em> running, the register at $DD00 is set to $C7, so the lowest two bits are %11. According to <a target="_blank" href="https://www.c64-wiki.com/wiki/VIC_bank">C64 technical documentation</a>, this points the VIC at bank 0, addresses $0000-$3FFF. It also tells the VIC to see the PETSCII character set at addresses $1000-$1FFF, hiding the RAM at these addresses from the VIC. This only hides the RAM from the VIC, not the CPU.</p><p>Still in the C64 Memory window, jump to register <a target="_blank" href="https://www.c64-wiki.com/wiki/53272">$D018 (53272 decimal)</a>. This register tells the VIC where to find screen memory within the selected bank, and where to find the character set. With the game running, this appears to be set to $19. This value is interpreted as follows:</p><p>* $19 = %0001 1001</p><p>* The upper four bits specify the location of screen memory, as a multiple of 1024 ($0400) bytes. %0001 = 1, so screen memory starts at address $0400. This is an offset from the beginning of the selected bank, and in this case the bank is 0, so the final address is $0400.</p><p>* The next three bits specify the location of character memory, as a multiple of 2048 ($0800) bytes. %100 = 4, so character memory starts at address $2000.</p><p>* The last (least significant) bit is ignored.</p><p>Be aware that the character memory offset gets described in manuals and online resources in different ways. I just described it the way the <a target="_blank" href="https://www.c64-wiki.com/wiki/53272">C64 wiki</a> does: a three-bit number times 2048. Other books, including the MEGA65 manual, describe it as the upper three bits of a four-bit number whose last bit is 0, times 1024. The math works out the same either way.</p><p>With the selected CIA configuration, a program could tell the VIC to use the PETSCII character set from ROM by setting the three bits to %010 = 2 times 2048 = address $1000. <em>Crossroads</em> tells the VIC to look at $2000 instead, which is RAM where Crossroads can install its custom character set.</p><p>Let’s confirm our understanding. In the C64 Memory window, go to address $2000.</p><p>The C64 Memory window doesn’t know what the values in memory mean, but it tries to help us out by displaying them in four different ways: as hex bytes, as PETSCII characters, as character graphics data, and as sprite graphics data. In this case, we’re looking at character graphics data, so that view makes the most sense, and the other views are mostly nonsense. Scroll down to address $21F8 to see the spar glyph data being animated by the program.</p><p>Cheating at Crossroads</p><p>The C64 Memory window lets us peek into the computer’s memory as it is running, and also lets us change memory as we like. If we knew where to look, we could change properties of the game, such as the number of lives the player has. So how do we know where to look?</p><p>Locating variables is such a common task that the debugger has a tool just for this. Open the C64 menu, then select the C64 Memory Monitor. (This is a new tool, not the C64 Memory window that we’ve been using.) Resize this innocuous-looking little window to make it bigger.</p><p>Start a new single-player game by pressing the fire button on the joystick configured for port #2. The level clears, creatures spawn in, and finally the player arrives.</p><p>The player starts with 4 lives. We can know for sure that somewhere in the computer’s memory is a representation of this value, and this representation will change when the player loses a life. We don’t know where it is, or how the value is represented.</p><p>Let’s take a guess that the number of lives is stored as a byte, encoded as a non-negative integer. In other words, if we search the computer’s memory for a value of 4, there’s a chance that this might be how it stores the number of lives. This is just a guess! We can start with this, and refine our guess if it doesn’t work out.</p><p>With the emulation still running, in the C64 Memory Monitor, click the Capture button. Retro Debugger takes a snapshot of all of memory, and a giant list of memory addresses and values appears. Next, set the filter settings:</p><p>* Check the box next to “Changed.” The list updates to show only the memory that differs from the captured snapshot in the current state of the emulation.</p><p>* Check the box next to “Matches prev.” Click the value box, type 04, then press <strong>Enter</strong>. (It’s important to press <strong>Enter</strong> in this field, or the value won’t stick.) The Memory Monitor now lists all of the memory locations that were set to $04 when you clicked the Capture button, but currently contain something else.</p><p>* Finally, check “Matches current,” and set its value to $03.</p><p>The list narrows to just the memory addresses that were 4, and are now 3. You may see more than one row, but likely only a few. Of all 65,536 memory addresses in the computer, these are the only ones that meet the criteria. This list updates in real-time as the emulation runs, and some rows will flicker in and out as memory changes.</p><p>Select the C64 Screen window again, and use your gamepad or the keyboard to move the player into harm’s way until they run out of shields and lose a life. The number of lives shown in the top display reduces to 3. Press <strong>F10</strong> to pause the emulation.</p><p>One of the addresses that meet the filter criteria in the Memory Monitor is $0011. Let’s take another guess that this is player 1’s life count. This is a good guess for at least two reasons. It’s an address in the Zero Page (addresses $0000-$00FF), which is a common place to put variables. It’s also the only row that doesn’t flicker while the emulation is running.</p><p>On the row showing address $0011, click the “Memory” button. This updates the C64 Memory window to highlight that location. As expected, its value is currently $03. Now change this value: select the Memory window, then type 07. Press the <strong>F11</strong> key to unpause the emulator.</p><p>Hmmm, the number of player lives on the screen still shows “3.” Was our guess incorrect? Try killing off the player one more time. Success! The life count now reads “6,” one less than the value we set. Double-check that the value at address $0011 is now $06.</p><p>When we dig deeper into the machine code next month, we should expect to find instructions that manipulate address $0011, and can probably assume that the code is related to the number of lives of player 1. We can use that information and some inductive reasoning to determine the purpose of the surrounding code, and figure out the rest of the program.</p><p>We got a bit lucky with our guesses in this example, though truthfully many games store the number of player lives this way. What if our guesses were wrong, and the number of lives wasn’t stored as a non-negative integer in a byte value? One possible strategy would be to locate the code that updated the “4” on the screen to a “3.” We could use the Memory Monitor against the screen codes for those characters, or we could locate the screen memory address and ask Retro Debugger to tell us which instruction last changed it. It might be possible to figure out from nearby code where it reads the value that it displays, and how the value is interpreted.</p><p>More things to try</p><p>Retro Debugger comes packed with plenty of toys for messing with the state of the emulator. Browse the menus and experiment! Most menu items open a new window with interesting features. Here are just a few ideas.</p><p><strong>Locate that first instruction.</strong> Recall that the BASIC bootstrap invokes the machine code at address 2300, or $08FC in hexadecimal. Pause the emulator by pressing <strong>F10</strong>. Select the C64 Disassembly window, type Ctrl+G (or Command+G for macOS) to go to address $08FC. We can see that the first few instructions initialize some hardware registers: $D40E, $D40F, $D412. You can look up these addresses in <a target="_blank" href="https://sta.c64.org/cbm64mem.html">C64 technical documentation</a> to see what they do. Researching all of the code this way is a bit tedious, but it’s fun to see the code sitting right there in memory. We’ll use a more powerful tool for investigating this code in next month’s Digest.</p><p><strong>Watch the SID chip make sound.</strong> Open the C64 menu, then the C64 SID sub-menu, then the C64 SID tool. The C64 SID window opens, showing information about the SID chip’s three sound voices. (Check out <a target="_blank" href="https://dansanderson.com/mega65/sounds-of-the-sid/">one of the earliest Digest issues</a> for an introduction to the SID chip.) Keep this window open, play the game for a bit, and watch the SID waveforms as the enemies duke it out.</p><p><strong>Draw on the screen.</strong> Open the VIC Editor menu, and select Show VIC Editor. This window resembles the screen, and by default shows the tile grid and the pixel grid. This is a powerful tool for updating the VIC data in real time, and there’s quite a bit of documentation of its features in <a target="_blank" href="https://github.com/slajerek/RetroDebugger/blob/master/docs/README-C64-65XE-NES-Debugger.txt">the text file</a>. For now, select the C64 VIC Editor window, then left-click on an empty space on the <em>Crossroads</em> maze. It fills in with a character. Try making a wall of characters in the maze. Another discovery! The characters block the path of creatures, and the player! It is likely that the game code reads screen memory directly to detect whether a creature is adjacent to a wall.</p><p><strong>Watch for sprites.</strong> The VIC Editor highlights sprites with a red box. If you zoom out in this window with the mouse scroll wheel, you can see that <em>Crossroads</em> keeps the sprites off screen when not in use. Play the game to cause explosion effects as shields and creatures are destroyed. Notice that the red boxes appear around the explosions in progress, then retreat out of view when no longer needed.</p><p>We’ve only scratched the surface of what Retro Debugger can do, and we’ve already learned quite a bit about how <em>Crossroads</em> works. We’ll be able to apply this knowledge as we start investigating the code.</p><p>Next month, we’ll introduce <a target="_blank" href="https://ghidra-sre.org/">Ghidra</a>, a powerful tool for inspecting machine code. With some effort and ingenuity, we’ll be able to produce a complete human-readable assembly language source listing for the game—the listing that Compute!’s Gazette refused to print.</p><p>Before you ask: no, there is currently no real-time memory visualization tool like Retro Debugger for the MEGA65 or the <a target="_blank" href="https://github.com/lgblgblgb/xemu">Xemu emulator</a>. Yes, it would be cool. LGB tells me more work is needed on Xemu before it can support real-time memory visualization. In the short term, we’re more likely to see investment in the serial debugging protocol and tools like <a target="_blank" href="https://github.com/MEGA65/m65dbg">m65dbg</a>, which can be used with both the Xemu emulator and with real MEGA65 hardware over a <a target="_blank" href="https://dansanderson.com/mega65/welcome/using-jtag.html">JTAG connection</a>.</p><p>This Digest is made possible by an amazing group of supporters. Only supporters are allowed to complain when the feature article isn’t specifically about the MEGA65. To become a supporter, visit: <a target="_blank" href="https://ko-fi.com/dddaaannn">ko-fi.com/dddaaannn</a></p><p>More next month!</p><p>— Dan</p><p></p> <br/><br/>Get full access to Dan’s MEGA65 Digest at <a href="https://m65digest.substack.com/subscribe?utm_medium=podcast&#38;utm_campaign=CTA_4">m65digest.substack.com/subscribe</a>
play-circle icon
40 MIN
Up Up Down Down Left Right Left Right B A Start
OCT 22, 2024
Up Up Down Down Left Right Left Right B A Start
<p>Everyone who owned a Commodore 64 had at least one joystick, a game controller consisting of a lever that could be pushed in eight directions and a single action button. Games based on this controller typically involved the player using the stick to move an avatar—a spaceship, a person, a creature—as well as pushing the action button to activate a weapon against some enemies. The button on this kind of joystick was almost universally referred to as the “fire” button for how often it was used to launch missiles or shoot bullets.</p><p>Then came the Nintendo Entertainment System with its gamepad controller, a plastic rectangle with a directional thumb pad, two action buttons, and two more business-like buttons intended for pausing the game and accessing menus. NES games, especially <a target="_blank" href="https://en.wikipedia.org/wiki/Super_Mario_Bros.">Super Mario Bros.</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/The_Legend_of_Zelda">The Legend of Zelda</a>, popularized a new game design language based on the two action buttons. While Mario-like platform games were made for the C64 and its one-button joystick, expecting the player to shove the joystick forward (“up”) to jump, every generation of gamers that followed the NES expected to be able to jump in a platform game by pressing one of the two action buttons.</p><p>The vast majority of C64 games used the one-button joystick protocol. But there have been several attempts, both vintage and modern, to bring multi-button gaming to the C64, and to other computers with 9-pin joystick ports. This is of particular interest to modern retro game developers who want to use multi-button game design conventions while coding for the C64 and MEGA65.</p><p>In this Digest, we’ll explore a bit of the history of 9-pin game controllers, and investigate several methods used to implement multi-button schemes. We’ll look at the fundamentals of game controller electronics, and game controller programming. We’ll also take a closer look at several modern game controllers and controller adapters you can buy today for your MEGA65.</p><p>But first news!</p><p>More MEGA65 parts available separately</p><p><a target="_blank" href="https://dansanderson.com/mega65/chicagoland/">Last month</a>, we noticed that Trenz Electronic is now <a target="_blank" href="https://shop.trenz-electronic.de/en/TE0765-06-T002CK-MEGA65-Mainboard-without-housing?c=564">making the MEGA65 mainboard available for preorder</a> as a standalone part. Trenz has since added more MEGA65 parts to <a target="_blank" href="https://shop.trenz-electronic.de/en/Products/MEGA65/">their store</a>: the MEGA65 keyboard, the plastic case, the floppy drive, and the power supply. The keyboard is a sophisticated part, including the mechanical key switches, keycaps, cable, metal frame, and LEDs. The case includes other plastic bits such as the ALPS floppy drive eject button and reset button cap. You could, in theory, assemble a full MEGA65 from the spare parts available.</p><p>Math wizards may notice that the cost of the parts all together add up to more than the cost of a complete MEGA65. I can’t speak for Trenz, but this jibes with my limited understanding of the microeconomics of short-run niche electronics. Without economies of scale, Trenz has to account for labor, logistics, and potential lossage to support the individual items, even when pulling from the same stock they use to assemble full units. As deft puts it, “Imagine buying a car one piece at a time.”</p><p>I’m grateful that they’re making these available, so we have potential replacement parts, as well as options for other projects.</p><p>“Should I upgrade my mainboard?”</p><p>Did you receive your MEGA65 in 2022, or buy it second-hand from someone who did? Then your computer has the revision 3 (R3) mainboard. Starting in 2024, Trenz Electronic began shipping MEGA65s with the revision 6 (R6) mainboard, which has <a target="_blank" href="https://shop.trenz-electronic.de/media/pdf/ca/ca/31/Mega65-Pressemitteilung.pdf">several changes from R3</a>. If you’re unsure which MEGA65 mainboard you have, you can double-check which one you have in the MegaInfo panel: open the Freezer (hold Restore for one second, then release), then press <strong>Help</strong>. It’ll say which one you have next to “MEGA65 Model.”</p><p>Should owners of the R3 board upgrade to the R6? Probably not. It is unlikely that a difference between the R3 and R6 mainboards would be worth the cost of a new mainboard to most R3 owners. The differences may not even be noticeable.</p><p>There are a few notable categories of changes between the R3 and R6 boards: bidirectional cartridge and joystick I/O lines, an added SDRAM chip, and electrical fixes.</p><p><strong>Bidirectional cartridge lines.</strong> The original R3 mainboard supports the vast majority of cartridges made for the Commodore 64, which provide program data as input to the computer. It will also support cartridges made for the MEGA65 in the future. The cartridge port changes in the R6 board apply to a few electronically fancy cartridges that communicate with the computer using both input and output. For example, the <a target="_blank" href="https://www.mssiah.com/">MSSIAH MIDI interface cartridge</a> works with the C64 core, and requires the R6 mainboard. EasyFlash 3 is also known to require the R6. Notably, an EasyFlash 1 cartridge can be both read from and written to by an R3 MEGA65. That’s how we’ve been testing <a target="_blank" href="https://mega65.atlassian.net/wiki/spaces/MEGA65/pages/36962324/MEGA65+Style+Cartridge+Work+in+Progress">the MEGA65 cartridge protocol</a>.</p><p><strong>Bidirectional joystick port lines.</strong> The original R3 mainboard also supports the vast majority of game controller peripherals for the C64, which provide input to the computer about how the user is manipulating the controller. A few unusual peripheral designs use the data lines for both input and output, to implement more buttons or other features with proprietary protocols. The R6 mainboard adds support for such protocols. See this month’s feature article for more on game controller protocols.</p><p><strong>SDRAM chip.</strong> The R6 adds an SDRAM chip that is intended to broaden the possibilities for alternate FPGA cores. It is possible that someday there could exist an alternate core that requires the R6 and doesn’t run on the R3. Personally, I think it’s worth tempering these expectations. I’ve discussed this with a bunch of people familiar with MiSTer-style core development, and they have all estimated that the most compelling alternate cores for the MEGA65—including an Amiga core—should fit the original R3 board. There may never be an alternate core that requires the SDRAM, even though it was added for this purpose. No core exists today that requires an R6, and I’m not aware of anyone working on one.</p><p>Most importantly, the MEGA65 core does <em>not</em> use the new SDRAM component. All software written for the MEGA65 will run on both R3 and R6 mainboards, now and in the foreseeable future. There are no plans to treat the SDRAM chip as a memory expansion for the MEGA65.</p><p><strong>Minor fixes.</strong> Lastly, the R6 board implements some minor fixes for known issues. If you are noticing these issues on an R3 board, you may be able to use inexpensive workarounds, such as <a target="_blank" href="https://www.amazon.com/gp/product/B0B28GR7XY">an HDMI repeater</a> or a <a target="_blank" href="https://files.mega65.org/?ar=ff484da0-d942-4e9b-adf1-3b5a77acaa25">replacement Real-Time Clock</a>. If you’re not noticing these issues, you won’t notice the fixes with an upgrade. This category also includes a few changes to accommodate the availability of components; these changes don’t affect the functionality of the computer.</p><p>I know I’ve spent a lot of money over the years indulging my <a target="_blank" href="https://en.wikipedia.org/wiki/Fear_of_missing_out">FOMO</a> by buying hobby computers “just in case” I want them later, and it’d be hypocritical of me to say an R6 is not a worthy upgrade to an R3 when I own one of each. But given that a new mainboard is more than half the cost of a new MEGA65, it’s worth resisting the temptation to think other people have all of those things and you have none of them. Really, R3 and R6 are mostly identical.</p><p>Portland Retro Gaming Expo 2024</p><p>I took the MEGA65 to the <a target="_blank" href="https://www.retrogamingexpo.com/">Portland Retro Gaming Expo</a> in Portland, Oregon, mere weeks after getting back from Chicago. PRGE is another massive show, but with a different vibe from VCF Midwest. As the name implies, the show is dominated by vintage gaming, with free-to-play arcade and gaming console exhibits, gaming tournaments, several concurrent tracks of talks and panels, meet-and-greet booths with voice acting and YouTube celebrities, and a massive vendor floor with multiple eras of console games and related merchandise.</p><p>PRGE has always featured vintage home computing in its line-up, but representation of the home 8-bits on the vendor floor has waned as our vintage hardware has become more collectible. This year, PRGE established a “home computing” exhibit to keep some of our favorite computers in the show. My MEGA65 booth joined several large displays of Texas Instruments, Commodore, Atari, and Apple vintage equipment, as well as more obscure Z80-based computers. I sat closest to the tournament area, where competitors tore through <a target="_blank" href="https://en.wikipedia.org/wiki/Street_Fighter">Street Fighter</a> and <a target="_blank" href="https://rivalsofaether.com/">Rivals of Aether</a> as commentators hyped up the crowd. I was also across from the big surprise of the show, a large display by <a target="_blank" href="https://en.wikipedia.org/wiki/Blockbuster_(Bend,_Oregon)">The Last Blockbuster</a>, with Blockbuster video iconography, merch, and racks of VHS tapes.</p><p>My MEGA65 table was much larger and more welcoming to visitors than it was at VCF Midwest. I’m grateful to Hans, the show runner, for gifting me two tables, and for lending me a big screen TV. And I got to hang up the banner! Even in this back corner of the show floor, the MEGA65 drew a lot of attention, and I spent nearly all of the first day on my feet, answering questions, shaking hands, and handing out cards and mousepads. Several people from press outlets wanted interviews. If the fire alarm hadn’t gone off in the middle of the day, I may never have had a break for lunch. The second day was quieter, but I still had quite a few kids stop by for a round of <a target="_blank" href="https://files.mega65.org/?id=0f619bcf-63f0-43d5-b938-0ae6b87f4917">Unicone</a> or <em>First Shot</em>.</p><p>It was especially gratifying to see young people take an interest in the MEGA65. Some of them already knew what it was and were excited to see it in person, some dragged their parents over to the table for a look, and several sat down at the computer for long stretches of time to peruse the demo disks and write short programs. I talked to MEGA65 owners and wannabe owners, and plenty of people simply intrigued by an 8-bit style computer that seemed familiar but unlike anything they’d seen before. I got to introduce many people to the stories of both the Commodore 65 and the MEGA65.</p><p>New TI-99/4A core</p><p>My very first computer was a Texas Instruments TI-99/4A, and now thanks to zeldin, I can recreate those childhood memories! <a target="_blank" href="https://files.mega65.org/?id=a25ce133-ed07-4ef7-8495-179d69c43ed0">Mega99</a> is a TI-99/4A core, written from scratch exclusively for the MEGA65. The core needs <a target="_blank" href="https://ftp.whtech.com/System%20ROMs/MAME/">the ROM files from the MAME project</a> (ti99_4a.zip, ti99_fdc.zip, and ti99_speech.zip) as well as the provided mega99sp.bin file in the root of the SD card. Flash the core to a spare slot in the core selection menu.</p><p>As of this writing, the core is only available for the R6 boards. This is not a matter of hardware capacity, and hopefully zeldin can produce a build for R3 owners in the future.</p><p>Be sure to read the README.md file for installation and usage instructions. The core matches the 99/4A CPU timing by default, and can also run in a turbo mode. And get yourself <a target="_blank" href="http://dunfield.classiccmp.org/ti/usrguide.pdf">the TI-99/4A User’s Guide</a> to remind yourself how this thing works! Hint: the Mega key is the FUNC key, and many text entry features use it.</p><p>Thank you zeldin for this excellent and nostalgic core!</p><p>Featured Files</p><p>Here are some recent demos uploaded to Filehost worth checking out:</p><p>* <a target="_blank" href="https://files.mega65.org/?id=26c503ff-571c-44a2-af02-46e8a5d8476d">Shodan</a>, by Drex.</p><p>* <a target="_blank" href="https://files.mega65.org/?id=ce0c4812-5eab-428b-b220-524f6324c507">3D functions</a> and <a target="_blank" href="https://files.mega65.org/?id=032a01e4-219c-450d-9dee-051dbd7c8133">Patterns</a>, by adorigatti.</p><p>* <a target="_blank" href="https://files.mega65.org/?id=1b20b366-9177-4739-8420-c74f911a7202">HyperBallad</a>, by MirageBD.</p><p>Joytest65</p><p>This month’s Digest is all about joystick and paddle programming, so I made a joystick and paddle tester app to go with it. It includes documentation and assembly language source code.</p><p>* <a target="_blank" href="https://files.mega65.org/?id=671054f3-45ed-4b88-957c-fd7a55c67b2d">Download joytest65 from Filehost</a>.</p><p>The 9-pin connector</p><p>The C64 was one of several early computers that adopted the <a target="_blank" href="https://en.wikipedia.org/wiki/Atari_joystick_port">Atari joystick port</a> standard from the <a target="_blank" href="https://en.wikipedia.org/wiki/Atari_2600">Atari 2600</a> (1977), and supported the use of Atari game controllers to play C64 games. I’m most familiar with the classic <a target="_blank" href="https://en.wikipedia.org/wiki/Atari_CX40_joystick">Atari CX40 joystick</a>, but there were <a target="_blank" href="https://www.ataricompendium.com/game_library/controllers/controllers.html">many others</a>, and everyone has a favorite. Commodore used the Atari-style controller connector on everything from the VIC-20 to the Amiga, and they intended the C65 to have two 9-pin peripheral ports, just like the C64. The MEGA65 has two 9-pin peripheral ports on the left-hand side.</p><p>Nintendo released the NES in the USA with a proprietary controller connector and more buttons, and the game console arms race that followed produced more custom connectors, more buttons, and more evolutions in game design language. Commodore made two attempts to follow suit in their final years, both using new protocols over the original Atari-style connector: the <a target="_blank" href="https://en.wikipedia.org/wiki/Commodore_64_Games_System">C64GS</a> and the <a target="_blank" href="https://en.wikipedia.org/wiki/Amiga_CD32">Amiga CD32</a>. These protocols were backwards compatible with older Commodore computers, and the new consoles also supported the one-button controllers and ran compatible games.</p><p>Commodore also made several types of computer mice that used the 9-pin connector, especially the 1351 mouse for the 8-bit computers, and the Amiga mouse. As you probably know by now, your MEGA65 supports both types of mice, using built-in adapter logic to make the Amiga mouse appear to software as a 1351. See the <a target="_blank" href="https://files.mega65.org/?id=a5081244-a976-4a21-9153-27cca13fd613">User’s Guide, 2nd edition</a>, for information on how to configure the mouse emulation mode. We won’t cover the mice protocols in this issue of the Digest.</p><p>What follows is a description of how Atari and Commodore computers use the 9-pin connector for game controllers. Other 8-bit computers and early game consoles used the connector, but not necessarily the same wiring or protocols.</p><p>Joystick fundamentals</p><p>A standard 9-pin one-button joystick tells the computer that the action button is being pressed by connecting pin #6 to pin #8 (the ground pin, labeled “GND”). This doesn’t require any fancy electronics, it’s typically just a button connected to these two pins. When the player presses down on the button, two pieces of metal in the button make contact, completing an electronic circuit. When the player releases the button, a mechanical spring-like action separates the two pieces of metal, breaking the circuit and signaling to the computer that the button was released. This kind of button is also known as a <em>momentary switch.</em></p><p>Pins #1, #2, #3, and #4 work similarly, representing the joystick directions up, down, left, and right, respectively, when connected to pin #8. The joystick indicates a diagonal direction by completing two circuits simultaneously, such as up and left. Typically, there are no fancy electronics involved here either. The joystick is built such that when the user pushes on the stick, it closes one or two momentary switches wired to those pins.</p><p>Within the MEGA65, these pins are connected to the Complex Interface Adapter (CIA) chip, which translates these electronic signals into register values that can be read by a program. Try this: connect a joystick to port 2, and run the following simple program:</p><p>10 PRINT PEEK($DC00) 20 GOTO 10</p><p>The program prints the number 127 repeatedly. Move the joystick and press the fire button. The number changes depending on which buttons are pressed.</p><p>This register value is a bit field, where each button is assigned to a bit. If the button is not pressed, the bit is 1 (“high”). If the button is pressed, the bit is 0 (“low”). This is why the register value is 127 when no buttons are pressed: all of the bits associated with the buttons are “held high” until they are “pulled low” by the button presses. (The register has additional bits not connected to the joystick pins.)</p><p>The one-button 8-direction joystick protocol can be summarized as follows:</p><p>* Buttons connect pin to GND; CIA bit = 0 when pressed</p><p>* Pin #1: Up, CIA bit 0</p><p>* Pin #2: Down, CIA bit 1</p><p>* Pin #3: Left, CIA bit 2</p><p>* Pin #4: Right, CIA bit 3</p><p>* Pin #6: Fire, CIA bit 4</p><p>* Pin #8: Ground (GND)</p><p>%01111111 = 127 %01111110 = 126: up %01111010 = 122: up and left %01101010 = 106: up, left, and fire</p><p>It is the program’s responsibility to read these register values, do the math, then change the game state appropriately, such as to move the player sprite around the screen.</p><p>Like the C64, the MEGA65 has two CIA chips. Only the first CIA is used to read the joystick ports. And yes, these are the same CIA chips that provide <a target="_blank" href="https://dansanderson.com/mega65/racing-the-beam/">timers and other features</a>.</p><p>The CIA and port 1</p><p>Register $DC00 represents joystick port 2. To read the status of joystick port 1, you read register $DC01.</p><p>C64 owners remember this one: with a joystick connected to port 1 and the cursor at the READY prompt, you can get junk to show up on the screen just by jiggling the stick around. This is no longer true with the MEGA65 in MEGA65 mode (as of release v0.96), but you can still reproduce this in GO64 mode or the C64 core. Try it!</p><p>The C64 uses the CIA chip connected to the joystick ports for multiple purposes. This includes reading the keyboard. When you type on the keyboard, it pulls down the CIA bits in certain patterns, just like a joystick on port 1 does. This is why, when the C64 is expecting keyboard input, a joystick in port 1 moving around can seem like typing. Even though you can prevent this effect in code for a game, many C64 games simply assumed that most people would keep their joystick connected to port 2.</p><p>The MEGA65 is better behaved because its keyboard handling uses a different mechanism that is not as reliant on the CIA chip. A couple of specific functions still test the CIA for specific key presses, but in general, port 1 joystick events are much less likely to interfere with the keyboard.</p><p>Reading the joystick from BASIC 65</p><p>BASIC 65 provides a handy function for reading the state of the joysticks. The JOY(port) function returns a value that represents joystick activity on the requested port (1 or 2). Instead of a bit field, the JOY() function returns a number from 0 to 8, where 0 means the joystick is in the center, and 1 through 8 are the eight directions counting clockwise from “up.” When the button is pressed, it adds 128 to this value. See the <a target="_blank" href="https://files.mega65.org/?id=a5081244-a976-4a21-9153-27cca13fd613">User’s Guide</a> for a table and example program.</p><p>10 PRINT JOY(2) 20 GOTO 10</p><p>As of ROM beta version 920397, the JOY() function can also read both joystick ports simultaneously, and report a merged result. To request this, use a port number of “3”: JOY(3). This is intended solely to allow a game to work with a single joystick in either port, so the player doesn’t have to change their joystick connections to play. It does not return a useful result when two joysticks are connected and moved simultaneously. If your game uses two joysticks, use JOY(1) and JOY(2) separately. This feature will be in the next MEGA65 stable release.</p><p>A machine code program can read the state of the joystick by accessing the CIA registers and interpreting the bits directly. For best results, such a program must take <a target="_blank" href="https://dansanderson.com/mega65/racing-the-beam/">interrupts</a> into account if it leaves the <a target="_blank" href="https://dansanderson.com/mega65/kernal-of-truth/">KERNAL interrupt handler</a> active.</p><p>The KERNAL interrupt handler messes with the CIA registers many times per second to process certain keyboard events. A program wanting a clean read of the CIA register must disable interrupts to prevent the handler from messing up the result.</p><p>The program has to tell the CIA chip to ignore the state of the keyboard when reading the joystick. I won’t cover how this works in detail, just know that the way to do this is to write the value $FF to the data register ($DC00 or $DC01) before reading it.</p><p>Here’s the complete sequence for a clean read of port 2 in assembly language:</p><p>sei ; Disable interrupts lda #$ff sta $dc00 ; Lock out the keyboard lines on port 2 lda $dc00 ; A = port 2 pin state cli ; Re-enable interrupts</p><p>Paddle pairs and potentiometers</p><p>In addition to joysticks, the Atari controller standard also supports a <a target="_blank" href="https://en.wikipedia.org/wiki/Paddle_(game_controller)">paddle controller</a>. A paddle uses a dial-like wheel instead of a joystick. A game can detect how far the wheel is turned by reading more registers. This controller is called a “paddle” after the seminal home computer game <a target="_blank" href="https://en.wikipedia.org/wiki/Pong">Pong</a>, which used such a controller to manipulate a paddle in a virtual game of ping pong.</p><p>Each joystick port supports <em>two</em> paddles, each with its own dial and fire button. The MEGA65, Commodore 64, and Atari 2600 all have two joystick ports, for up to four paddle players. The two dial-like controls are also used together by peripherals such as light pens or mice, where the two inputs represent movement along X and Y axes.</p><p>The paddle protocol is different from the joystick protocol. Electronically, the fire buttons are wired to joystick port pins #2 for the first paddle and #3 for the second paddle, connecting them to pin #8 (GND) when pressed. A program can read these pins using the CIA data registers, just like reading the joystick. The register bits read 0 when the button is pressed.</p><p>The paddle dial itself is a <em>potentiometer</em>, also known as a <em>variable resistor</em> or “pot.” Instead of simply connecting or disconnecting the path between two pins like the fire button, the potentiometer forms an electrical connection between two pins through an amount of electrical resistance that the computer can measure. When the player turns the knob, the amount of resistance changes, indicating the position of the dial. The first paddle on a port connects signal pin #5 (“POTX”) to pin #7, where the computer provides a voltage of +5V. The second paddle on the port uses signal pin #9 (“POTY”) and pin #7.</p><p>The paddle protocol:</p><p>* Potentiometers connect pin to +5V</p><p>* Buttons connect pin to GND; CIA bit = 0 when pressed</p><p>* Pin #2: Paddle A button, CIA bit 1</p><p>* Pin #3: Paddle B button, CIA bit 2</p><p>* Pin #5: Paddle A analog (POTX)</p><p>* Pin #7: +5V</p><p>* Pin #8: Ground (GND)</p><p>* Pin #9: Paddle B analog (POTY)</p><p>Resistor values and register values</p><p>Strangely, Commodore used a different potentiometer in their own paddles compared to the ones by Atari, and the two paddle types produce different numbers when accessed from a Commodore program. It is <a target="_blank" href="https://www.atariarchives.org/ecp/chapter_4.php">generally understood</a>, and <a target="_blank" href="https://www.breadbox64.com/blog/paddle-battle/">some have measured</a>, that Commodore paddles use a potentiometer rated at 470 kΩ (kilo-ohms), and Atari paddles are rated at 1 MΩ (mega-ohms), with the measured resistance range a bit less but on that order of magnitude. This means that when an Atari paddle is connected to a Commodore, turning the knob goes from the minimum value to the maximum value in half the rotational distance (half the “throw”) than an official Commodore paddle. In practice, this can be both good and bad: shorter throw can result in faster play, but with less accuracy and a large “dead zone” where the resistance is above the maximum recognized by the computer.</p><p>I wanted to know the actual resistance value range recognized by the MEGA65, so I started by measuring the resistance of my Commodore and Atari paddles with an ohmmeter. What I discovered was a bit of a surprise.</p><p>I took some ohmmeter measurements of my Commodore and Atari paddles, and also tested the values returned by the BASIC 65 POT() function, which returns a value from 0 to 255 based on the dial setting. Both paddles had a minimum resistance in the fully clockwise position, then increased counter-clockwise to their maximum. The Commodore paddles measured a minimum of 44 Ω to a maximum of 166 kΩ. The POT() function returned a value of 220 at the maximum, not the full 255. Atari paddles had a higher resistance of 124 Ω at minimum to 782 kΩ at maximum. Here, the POT() function returned the full 255 after only a third of a turn, with a whopping dead zone of two thirds of a rotation, returning 255 for that portion.</p><p>So I opened the cases of both sets of paddles, and discovered that my Commodore paddles have a potentiometer rated at 200 kΩ, far less than the 470 kΩ that others have reported. My Commodore paddles also have a capacitor in parallel with the signal lines, which smoothes out the signal and shouldn’t affect the DC resistance, but is notable because it is absent from other paddles. I asked some friends to open theirs and they all reported 470 kΩ pots, so I must have some weird ones.</p><p>While it’s reasonable in the abstract that a Commodore program should be able to detect the full range of motion of the Commodore paddle knob, it may have turned out to be unreasonable in practice. A game expecting the full value range to represent a full turn of the knob might be unplayable with Atari paddles, and vice versa. Perhaps Commodore decided to split the difference at some point and changed to a 470 kΩ potentiometer, and I just happen to have an earlier model of the paddles.</p><p>Of course, it's possible that a previous owner of my paddles replaced the pots with the unusual values and these didn't come from Commodore.</p><p>Reading paddles from BASIC 65</p><p>As with joysticks, BASIC 65 has a function for reading paddles: POT(paddle) returns a paddle position as a number between 0 and 255, and adds 256 if the paddle’s button is pressed. The paddles on joystick port 1 are #1 and #2, and the paddles on joystick port 2 are #3 and #4.</p><p>10 PRINT POT(1), POT(2), POT(3), POT(4) 20 GOTO 10</p><p>The MEGA65 paddle registers</p><p>The MEGA65 has dedicated circuitry and registers for reporting the four paddle values. A MEGA65 machine code program can read these values directly from registers.</p><p>* $D620: Port 1, paddle X</p><p>* $D621: Port 1, paddle Y</p><p>* $D622: Port 2, paddle X</p><p>* $D623: Port 2, paddle Y</p><p>The fire buttons on the two paddles work just like joystick buttons, and can be read directly from the CIA data register for the appropriate port.</p><p>That's all a MEGA65 programmer needs to know. On the C64, the process is a little more elaborate, and it's interesting to know why.</p><p>Reading paddles the old-fashioned way</p><p>The CIA chip only knows how to handle digital signals (1’s and 0’s), and can’t read a resistance value (an analog value in a range). Instead, it gets the help of another chip in the chipset more familiar with converting between analog and digital signals: the SID sound chip.</p><p>To read a paddle value, a program first tells the CIA to connect the SID to one of the joystick ports. The program must then wait briefly before reading the value from a SID register. The SID needs a small amount of time to read the resistance value and update the register. During this time, the SID charges an internal capacitor that is connected to the signal and voltage lines of the controller. Once it is charged, the SID flips to a different circuit that discharges it. The SID determines the resistance of the paddle controller from the amount of time it takes to perform this charge-discharge process. To convert this to a value between 0 and 255, the SID needs 512 CPU cycles. At the end of this time, the SID updates its register value.</p><p>512 machine cycles at a rate of 1 MHz takes about 1/1950th of a second. That doesn't sound like a lot, but it can be a long wait for an action game, over 10% of the time it takes to draw a frame of graphics. Of course, the program is welcome to do other things during this time. A game loop could set the CIA select bits at the beginning of the frame, then read the paddle values near the end of the game logic, adding a busy-wait at the end as needed.</p><p>The SID can only be connected to one joystick port at a time. To read paddles from both ports, a program must connect to the first port, wait the 512 cycles, read the SID registers, then connect to the second port, wait another 512 cycles, and read the SID registers again. A game that reads all four paddles may or may not need to be clever to use the waiting time wisely, depending on how much time the game needs per frame.</p><p>If the program leaves the SID connected to a single port and takes over the hardware interrupt vectors (such that the KERNAL interrupt handler isn’t messing with the CIA connections), it can skip the wait and just read the SID register at its convenience. The register will contain the last stable value.</p><p><a target="_blank" href="https://www.c64-wiki.com/wiki/Paddle">The C64 Wiki page on paddles</a> has a diagram of the <a target="_blank" href="https://en.wikipedia.org/wiki/RC_circuit">resistor-capacitor circuit</a> that the SID is using to measure the resistance value in the controller. I was confused at first because the diagram makes it look like the capacitor is provided by the paddle controller, outside of the joystick port. This is not the case: the SID provides the capacitor part of the RC circuit. The capacitor present in my Commodore paddles bridges the +5V and signal lines, and is there for smoothing purposes and is not part of the RC timing circuit. Other paddles don’t have the smoothing capacitor.</p><p>The C64 way to read paddles from machine code</p><p>A C64 machine code program must perform the full procedure to read an analog value from the SID chip: select the port to connect the SID chip, wait briefly, then read the result from a SID register.</p><p>To select the port, set bits 6 and 7 of register $DC00: for joystick port 1, set bit 6 = 1 and bit 7 = 0; for joystick port 2, set bit 6 = 0, bit 7 = 1. This is the same address as the CIA data register for reading joystick pins on port 2, but you use this address even when connecting the SID to joystick port 1. That's just how the CIA chip is wired.</p><p>The program then waits briefly for the SID to get the value. On a C64, this relatively easy: perform a busy-wait loop for some number of iterations. Based on a reference table of cycle counts per instruction, you probably only need 103 or so repetitions of a loop, but it doesn’t hurt to wait longer. The C64 CPU runs at 1 MHz, so 512 CPU cycles is sufficient.</p><p>(The MEGA65 normally runs its CPU at 40 MHz. To reproduce the SID reading procedure, you have two options: temporarily down-clock the CPU to 1 MHz for the busy-wait, or perform the busy-wait loop 40 times. Note that instruction cycle counts differ on the 45GS02 CPU than on the 6502.)</p><p>After the delay, the values of the two paddles can be read from SID registers $D419 and $D41A. The ROM code that implements the BASIC POT() function takes an additional step to <em>debounce</em> the register value, which just means to wait until two consecutive reads of the register return the same value.</p><p>Here is code for the complete procedure, reading the state of both paddles on port 2:</p><p> ; Disable interrupts sei ; Down-clock MEGA65 CPU to 1 MHz ; FAST $D031.6 -> 0 lda #$40 trb $d031 ; Connect SID to port 2 analog inputs lda #%10000000 sta $dc00 ; Wait for SID to read, ~512 1 MHz cycles ldx #$00 - inx bne - ; Read port 2 paddles, with debounce - lda $d419 cmp $d419 bne - sta paddle2a - lda $d41a cmp $d41a bne - sta paddle2b ; Reset MEGA65 CPU to 40 MHz ; FAST $D031.6 -> 1 lda #$40 tsb $d031 ; Re-enable interrupts cli ; ... paddle2a: !byte $00 paddle2b: !byte $00</p><p>Two buttons—and why not a third</p><p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Commodore_64_Games_System">Commodore 64 Games System</a> (1990), aka the C64GS, repackaged the C64 into a keyboard-less console box. To enhance the console’s gaming potential, the <a target="_blank" href="https://www.c64-wiki.de/wiki/Cheetah_Annihilator">Cheetah Annihilator joystick</a> had two buttons: a trigger button in the joystick grip, and a second button that could be detected separately in the base. This two-button protocol worked over the 9-pin connector and could be supported by any C64 game that knew about it. Only a few games were written to support it.</p><p>Math wizards may notice that all nine of the joystick port pins have been assigned: up, down, left (or paddle A button), right (or paddle B button), paddle B (“POTY”), fire, +5V, GND, and paddle A (“POTX”). That’s nine. So how is the second button connected?</p><p>In the two-button protocol, the second button uses paddle A’s analog line (pin #9, “POTX”). Unlike the other joystick buttons that connect their respective pins to pin #8 (GND, “pulled low”), this button connects pin #9 to pin #7 (+5V, “pulled high”), with a current-limiting resistor to protect the sensitive CIA and SID chips. (One <a target="_blank" href="https://www.c64-wiki.com/wiki/Control_Port">recommended resistance value</a> I’ve seen is 270-330 ohms.) To a program, a button press looks like a paddle dial flipping between its minimum and maximum positions.</p><p>The Cheetah Annihilator only had two action buttons, but if someone were to add a third button to such a controller, it would have an easy way to connect: just use the other paddle line (pin #5, “POTY”). This three-button protocol was uncommon in vintage joysticks, but is <a target="_blank" href="http://wiki.icomp.de/wiki/DE-9_Joystick">generally accepted</a> by controller modders and homebrew controller makers, because it’s a natural extension of the two-button protocol, and doesn’t require fancy electronics beyond the button and safety resistor.</p><p>The three-button protocol:</p><p>* Pin #1: Up, CIA bit 0</p><p>* Pin #2: Down, CIA bit 1</p><p>* Pin #3: Left, CIA bit 2</p><p>* Pin #4: Right, CIA bit 3</p><p>* Pin #5: Button C, via POTX</p><p>* Pin #6: Button A, CIA bit 4</p><p>* Pin #7: +5V</p><p>* Pin #8: Ground (GND)</p><p>* Pin #9: Button B, via POTY</p><p>To read the complete state of a three-button controller, simply combine the techniques for joysticks and paddles. Here’s an example of reading all buttons from port 2 in BASIC:</p><p>10 J = JOY(2) 20 D = J AND 128 : REM: THE DIRECTION 30 A = J > 127 : REM: BUTTON A 40 B = POT(3) < 128 : REM: BUTTON B 50 C = POT(4) < 128 : REM: BUTTON C</p><p>Reading the additional buttons from machine code is similar to reading the paddle values. A C64 program must still connect the SID to the port, wait for the SID to sense the button value, then read the value from the SID register. A MEGA65 program can just read the paddle registers.</p><p>Five buttons??</p><p>An 8-way joystick with two or three action buttons brings Commodore gaming one step forward in 1980’s game design language. Math wizards may notice that the NES gamepad has not three but <em>four</em> buttons: A, B, Start, and Select. Can we support all four with minimal changes to the protocol?</p><p><a target="_blank" href="https://github.com/crystalct/5plusbuttonsJoystick">5plusbuttonsJoystick</a>, by crystalct, specifies a five-button protocol using a neat trick: button #4 triggers “up” and “down” simultaneously, and button #5 is “left” and “right.” A normal joystick can’t activate these opposing directions at the same time, so they uniquely identify the buttons. This scheme has the disadvantage of not being able to use buttons #4 and #5 simultaneously with the joystick—pressing button #4 and “up” at the same time would only register the button—but they can still plausibly be used as Start and Select buttons, which aren’t typically combined with other buttons during play.</p><p>crystalct has published the schematic and board design for a joystick that supports this protocol, and you can <a target="_blank" href="https://www.pcbway.com/project/shareproject/DIY_5_buttons_joystick_for_Commodore_64_Vic20_autofire_943caf84.html">order the board from PCBWay</a>. It would be easy to hack a NES-style gamepad to support this with just a few wires. The two buttons are easy to detect with the CIA data registers, though they won’t work with the current version of BASIC 65’s JOY() function, which interprets the directional buttons to direction values only.</p><p>The project includes a C64 joystick test program also useful for trying out three-button controllers (<a target="_blank" href="https://github.com/crystalct/5plusbuttonsJoystick/blob/main/Joystick5plus1Test.prg">PRG download</a>). It works with the C64 core; I had difficulty running it with the MEGA65 core in GO64 mode. crystalct also <a target="_blank" href="http://wiki.icomp.de/wiki/DE-9_Joystick#C64">personally modded dozens of games</a> to add multi-button features—though none use the 4th and 5th buttons, as far as I can tell.</p><p>More buttons and bidirectional protocols</p><p>Game consoles that followed the NES had seven or eight buttons in addition to the directional pad. How far can we go, using the same 9-pin joystick port?</p><p>The protocols we’ve discussed so far could all be considered <em>passive</em> protocols: the controller can report the state of the joystick and buttons to the computer by mechanically completing circuits across the connector pins, and the computer does all the work to interpret these input signals. To be able to report more sophisticated inputs using the same pins, we need an <em>active</em> protocol, where the computer not only reads signals from the controller, but also sends signals to the controller. Perhaps it’d be more accurate to call these <em>bidirectional</em> protocols, because the output signals could be manipulating otherwise “passive” digital electronics in the controller, such as a key matrix. These days, microcontrollers are cheap, and modern game controllers contain tiny computers of their own, capable of an active dialog with the host computer.</p><p>The Amiga CD32 game controller provided seven buttons: red, blue, green, and yellow action buttons, left and right shoulder buttons, and one menu button. It used the same 9-pin connector, and did so in a way that allowed the CD32 to support all previous Commodore-compatible passive controllers <em>and</em> allowed the CD32 controller to be used as a passive two-button controller on other Commodores. This required the computer to treat pin #5 as an output pin to select either active or passive mode: the CD32 would hold this pin low relative to the +5V line to request the active protocol—something other Commodores wouldn’t do. When in active mode, the computer sends pulses to the controller on pin #6. With each pulse, the CD32 controller rotates through the seven buttons, reporting the status of each button on pin #9. This mechanism is called a <em>shift register</em> and is typically implemented with a common shift register chip in the controller.</p><p>While the backwards-and-forwards compatibility of this design is impressive, it rules out the ability for C64 programs to support a CD32 controller, because the C64 cannot treat pin #5 as an output. Perhaps someday we could add a CD32 controller mode to the MEGA65 core, but there just aren’t many CD32 controllers around. Would be a fun VHDL experiment, though.</p><p>Sega game consoles also used a 9-pin connector, though they did not use Commodore-compatible pin assignments. The <a target="_blank" href="https://en.wikipedia.org/wiki/Master_System">Sega Master System</a> started with <a target="_blank" href="https://segaretro.org/Control_Pad_(Master_System)">a passive two-button controller</a> protocol, and the <a target="_blank" href="https://en.wikipedia.org/wiki/Sega_Genesis">Sega Genesis</a> (aka Mega Drive) added more buttons (first <a target="_blank" href="https://segaretro.org/Control_Pad_(Mega_Drive)">3+1</a> then <a target="_blank" href="https://segaretro.org/Six_Button_Control_Pad_(Mega_Drive)">6+1</a>) with an active protocol: one pin was a dedicated output from the console that marched through two, four, or eight cycles, alternating high and low, and the definition for each of six input pins changed for each cycle. The full state table is a bit complex, trying to be backwards compatible with previous standards. (This appears to be based on timing? I got a bit lost trying to read about it.)</p><p>I always feel obligated to mention: <strong>Do not connect a Sega Master System or Sega Genesis controller directly to a Commodore.</strong> The incompatible wiring protocol could damage the delicate CIA chip. The MEGA65 is a bit more robust in this regard, but the MEGA65 core won’t assign the pins in a way that matches the controller.</p><p>These newer controllers weren’t the first to take advantage of bidirectional communication to support more buttons. The <a target="_blank" href="https://en.wikipedia.org/wiki/ColecoVision">ColecoVision Hand Controller</a> sported the usual 8-way joystick, and also a number pad with twelve buttons. Surprisingly, this protocol <a target="_blank" href="https://old.pinouts.ru/Game/colecovision_controller_pinout.shtml">only uses seven of the nine pins</a>, and the computer selects between one-button joystick mode or number pad mode by connecting one of two pins to power. In number pad mode, each button is represented as a combination of the pin signals. For example, when the “5” button is pressed in this mode, pins #2 and #3 are pulled low. When the “4” button is pressed, pins #1, #2, and #3 are pulled low. This means that only one button can be recognized reliably at a time. If “4” and “5” are both pressed, only “4” is recognized.</p><p>None of these protocols work with the Commodore 64, and due to the lack of a prevalent commercial implementation, there is no real consensus on a common protocol for Commodore 8-bit computers that supports more than three buttons. One glimmer of hope is the <a target="_blank" href="https://www.protovision.games/shop/protopad/protopad.php">in-progress Protovision Protopad</a>, a project that intends to produce an eight-button controller (four action, two shoulder, two menu) with support for both the passive three-button protocol and a proprietary eight-button protocol, selectable by software. The active protocol uses an elegant and fast multiplexing technique compatible with the C64’s CIA bidirectional capabilities. It’s not clear if or when the hardware part of this project will come to fruition, but <a target="_blank" href="https://www.protovision.games/files/Protopad_Development_Guide.zip">the Protopad Development Guide</a> defines the protocol. It’s a fun read. (Well I think it’s fun.)</p><p>This brings us back to the topic of MEGA65 mainboard revisions. A Commodore-compatible active protocol game controller would use bidirectional communication over the joystick port data lines, and therefore would require an R6 mainboard. That is, if such a controller existed. I’m rooting for the Protopad, but in the meantime, I’m focusing on passive protocol controllers, which work with both R3 and R6 mainboards.</p><p>Modern game controllers and adapters</p><p>You can find plenty of vintage Commodore-compatible one-button 9-pin game controllers at flea markets, computer conventions, and online auction websites. Many are still in working order, and hobbyists refurbish and re-sell them. You can also get new 9-pin game controllers ranging from hand-assembled hobbyist projects to limited run Kickstarters to fully manufactured products.</p><p>There are also quite a few hobbyist electronics projects to make adapters for non-Commodore game controllers, both new and vintage, so that they work as Commodore 9-pin game controllers. A few of these implement the three-button protocol, or have a way to switch between multiple protocols. You can buy some of these pre-assembled; others are only available as schematics, and require ordering the parts separately and assembling them with a soldering iron.</p><p>The following are just a few examples of useful and interesting game controllers and adapters.</p><p>Game controllers</p><p><strong>RetroGameBoyz gamepads.</strong> Mike of <a target="_blank" href="https://retrogameboyz.com/">retrogameboyz.com</a> has been making new game controllers for vintage computers since 2017. Mike offers a wide variety of styles, platforms, and configurations. My favorites are the NES-style game pads, which include 9-pin connectors, long cables, and attractive decorative faceplates. Mike even makes <a target="_blank" href="https://retrogameboyz.com/products/mega-65-them-commodore-64-atari-2600-flashback-9-x-controller-joystick-up-to-jump-map-gamepad">a MEGA65-themed game pad</a>! This one supports the one-button protocol, and wires the second action button to “up,” which is used as “jump” in many C64 platform games. I’m working with Mike—well, I’ve asked Mike and he’s doing all the work—to produce a custom MEGA65-themed controller that supports the three-button protocol, for future MEGA65 multi-button games.</p><p><strong>The Commotron wireless gamepad.</strong> The <a target="_blank" href="https://shop.tentelian.com/Commotron-Gamepad-Turbo-2000-Super-p500731320">Commotron Gamepad Turbo 2000 Super</a> is a fully assembled gamepad with two unique properties. For one, it’s wireless, with a dongle and a range of six meters. And for two, it supports six remappable button layouts including the an “up” button in addition to the three-button protocol. It’s currently sold out in the Commotron store, but they’re taking pre-orders for more, and <a target="_blank" href="https://retro8bitshop.com/product/new-gamepad-c64-style-wireless/">third-party sellers still have some</a>.</p><p>The Commotron powers on into a mode compatible with the three-button protocol described above, where button “1” is the primary fire button. I couldn’t find the instructions for the Commotron online, so for the benefit of future web searchers:</p><p>* Buttons: directional pad (up, down, left, right), Map, Auto; and four action buttons, starting right-most going counterclockwise: 1, 2, 3, and “up.”</p><p>* Button 1 is the primary fire button, for one-button games. In C64 mode, buttons 2 and 3 are POTX and POTY, respectively. The “up” button triggers the “up” direction signal, good for “jump” in one-button platform games.</p><p>* The controller takes two AAA batteries. The dongle connects to the joystick port and is powered by the computer.</p><p>* Both the controller and the dongle have a light on them:</p><p>* Off: no power, or in standby mode.</p><p>* Blinking: waiting to connect.</p><p>* On: connected.</p><p>* To connect, press the Auto button.</p><p>* To select a preset, hold the Map button and press a direction:</p><p>* Left: Commodore/ZX Spectrum mode (the default). POTX and POTY connect to +5V when active, per the three-button protocol.</p><p>* Up: Amiga and Atari ST mode. These computers connect these pins to GND when active.</p><p>* Right: Atari 7800 mode. Buttons 1 and 2 are “right” fire; button 3 is “left” fire.</p><p>* You can swap the functions of button 1 and the “up” button. To swap, hold Map and press Down.</p><p>* You can enable auto-fire to have the buttons trigger repeatedly while held down. To toggle auto-fire mode, press Auto. To change the fire rate, hold Map and press an action button:</p><p>* Button 1: 3 clicks per second</p><p>* Button 2: 5 clicks per second</p><p>* Button 3: 8 clicks per second</p><p>* Button “up”: 13 clicks per second</p><p><strong>Neo-Atari controllers.</strong> <a target="_blank" href="https://atari.com/">The modern-day company that owns the Atari trademark</a> has made a largely successful play for our nostalgia-filled hearts with recreations of vintage consoles with varying degrees of authenticity and modernity. This includes new versions of the classic 9-pin game controllers, including the <a target="_blank" href="https://atari.com/products/cx40-joystick">CX40+ joystick</a>, the <a target="_blank" href="https://atari.com/products/cx30-paddle-controller">CX30+ paddles</a>, and the <a target="_blank" href="https://atari.com/products/cx78-gamepad">CX78+ two-button gamepad</a>. (We didn’t get the Atari CX78 in the USA back in the day, so this is news to me!) <a target="_blank" href="https://atari.com/products/wireless-cx40-joystick-atari">Wireless models of the CX40+</a> and <a target="_blank" href="https://atari.com/products/wireless-cx78-gamepad-atari">the CX78+</a> are available for pre-order, and will include both 9-pin and USB-A wireless dongles, so you can use them with emulators on a PC <em>and</em> with vintage and retro hardware. I haven’t tested this model of paddles yet and would expect them to support the Atari resistance range.</p><p><strong>Hyperkin 9-pin controllers.</strong> <a target="_blank" href="https://hyperkin.com/">Hyperkin</a> makes a series of retro gaming consoles, as well as game controller peripherals for consoles old and new. Two of their controllers are compatible with Commodore and Atari computers. The <a target="_blank" href="https://www.amazon.com/Hyperkin-Trooper-Controller-not-machine-specific/dp/B07M5HYTZL">Hyperkin Trooper</a> most resembles the classic Atari CX40, with the fire button duplicated for left-handed and right-handed play. The <a target="_blank" href="https://www.amazon.com/Hyperkin-Premium-Gamepad-not-machine-specific/dp/B08227NQ3Z">Hyperkin Ranger</a> is a gamepad-style controller with one fire button, and even includes a single paddle wheel in a unique design. The Ranger also supports left-handed and right-handed play with a switch. Both the Trooper and the Ranger are in stock at Amazon.com.</p><p>Note: The Ranger’s paddle wheel is <em>useless</em> on Commodores. The potentiometer covers the full Atari range, 0 Ω to 1 MΩ. Less than a fifth of the throw registers between 0 and 255 with the SID, worse than an Atari paddle. I can barely get a middle value to register in my joystick-paddle tester, and can’t imagine using this paddle knob for Commodore gaming.</p><p><strong>Ultimate ArcadeR Classic.</strong> The <a target="_blank" href="https://ultimatemister.com/product/ultimate-joystick-arcader-sanwa-db9-black/">ArcadeR</a> is a one-button protocol 9-pin joystick built to last. It uses arcade-quality parts and is designed to be repairable and moddable, including auto-fire options. The joystick has quite a bit of travel, for better and for worse, and the switches make satisfying click sounds.</p><p>Controller adapters</p><p><strong>Retro Rewind C64 Genesis adapter.</strong> This pre-assembled adapter <a target="_blank" href="https://retrorewind.ca/64-amiga-genesis-adapter">converts a Sega Genesis controller to a C64/Amiga controller</a>. It supports both the one-button + “up” button configuration and a C64GS-style two-button configuration, selectable by a jumper (a little metal piece you push onto some pins on the adapter). Another jumper changes which pin is used for the second action button: POTX for “C64” mode and POTY for “Amiga” mode. Use this with a vintage Sega Genesis controller, or combine it with the <a target="_blank" href="https://www.8bitdo.com/retro-receiver-genesis-mega-drive/">8BitDo wireless Genesis-compatible controller</a> for cable-free multi-button gaming.</p><p><strong>sega-adapter.</strong> If you’re handy with a soldering iron, the <a target="_blank" href="https://github.com/eyvind/sega-adapter">sega-adapter project</a> is a Sega Genesis controller adapter with some cool features. It supports both the one-button + “up” protocol and the three-button protocol, and you can switch between them by holding the Start button. This project was tested extensively with the <a target="_blank" href="https://www.8bitdo.com/retro-receiver-genesis-mega-drive/">8BitDo wireless Genesis-compatible controller</a>. The microcontroller code is open source, so you can customize it with your own features. Note the special instruction to invert the 2nd and 3rd button signals to comply with the C64 version of the three-button protocol.</p><p><strong>mouSTer.</strong> I would put the <a target="_blank" href="https://github.com/willyvmm/mouSTer?tab=readme-ov-file">mouSTer multi-function USB 9-pin adapter</a> at the top of my list for lots of reasons, except they’re sold out everywhere, and not available as a DIY board either. This clever versatile device is the best way to connect a modern USB mouse to the MEGA65 or other Commodores, and it also adapts USB gamepads and joysticks with support for the three-button protocol, as well as crystalct’s 5plusbuttonsJoystick protocol. It’s highly configurable: to upload new configuration, put <a target="_blank" href="https://github.com/willyvmm/mouSTer/blob/main/MOUSTER.INI">a configuration file</a> on a USB stick and shove the stick into the adapter. I love it, but yeah, it’s currently unavailable.</p><p><strong>Unijoysticle 2.</strong> <a target="_blank" href="https://github.com/ricardoquesada/unijoysticle2">This bare board project</a> connects to both joystick ports simultaneously, and pairs with any modern Bluetooth game controller. The C64 model supports the three-button protocol and the 5plusbuttonsJoystick protocol. Normally for sale on Tindie, this one is also <a target="_blank" href="https://www.tindie.com/products/riq/unijoysticle-2-c64-gamepad-for-commodore-64/">out of stock</a>, though designs are available under an open hardware license so you can make your own.</p><p><strong>SNES controller adapters.</strong> <a target="_blank" href="https://snes2c64.readthedocs.io/en/latest/">snes2c64</a> and <a target="_blank" href="https://github.com/Hojo-Norem/PadSwitcher64">PadSwitcher64</a> are two projects with interesting takes on multi-button support. snes2c64 adapts the six-button SNES controller to a three-button C64 controller, using a programmable Arduino Nano for custom button mapping and auto-fire options. PadSwitcher64 connects to <em>both</em> 9-pin joystick ports to support all six SNES buttons with a proprietary passive protocol.</p><p>I’m most excited about the possibility of the three-button protocol for MEGA65 games. It’s relatively easy to find pre-assembled controllers, easy to implement in software and modified hardware, compatible with both R3 and R6 mainboards, and is the closest thing we have to an implemented standard for multi-button Commodore-compatible game controllers. I’ll let you know what Mike and I come up with for controllers and software support. If you can get your hands on a Commotron, or are handy enough to build a sega-adapter, those are also good options.</p><p>Give <a target="_blank" href="https://files.mega65.org/?id=671054f3-45ed-4b88-957c-fd7a55c67b2d">joytest65</a> a try and let me know how it works for your game controllers.</p><p>Happy gaming!</p><p>— Dan</p> <br/><br/>Get full access to Dan’s MEGA65 Digest at <a href="https://m65digest.substack.com/subscribe?utm_medium=podcast&#38;utm_campaign=CTA_4">m65digest.substack.com/subscribe</a>
play-circle icon
50 MIN