Afleveringen

  • [Did you know: All issues of the Digest have an audio version! Search for “Dan’s MEGA65 Digest” in your favorite podcast app, or check out the audio player at the top of each issue. — Dan]

    There are two methods for making sound and music with the MEGA65, as it is currently implemented. The first method is the four SID chips, programmable devices that generate waveforms with requested parameters using analog electronic components. We took a dive into the SID chips back in—November 2022?? How long have I been doing this?? 


    The MEGA65 can produce sound another way. Pulse-Code Modulation (PCM) describes a waveform as a sequence of values over time, literally the shape of the desired waveform as a series of high and low numbers, as if drawn on a graph. The computer feeds these numbers into a device called a Digital-Analog Converter (DAC) that produces the waveform in that shape, as if rapidly changing the position of a speaker membrane according to each value. The MEGA65 has four DACs, and these waveforms are mixed with the rest of the audio system to produce the stereo audio output of the computer.

    With PCM, a computer can reproduce real-world sounds captured by a microphone, such as human speech or musical instruments. Today, we take this extremely for granted: modern computers generate pretty much all sound using PCM waveforms. We used to call this “digitized sound,” in contrast with “synthesized sound.” Now we just call it “sound.” While PCM gives a computer program much more control over the generated sound, the trade-off is memory: relative to the memory sizes of 1980’s computers, PCM sound data takes a huge amount of space, depending on the length and quality of the sounds.

    In this issue, we’ll look at how to control the MEGA65’s DACs to play digitized sound, as well as techniques for wrangling sound data for use in your programs. As usual, we’ll spend a bit too much time nerding out on theory and file formats.

    Are you ready? Here we go.

    Featured Files

    Bomb’em All by btoschi, an explosive action game for two to four players. Drop bombs, pick up items, and break through walls while trying to trap your opponents in the blast zone. The game supports the Four Fun joystick adapter for four joysticks, or can be played with a mix of joystick and keyboard controls.

    BASIC Star Galactica by jim_64, a space battle adventure. Destroy the Cylons and protect the fleet—and the future of humanity. Don’t miss the downloadable, printable disk label and manual.

    fredrikr has prepared the fourth in his series of text adventure game bundles for the MEGA65, featuring modern classics from the interactive fiction community. This pack includes a variety of games released from 1995 to 2023, all playable on the MEGA65 thanks to the Ozmoo Z-machine player. (See the Digest from October 2022 for more on Ozmoo and MEGA65 adventure gaming.)

    Another arcade core from muse! In Ghosts’n Goblins (1985), you are brave knight Sir Arthur, on a quest to save the Princess Prin-Prin. Don your armor—and take care not to lose it—while fighting waves of zombies, giants, demons, and other monsters. This classic from Capcom is considered one of the best video games of all time—and one of the most difficult. As with the other arcade cores, you will need to find the game ROM online, and follow the instructions to install it.

    In Stranded, a graphical adventure game by Magnus Heidenborn, your boat has crashed and washed ashore a deserted island. Magnus wrote Stranded for the Commodore 64, specifically the modern TheC64 clone. Gurce ported it to the MEGA65, and added original music. I especially appreciate the novel keyboard-based linear travel and exploration mechanic, which works around common issues with point-and-click adventure games. Check it out!

    Expansion board progress

    Paul is making progress on the MEGA65 expansion board project. As we reviewed in a previous issue, this project intends to produce an internal hardware expansion that adds component video output, a Commodore user port, a tape port, and a port for the never-released 1565 external floppy drive that was originally intended for the Commodore 65. The goal is for these expansion boards to be made entirely out of printed circuit boards (PCBs) and common components with open source designs, so anyone can order and assemble one from any PCB fabricator.

    The latest prototype includes a way to connect an ESP32 wireless Internet module (!), and routes a path for the optional JTAG adapter to a firmly mounted microUSB port accessible through the back of the computer. It also completes the 1565 disk drive port. Hopefully someday we’ll be able to make a modern recreation 1565 drive with a plastic case that matches the MEGA65.

    KLF is gonna rock you

    Here is a visual representation of the waveform of the first few notes of “3 am Eternal” by The KLF, performed by soul singer P. P. Arnold:

    Storing and replicating this waveform exactly as it was performed would require a device and a storage medium that could capture the infinitesimal changes of air pressure in the listener’s ear over time. Digital storage media is neither infinite nor infinitesimal, so we have to make some tradeoffs when digitizing audio. How can we represent this waveform as a collection of numbers, then use those numbers to reproduce an approximation of the waveform on a loudspeaker?

    Sample rate

    Pulse-code modulation describes the height of a waveform measured periodically, or sampled, over time. We can’t measure every infinitesimal point in time, so we have to choose a sample rate that says how often we take a sample. For audio, a typical sample rate is on the order of kilohertz, or thousands of times per second. A smooth curve in the original waveform is approximated by a stair-step pattern in the digitized waveform.

    The sample rate for digital audio is a lot like the screen resolution of a digital image. The actual image of an object as seen by the eye could have infinitesimal detail, but to capture it and represent it on a screen, it must be digitized into pixels. The smaller and closer together the pixels, the more detail can be captured and represented. You can think of sample rate as the “horizontal resolution” of the waveform.

    Bit depth

    We can’t measure the height of each waveform sample infinitesimally either, so this too needs a digital compromise. For example, we could store each sample as 8 bits (one byte) of data. This would give us 256 possible values for the sample. If the measured sample is between two adjacent values, it gets rounded—or quantized—to the closest value. The number of storage bits per sample is the bit depth of the sample (or sample depth). You can think of bit depth as the “vertical resolution” of the waveform.

    Sample depth can also be understood by analogy with digital images. Each pixel of an image is stored with a digital value that represents its color. The number of possible colors it can use is limited by the bit depth of the color value. Naturally, the more colors the computer can use for a pixel, the more accurately it can represent the original image.

    Signed vs. unsigned samples

    Conceptually, an audio waveform is a variance in the regular air pressure of a silent room, wiggling positive and negative in a pattern until stabilizing back to zero. You can see the middle line on these waveform diagrams where this level lies. Based on this, waveform samples could be represented as a signed number, with some negative numbers and some positive numbers around a baseline of zero. Or, it could be represented as an unsigned number, where the baseline is the middle value of a range of positive numbers.

    A signed 16-bit sample has a range of -32,768 to +32,767. It is usually stored as a two’s complement value, $8000 (-32,768) up to $FFFF (-1), then $0000 (0) up to $7FFF (32,767). An unsigned 8-bit sample has a range of 0 to 255, where 128 is the baseline of the waveform. It is stored simply as its byte value, $00 (0) to $FF (255). If you’re messing with sample data, you need to know both its bit depth and whether it is signed or unsigned to interpret it correctly.

    Size vs. audio quality

    Both sample rate and bit depth explain how the amount of data relates to the quality of the reproduction of the original sound. The faster we sample, the more samples we collect, and the more accurate the data is to the original sound. The higher the bit depth of the sample, the more memory is required for each sample, and the more accurate the sample is to the waveform.

    Before there were large hard drives, fast Internet transmission speeds, and data compression algorithms tuned for audio, digital music could only be practically distributed on optical fixed-storage compact discs (or “CDs,” as we called them). We purchased these discs at retail establishments with names such as “Tower Records,” and ordered them from printed catalogs to be delivered to our home via postal service from Columbia House at an introductory cost of 10 discs for 1 penny. A typical audio CD stored 74 minutes of uncompressed stereo sound data, using a sample rate of 44.1 kHz and a depth of 16 bits.

    We can calculate the amount of sample data on an audio CD with a simple multiplication: 74 minutes x 60 seconds per minute x 44,100 samples per second x 2 bytes per sample x one sample for each stereo channel (2) = 783,216,000 bytes, or almost 747 MiB. Old-timers may remember that a CD-ROM, which uses the same type of disc for storing computer files, has a capacity of 650 MiB. CD-ROMs use the rest of the space for error correction and addressing, so computers can find files and make sure they read them correctly. When an audio CD player reads a sample incorrectly, it just pretends nothing happened and keeps going, so it can use more space for samples.

    For perspective, at CD quality, the MEGA65’s 8 megabytes of Attic RAM can contain 45 seconds of audio. As we’ll soon see, we’re actually limited to 64 kilobytes at a time, which would last us 0.35 seconds at 44.1 kHz 16-bit. We’ll need to make some tradeoffs in quality and duration to make practical use of digitized sound.

    The following are the durations of 64 kilobytes of sample data at various sample rates and bit depths:

    * 4000 Hz, 8-bit: 16.384 seconds

    * 4000 Hz, 16-bit: 8.192 seconds

    * 8000 Hz, 8-bit: 8.192 seconds

    * 8000 Hz, 16-bit: 4.096 seconds

    * 11025 Hz, 8-bit: 5.944 seconds

    * 11025 Hz, 16-bit: 2.972 seconds

    * 16000 Hz, 8-bit: 4.096 seconds

    * 16000 Hz, 16-bit: 2.048 seconds

    MEGA65 Audio DMAgic

    Imagine we had a way to control the speaker membrane directly from a MEGA65 program using a hardware register. What would the program have to do to play back a short digitized sound? The program would write each PCM sample to the register, and it would have to do it at a consistent rate that matches the sample rate. If the sound was digitized at 8 kHz, this program would have to write sample data to the register 8,000 times per second, at even intervals. This is entirely possible with a 40 MHz CPU, but getting the timing right would be a significant programming challenge, especially if the program does other things besides play the sound.

    Thankfully, the MEGA65 can help us with this. Reading a series of values from one memory location and writing them to another is the bread and butter of the Direct Memory Access (DMA) chip, a purpose-built chip in the Commodore 65 that the development team called “DMAgic.” DMA is typically used to copy one region of memory to another location very quickly, or fill a region with a value. Normally it does this as quickly as possible. The MEGA65 has enhanced DMAgic with a mechanism for playing audio samples to the DAC at a programmable sample rate, controlled with hardware registers. Your program can even do other things while the sample is playing: playback happens concurrently with program execution.

    Because sample timing is managed for us by audio DMA, we don’t need to worry about our program being fast or accurately timed. You can even use audio DMA from BASIC!

    Audio DMA specs and techniques

    For audio DMA to work its “DMAgic,” a few things must be true:

    * The CPU must be running at 40 MHz. (This is the default.)

    * Sample data must be in main memory, not Attic RAM.

    * Samples must use a bit depth of 16, 8, or 4. Values can be signed or unsigned.

    * The playback region cannot exceed 64 KB.

    At first glance, this seems a bit limiting, but it’s actually quite powerful with a few tricks. For example, while sample data must be in the first 384 KB of main memory during playback, your program can store its samples in the 8 MB of Attic RAM, then use a DMA copy operation to install it in main memory to be played.

    4-bit samples are stored in an interesting way: the DMA must advance through memory by at least one byte per sample, so 4-bit samples use either the top four bits or the bottom four bits of each byte, and you tell audio DMA which bits to use when you play the sound. This means you can have two 4-bit sounds stored in the same bytes, one in the top bits and another in the bottom bits.

    When you play a sound, you can tell audio DMA to stop at the end, or loop back to the beginning automatically and continue playing. Looping is great for short repeating waveforms, or long repeating patterns like drum beats or atmospheric sounds.

    With a bit of cleverness, you can play sample data larger than 64 KB by taking advantage of the looping feature. Your program can copy new sample data into the memory region as the sound is being played, so when the playhead loops back to the beginning, it starts playing the new data.

    Your program specifies the sample rate to use the play the samples. If you want the samples to sound like the original recording, you play the samples at the rate they were digitized. You can also play the samples at a slower or faster rate to change the pitch and speed of the sample, like spinning a record player at a faster or slower speed. —Oh, uh, records were another way to distribute music before CDs, as analog waveforms etched into grooves on vinyl discs. Sounds were reproduced mechanically by vibrating a needle called a stylus, by running it across the etched groove at a steady speed. Because retro is cool, vinyl album sales have seen a rapid resurgence recently that is expected to grow in 2024, while sales of CDs have dropped in favor of online music streaming.

    A synthetic example

    Before we figure out how we get recorded sound data into the MEGA65, let’s try out the audio DMA system with some made-up numbers. We’ll use BASIC here, but the procedure is the same in assembly language: we’re just writing to memory and registers. (Try porting this example to assembly language!)

    The waveform

    To start, let’s draw a simple “sawtooth” waveform into some memory. This will just be the numbers 0 to 255 across 256 bytes of memory, which we will play looped.

    10 FOR X=0 TO 255 : POKE $50000+X,X : NEXT X

    Channel registers

    Each of the four audio DMA channels has 16 bytes of registers. Channel 0’s registers are at addresses $D720 to $D72F, channel 1’s are at $D730 to $D73F, channel 2’s are at $D740 to $D74F, and channel 3’s are at $D750 to $D75F. I’ll refer to each register by its offset $0 through $F. Just know that the registers have the same layout for all four channels.

    Switch off channel 0 while we’re setting it up, by writing a 0 to register $0:

    20 POKE $D720,0

    Enabling the audio DMA system

    The audio DMA system must be enabled before it can be used. This is a global setting, address $D711 bit 7:

    30 SETBIT $D711,7

    Sample addresses

    The starting address of the sample is a 24-bit value, across registers $1 to $3. We also want to set the channel 0 playhead, a 24-bit value across registers $A to $C. (Remember, these are all Little Endian.) The starting address is used for looping: when the playhead reaches the end, it’ll jump back to the start address.

    40 POKE $D721,$00:POKE $D722,$00:POKE $D723,$05 : REM SAMPLE STARTS AT $5.000050 POKE $D72A,$00:POKE $D72B,$00:POKE $D72C,$05 : REM SET PLAYHEAD TO BEGINNING

    The end of the sample is stored as a 16-bit value equal to the lower 16 bits of the last address, in registers $7 to $8. In our case, the end address is $5.00FF, so the register value is $00FF.

    60 POKE $D727,$FF:POKE $D728,$00

    Channel volume

    Each audio DMA channel gets two volume settings, with the ability to pan the channel’s output to the Left DAC or the Right DAC in different proportions.

    Channels 0 and 1 are considered “left” channels, and channels 2 and 3 are considered “right” channels. The $9 register in each channel’s register bank sets the volume of the signal that it outputs to its device, either the Left DAC or the Right DAC. The register value is between 0 and 255, with 255 being the loudest.

    Another set of volume registers allow for each channel to also output to the opposing DAC. Registers $D71C and $D71D set the output of channels 0 and 1, respectively, to the Right DAC. Registers $D71E and $D71F set the output of channels 2 and 3, respectively, to the Left DAC.

    This can get a little confusing because the user can subsequently pan the Left DAC or the Right DAC using the Audio & Volume tool in the Freezer, and can even flip the stereo field entirely. If you want to experiment with this, I recommend opening the Freezer tool and setting the “Left Digi” volume up in the left output channel and all the way down in the right output channel, and the “Right Digi” volume down in the left and up in the right, so you can hear clearly through stereo speakers which DAC is being used.

    Let’s just set channel 0 to output evenly to both DACs for now. This sawtooth wave is a bit obnoxious, so I'm using a low volume level:

    70 POKE $D71C,$22 : POKE $D729,$22

    Headphone warning: If you are listening to your MEGA65 with headphones connected directly to the 3.5mm jack, I recommend reducing the master volume in the Audio & Volume tool while you are testing digital audio samples. Incorrect sample data or erroneous register values could cause unexpectedly loud sounds. I prefer to use a set of speakers with an independent volume knob set to a low setting. (Headphones tend not to have their own volume control.)

    Sample rate

    The sample rate (frequency) is stored as a 24-bit value in registers $4 to $6. This one is a bit weird, but it’ll make sense, I promise.

    The value is the 24-bit proportional value of the frequency relative to the CPU speed. For example, if the sample rate is 16 kHz, then the register value is 16 kHz divided by 40 MHz (a ratio), multiplied by 2 to the 24th power minus 1 (the largest 24-bit value). Watch those units when doing the math! The CPU is much faster than the sample rate, so you should get a very small ratio.

    Here are the register values for some useful sample rates, pre-calculated for your convenience:

    * 4 kHz : 1,662 ($00067E)

    * 8 kHz : 3,324 ($000CFC)

    * 16 kHz : 6,648 ($0019F8)

    * 32 kHz : 13,296 ($0033F0)

    For our experiment, we actually want to do something special with the frequency. We have a very short sawtooth waveform, capable of playing a musical note. The middle “A” key on a piano would play this pattern 440 times per second (440 Hz). We have 256 samples, so to achieve a middle A pitch, we need a sample rate of 440 x 256 = 112640 Hz = 112.64 kHz. Proportional to the 40 MHz CPU speed, the 24-bit value is: 47,244 decimal, or $00B88C (that’s “zero zero Baker eight eight Charlie”).

    Someone check my math.

    80 POKE $D724,$8C:POKE $D725,$B8:POKE $D726,$00 : REM SAMPLE RATE 112.64 KHZ

    Sample sign, bit depth, looping, and playback

    Finally, we can trigger the sample, with a few last settings in register $0. This register uses the following bits as flags:

    * Bit 7: Play it.

    * Bit 6: Loop it. We want this to loop our very short sawtooth wave.

    * Bit 5: Set this to 0 if the sample value is signed. We’re using unsigned values in this example, so we set this to 1.

    * Bits 1-0: The bit depth: 11=16 bits, 10=8 bits (our choice), 01=upper 4 bits, 00=lower 4 bits.

    90 POKE $D720, $80 + $40 + $20 + $02100 GETKEY A$ : REM WAIT FOR A KEYPRESS110 POKE $D720,0 : REM SWITCH IT OFF! SWITCH IT OFF!

    Try it out!

    Run this to hear the tone. It’s a bit obnoxious, so press a key to switch it off. If you accidentally press Run/Stop with the sound still playing, use POKE $D720,0 to disable the sound.

    You can experiment with different waveforms by writing different values to $5.0000-$5.00FF. Try these:

    10 FOR X=0 TO 255 : POKE $50000+X,255*(SGN(X-128)+1) : NEXT X10 FOR X=0 TO 255 : POKE $50000+X,X-(X-128)*(X>128) : NEXT X10 FOR X=0 TO 255 : POKE $50000+X,127*SIN(X/255*3.1415)+128 : NEXT X

    Converting audio files to raw PCM data

    This little experiment to play triangle, sawtooth, and sine waveforms is fun, but not particularly impressive considering that the SID chips can already generate these waveforms on their own. To unleash the true power of audio DMA, we need PCM sample data for more interesting sounds. The MEGA65 does not have a built-in audio digitizer (at least not yet), so we must turn to our trusty modern computers.

    There are many ways to record, produce, or otherwise acquire sound files with a modern computer and an Internet connection. Your computer’s operating system probably includes a free sound recording or editing program, and so does your mobile phone. Sound editing software like Audacity is free, and you can also download free sound files from FreeSound.org. Whatever software you’re using, be sure to edit your sound file to trim it to just the length you want your MEGA65 program to play.

    Audacity

    Our goal is to convert the sound file to raw PCM sample data at an appropriate sample rate, and at a bit depth supported by the MEGA65 audio DMA. Audacity can do all of this in a single export step:

    * File menu, Export Audio.

    * Format: “Other uncompressed files”

    * Channels: Mono

    * Sample Rate: 8000 Hz or higher, or select “Other” and enter any rate in Hertz

    * Header: “RAW (header-less)”

    * Encoding: “Signed 16-bit PCM” or “Unsigned 8-bit PCM”

    * Click Export.

    Remember that sample rate and bit depth affect data size and sound quality, so choose wisely.

    Other modern sound production software may not have all of the same export options. Some of the more expensive software packages on my computer can’t believe I would ever want to export at a sample rate lower than 44.1 kHz. If your software doesn’t export raw PCM sample data, or doesn’t offer the desired sample rate or bit depth, export a .wav file with high quality settings, then use Audacity for the final conversion to raw PCM data with the desired parameters.

    It’s important to use the highest quality settings for every processing step until the last one. Because each digital audio file is an approximation of the original waveform, the conversion tool has to use some math to assume the gaps between the samples when converting from one sample rate to another. The more data that goes into that process, the better.

    While preparing this Digest, I had occasional issues with Audacity trying to boost the volume of my samples, causing clipping of the signal in some cases that added loud pops to the final sound effect. Notably, this clipping only happened on real hardware and not in Xemu, so be sure to test your samples.

    ffmpeg

    Audacity is fine, but I like command line tools so I can automate build workflows. The tool for this is ffmpeg, an essential free media conversion tool for video and audio. It’s similar to how we used ImageMagick to convert still images back in a previous Digest. ffmpeg is available for all platforms. On a Mac using Homebrew, install this with: brew install ffmpeg

    ffmpeg accepts most audio files as input, including .wav files. Specify the input file with the -i parameter. It’ll detect everything it needs to know about the input data from the file itself.

    For the output file, we want something special, so we need to tell it what we want. The -f option selects the bit rate, selected from this list:

    * s16le : signed 16-bit Little Endian

    * u16le : unsigned 16-bit Little Endian

    * u8 : unsigned 8-bit

    To convert the file to a different sample rate, use the -ar option, and provide the value in Hertz. To convert a stereo sound to monophonic, specify -ac 1.

    ffmpeg -i klf.wav -f u8 -ar 8000 -ac 1 klf.raw

    You now have a raw PCM data file. Assuming it’s small enough, you can now copy this to a D81 disk image, and transfer the disk image to your MEGA65. See a previous Digest for more information on how to manage files and disk images.

    Playing the digitized sound

    The BASIC program above can be modified to play an arbitrary sample file. Replace line 10 with a BLOAD command that loads your sample file to address $50000:

    10 BLOAD "KLF.RAW",P($0050000)

    You will need to adjust the sample length (line 60) and the sample rate (line 80) as appropriate for your data. You might want to remove the loop flag ($40) from the playback command (line 90). Only include the “unsigned” flag ($20 on line 90) if the sample data is unsigned.

    Can you hear the sound, but it’s noisy or crackling? Double-check the “unsigned” bit. Using the unsigned bit when the sample data is signed (and vice versa) will cause transitions from negative to positive values to pop, in a bad way.

    What about 4-bit sample data?

    None of the audio processing programs I tried offer export of 4-bit samples. How can we make 4-bit samples, to take advantage of this feature of audio DMA?

    Compared to something as complex as re-sampling at different sample rates, converting from an unsigned 8-bit sample to an unsigned 4-bit sample is quite easy. We just lop off the lower four bits, equivalent to dividing by 16. Here’s a simple Python program that does this:

    INPUT_FILE = 'klf_8b.raw'OUTPUT_FILE = 'klf_4b.raw'data_input = open(INPUT_FILE, 'rb').read()with open(OUTPUT_FILE, 'wb') as outfile: for i in range(len(data_input)): samp = int(data_input) // 16 outfile.write(samp)

    This takes the file klf_8b.raw containing unsigned 8-bit samples and produces the file klf_4b.raw containing unsigned 4-bit samples, with each sample in the lower four bits. We can modify our playback program to use this by setting the appropriate flags in the $0 register:

    90 POKE $D720, $80 + $20 : REM PLAY IT ONCE, UNSIGNED, 4-BIT LOW

    Audio DMA requires that each sample be at separate memory locations, so merely converting a sample from 8-bit to 4-bit doesn’t actually save any space. The space savings comes from storing two 4-bit samples on top of each other, and telling audio DMA to play either the bottom four bits or the top four bits. We can modify this Python script to store two samples together in this way:

    INPUT_FILE_ONE = 'klf_8b.raw'INPUT_FILE_TWO = 'rockyou_8b.raw'OUTPUT_FILE = 'klf_4b.raw'data_one = open(INPUT_FILE_ONE, 'rb').read()data_two = open(INPUT_FILE_TWO, 'rb').read()# Pad the shorter sample with zeroes, so they are the same lengthif len(data_one) < len(data_two): data_one += b'\x00' * (len(data_two) - len(data_one))elif len(data_two) < len(data_one): data_two += b'\x00' * (len(data_one) - len(data_two))with open(OUTPUT_FILE, 'wb') as outfile: for i in range(len(data_one)): samp_one = int(data_one[i]) // 16 samp_two = int(data_two[i]) // 16 result = samp_two * 16 + samp_one outfile.write(bytes([result]))

    This takes the two 8-bit sample files klf_8b.raw and rockyou_8b.raw, converts them both to 4-bit, then writes them to a single file klf_4b.raw with klf in the lower bits and rockyou in the upper bits.

    To tell the playback program which sample to play, set bits 1 and 0 of $D720 accordingly:

    90 POKE $D720, $80 + $20 : REM PLAY IT ONCE, UNSIGNED, 4-BIT LOW90 POKE $D720, $80 + $20 + $01 : REM PLAY IT ONCE, UNSIGNED, 4-BIT HIGH

    I have a vivid memory of hearing The KLF’s “3 a.m. Eternal” played on my childhood Amiga 500. Like the MEGA65, the Amiga can play short digitized sounds over four audio DACs. Most Amiga owners didn’t have enough memory to store several minutes of digitized sound, so another kind of music was born. A MOD file encodes music as short digitized sounds played in a pattern of frequencies and timings, saving memory by re-using samples throughout the song. The KLF’s music was largely sample-based and repetitive to begin with, and they even produced some of it on home computers like the Apple II and Atari ST. MOD files can come close to reproducing the original songs within the memory limitations of a vintage computer.

    Your MEGA65 includes a MOD player on the Intro Disk, called “Manche,” that uses audio DMA to play sound samples. I found one person’s attempt at a MOD of “3 a.m. Eternal” and was able to play it in Manche on my MEGA65. I can’t say this particular MOD is my favorite remix, but it’s been fun to revive this memory.

    Here are a few MOD arrangements of KLF songs for you to enjoy:

    * Download: 3ametern.mod

    * Download: whattime.mod

    * Download: doctorin.mod

    Put these in the root of your SD card, then start Intro Disk #1. Open the Music menu, select Manche, and press Return to run the program. Within Manche, press F1, type one of the filenames, then press Return to load the file. Press Space to start playback.

    I also made this demonstration disk with the waveform generator program from this issue, as well as a program demonstrating the same sound at different sample rates and bit depths.

    * Download: KLF.D81

    This Digest is made possible with support from justified ancients, like you! To contribute, visit ko-fi.com/dddaaannn.

    See you next month!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • Spaceships. Aliens. Marios. Goombas. Bullets. Fireballs. Mouse pointers, text cursors. Any of these could be a sprite, a feature of a computer graphics system dedicated to things that move. The sprite capabilities of the Commodore 64’s VIC-II chip super-charged video games and user interfaces beyond a single screenful of character text or a bitmap image. The MEGA65 includes support for VIC-II hardware sprites, and has sprite-related BASIC commands that make them easy to use in your programs.

    In this Digest, we’ll review the VIC-II sprite system’s capabilities, try out the sprite features added to Commodore BASIC for the C128, C65, and MEGA65, and step through a development workflow for using sprites in BASIC games. And we’ll try putting these pieces together to make a simple arcade game.

    But first


    The User’s Guide, 2nd edition, now available

    You can now buy a spiral-bound printed copy of the MEGA65 User’s Guide, 2nd edition!

    This new edition has been updated substantially from the 1st edition printing from two years ago. It covers the upcoming v0.96 release, with instructions for new features like Ethernet file transfer, and revised information on important topics like upgrading the firmware and using disks. The BASIC reference has been updated with corrections, polish, and material on new features. And there are handy new appendices on screen codes and system colors.

    Whether you have the 1st edition and want to upgrade, or don’t yet have a MEGA65 and just want a useful book to go with Xemu, getting the 2nd edition in print is a great way to enhance your MEGA65 experience.

    I wrote a FAQ with more information, including what’s happening with the manuals bundled with new MEGA65s. Let me know if you have any questions.

    Release testing update

    The v0.96 release package has been in public testing for a month, and we’ve been chasing down issues and polishing it up for factory installation on all of the new MEGA65s. This process should be complete a week or so after you read this. Many thanks to everyone who has contributed to the testing effort!

    What happens next: the v0.96 release package will be made official and sent to Trenz for the factory installation on new machines. It will be declared the new stable release for R3A and R6 mainboards, and made available on Filehost. Everyone with the “retail” MEGA65 will be encouraged to upgrade.

    DevKit and Nexys board owners will need to wait, just a bit. In order to meet the assembly schedule, we have had to defer preparing new cores for these boards until after this release. The plan is to immediately start work on these deferred tasks, and issue a v0.97 update within a couple of months that includes support for these boards. You’re always welcome to help test along the way, just be aware of known issues with slot 0 flashing on the older boards.

    Upgrade party at lydon’s place! 🎉

    New Intro Disks!

    Gurce has put a ton of work into preparing the new software bundle for the SD card that will ship with the new MEGAs. Current owners are familiar with the “Intro Disk” menu that starts when you first switch on the computer, as well as other bonus goodies that come on the pre-installed memory card. The new bundle includes all of that and much more, a total of 191 (one hundred and ninety one!) menu entries. And that’s not even counting the disk menus themselves, with useful information and musical accompaniment. This compilation starts all new MEGA65 owners off with plenty to do on their first day. Huge thanks to Gurce for his meticulous work on this project, and of course to everyone who has written software for the MEGA65.

    You can download the new software bundle on Filehost. (There’s a separate download for registered owners with a more complete version of GEOS.) If you don’t yet have a MEGA65, you can try it out in Xemu—or save it as a surprise for when your MEGA65 arrives!

    New on Filehost

    Don’t miss these new titles on Filehost:

    Rocket Delivery Service, by fredrikr, a new game for one or two players. Navigate your rocket man to pick up and deliver packages, for cash! Each player can use a joystick, or player one can use the keyboard while player two uses a joystick. Written entirely in BASIC!

    MJoergen and sy2002 are updating their vintage platform cores for use on the new R6 mainboard. The ZX Spectrum core v1.2 is now available, and there is a beta test version of the C64 core v5.1 (link goes to Discord) to be released soon. The C64 core update also includes a few fixes for all mainboards, and support for using the MEGA65’s Real-Time Clock with the Commodore 64 version of GEOS.

    muse has yet another arcade core, and he keeps picking my favorites! Elevator Action (1983), a spy thriller set in a multi-level top secret facility. Infiltrate the building from the roof, avoid the armed goons, collect the secret files, and escape through the parking garage. As with the other arcade cores, you must locate the arcade ROMs yourself, so be sure to follow the installation instructions. Hold the button to jump.

    Amiga fans: geehaf has published an ADF disk image utility that can use the MEGA65’s physical floppy drive to make Amiga disks from ADF files, and vice versa. This is a beta release of the tool, so take care to back up important data.

    Exploring sprites

    The hardware sprites of the VIC-II chip should be familiar to anyone who has written a program for the Commodore 64. The Commodore 64 Users Guide that came with the machine included a chapter on sprite graphics with a type-in demo. C64 programmers may also remember drawing out pictures on graph paper, hand-coding them into decimal numbers, typing them into DATA statements, and messing about with dozens of arcane POKE statements. In later computers and later versions of BASIC, Commodore added a BASIC sprite subsystem with access to most of the VIC-II’s sprite features, driven by a new set of commands. No POKE-ing necessary.

    From here on, when I say “sprites,” I’m referring to the built-in sprite features of the VIC-II chip that have carried forward from the Commodore 64 to the MEGA65. Experienced game programmers would want me to point out that the general term “sprite” could apply to any kind of moveable graphics object, and there are, in fact, other ways to accomplish sprite-like effects on the MEGA65. We’ll have to cover those in later issues of the Digest.

    The best way to get to know Commodore sprites is to try out the commands! The new v0.96 release version of the MEGA65 ROM includes pre-defined sprite images for a mouse pointer and a simple line pattern, so you can get started without drawing any graphics. If you’re using the previous release, you can still switch on the sprites, you’ll just see a blob of pixels that represents uninitialized memory contents.

    Getting a sprite onto the screen

    The VIC chip can keep track of up to eight sprites at a time, numbered 0 through 7. Each sprite has a set of modes and flags, including a flag to enable or disable the sprite. You manage these flags with the SPRITE command.

    To turn on sprite 0:

    SPRITE 0,1

    Nothing appears to happen because the sprite starts located off the screen. Let’s move it roughly to the middle of the screen so we can see it (X=160, Y=120):

    MOVSPR 0,160,120

    While many of BASIC 65’s sprite commands originate with BASIC 7 and the Commodore 128, there are subtle differences. For example, on the C128, sprites are numbered 1 through 8. I won’t describe every difference here, just be aware that they’re not exactly the same on both computers.

    Pixels and colors

    In the default sprite mode (sometimes called “high resolution” mode), each sprite is 24 pixels wide and 21 pixels high, using a single sprite-assignable color for each “on” pixel (bit 1) and treating each “off” pixel (bit 0) as transparent. This is encoded as three bytes per row (8 bits per byte x 3 bytes = 24 pixels), for a total of 63 bytes (21 rows x 3 bytes per row) per sprite image.

    You can set the color of a sprite with the SPRITE command. You can omit any argument you don’t want to change by specifying just a comma. The color value refers to the palette entry, in this case the default system palette. To turn sprite 0 red (palette entry 2):

    SPRITE 0,,2

    On the MEGA65, you can change the system palette using the PALETTE COLOR command. Each palette entry can be any of 4096 possible colors, with a red, green, and blue component each between 0 and 15. This changes the palette entry for all uses of the color on the screen, not just sprites. To replace the red color at entry 2 with a bright green:

    PALETTE COLOR 2,12,15,4

    To restore the default palette:

    PALETTE RESTORE

    Multicolor mode

    If you’re willing to use a lower sprite resolution of 12 double-wide pixels per row instead of 24 single-wide pixels, you can set a sprite to multi-color mode, for two more additional colors. The two new colors must be shared by all sprites that are in multi-color mode. In this mode, sprite pixels are encoded as bit pairs: 00 for transparent, 10 for the sprite color, and 01 and 11 for the two shared colors.

    Let’s try setting sprite 0 to multi-color mode, using a value of 1 for the seventh argument to SPRITE:

    SPRITE 0,,,,,,1

    If you’re using a ROM beta version, the default mouse pointer image of sprite 0 might not look that impressive in multi-color mode. Try enabling sprite 1 and moving it to the middle of the screen, then put it in multicolor mode. The default image of sprite 1 is designed to illustrate multicolor mode, with a repeating pattern of 00, 01, 10, and 11 bit pairs. (If you’re using release v0.95’s ROM 920377 or earlier, you’re in luck: the garbage data that’s usually there typically has an interesting combination of bit pairs.)

    To set the two shared colors for the multicolor sprites, use the SPRCOLOR command, with the two palette entry numbers:

    SPRCOLOR 4,5

    Double width, double height

    Each sprite can be displayed normal size, double width, double height, or both double width and double height. The double modes don’t give you more pixels: instead, they stretch the existing sprite design in the requested dimension.

    These modes can be selected per sprite, and are the fifth and sixth arguments to the SPRITE command, respectively. Try the combinations of 0 and 1 for these arguments:

    SPRITE 0,,,,1,1

    Sprite priority

    Each sprite can be set to appear above the character or bitmap layer, or below it. When above, you can see the character or bitmap through the sprite’s transparent pixels.

    Use the cursor keys to move the text cursor to where the sprite is on the screen, then type some characters underneath it. On a blank line, set the fourth argument to SPRITE to 0 or 1, and see what happens:

    SPRITE 0,,,1

    When sprites overlap each other, lower numbered sprites are always in front of higher numbered sprites. This order cannot be changed. Use SPRITE to make sure two sprites are active, then use MOVSPR to locate them so that their images overlap.

    SPRITE 1,1MOVSPR 1,160,120

    Overlapping sprites is a common way to draw a high resolution graphics object using more than one color: just use more than one sprite to represent the object, and allow pixels of lower sprites to shine through the transparent pixels of upper sprites.

    Location, location, location

    A sprite can be located at any pixel location on the screen. A sprite’s location is specified as coordinates on the screen, where the sprite’s top-left corner is placed at that location. Coordinates extend to locations under the screen border, and a sprite that overlaps the border will be obscured. This allows a sprite to glide off the screen smoothly until it disappears. (Note that double-width sprites won’t fit completely under the left border.)

    To place a sprite exactly in the top-left corner of the screen just inside the border, set its coordinates to X=24 Y=50. If a sprite is in its normal display mode (with its double-width double-height features turned off), you can place the sprite’s bottom-right corner exactly at the bottom-right corner of the screen with coordinates X=321 Y=229.

    The VIC-II sprite coordinate system is independent of the resolution of the underlying screen mode. The MEGA65’s default 80-column text screen is actually 640 pixels wide. VIC-II sprite coordinates refer to the same locations regardless of the MEGA65 screen resolution. If you switch to the 40-column text mode, the sprites will remain where they are.

    Sprite coordinates are the same for both NTSC and PAL video modes. Even though these modes use different dimensions for the full screen, the dimensions inside the border are the same.

    We’ve already seen how the MOVSPR command can set a sprite to specific coordinates. This command has several other useful features. To move a sprite to a relative distance from its current location, use a + or - and an offset for the coordinate value (X, then Y):

    MOVSPR 0,+20,-10

    The MOVSPR command can animate the movement of a sprite at a given speed. This animation happens asynchronously to BASIC program execution, similar to the PLAY command for music: the animation occurs in the background while the rest of your code continues to run. To move a sprite from one coordinate pair to another, use the TO keyword, and provide a speed as a number of pixels per frame. Remember that PAL mode refreshes 50 frames per second, while NTSC mode refreshes 60 frames per second, so the movement speed differs based on video mode.

    MOVSPR 0,100,100 TO 250,200,5

    Note that the sprite needs to hit the end coordinate almost exactly for the sprite to stop. If the speed is not a multiple of the differences between the starting and ending coordinates, the sprite might overshoot its destination and wrap around the screen until it finally lands where it was told. If there’s a chance of this, you may need to resort to a loop that tests RSPPOS() and stops the sprite with another MOVSPR command when it is close enough.

    A sprite can be set to move continuously, with no fixed end coordinate. To do this, provide an angle as a number of degrees, with 0 degrees being “up” and proceeding clockwise, so 90 is right, 180 is down, and so forth. Follow this with a # symbol and the speed.

    MOVSPR 0,135#1

    The sprite will continue to move at this angle and speed until you set its speed to 0 with another MOVSPR command, or until you switch it off with the SPRITE command.

    MOVSPR 0,0#0

    When a moving sprite leaves the screen, it will continue to move until its position wraps around to the other side of the screen. If you want to test the position of the moving sprite, such as to stop its motion after it is off screen, use the RSPPOS() function. This takes the sprite number, and an argument identifying the parameter to return: 0 for the X position, 1 for the Y position, 2 for the speed.

    Here’s a short program that starts the sprite moving to the right, then stops it either when a key is pressed or the sprite leaves the screen:

    10 SPRITE 0,120 MOVSPR 0,100,10030 MOVSPR 0,90#140 GET A$50 X=RSPPOS(0,0)60 IF A$="" AND X < 345 THEN 4070 MOVSPR 0,0#0

    Collision detection

    The VIC chip can report when two sprites have non-transparent pixels on top of each other, or on top of the character or bitmap layer. Your program can use this to detect collisions between sprites, or between a sprite and the background, such as to know when a player’s bullet hits an alien ship, or when the player’s ship crashes into a mountain.

    BASIC 7 on the Commdoore 128 introduced an interesting mechanism for handling sprite collisions. To tell BASIC that you care about sprite collisions, you use the COLLISION command to indicate the type of collision (1 = sprite on sprite, 2 = sprite on background), followed by a line number of your BASIC program. At some later point, when the VIC detects the requested collision type, BASIC will stop whatever it is doing and jump to the given line number as if it were a GOSUB subroutine. Your code at this line number should do whatever it needs to do to react to the collision, then use the RETURN command to resume where the program left off.

    Your handler subroutine is called for any collision of the requested type. Your code will need to use other tests to determine which collision took place. The BUMP() function reports which sprites were involved in a collision since the last call to BUMP(). You can also use the RSPPOS() function to test individual sprite locations to further determine where the collision took place. See the User’s Guide for information on these functions.

    Try to guess what this program does, then type it in and run it:

    100 SCNCLR110 X=0120 SPRITE 0,1130 MOVSPR 0,100,100140 MOVSPR 0,90#1150 CURSOR 70,6160 PRINT "XXX"170 COLLISION 2,220180 GET A$190 IF A$="" AND X=0 THEN 180200 MOVSPR 0,0#0210 END220 PRINT "BLAMMO!"230 X=1240 RETURN

    The VIC’s built-in collision detection is not always the most reliable way to detect game events. Depending on the shapes of your sprites and other factors, you may prefer a different method to detect collisions, such as by testing sprite positions relative to a hitbox. To do this, instead of a COLLISION handler, you’d make repeated tests of RSPPOS() in your game’s main loop.

    Another caveat: There is a known issue with the VIC-IV core where sprite collisions are not detected with bitmap graphics (the BASIC 65 SCREEN system). Collisions are limited to sprite-to-sprite and sprite-to-text for now. Of course, there’s quite a bit you can do graphically in text mode using PETSCII graphics, and custom character sets with the CHARDEF command.

    Other sprite features?

    If you grew up with a Commodore 64, these sprite features probably feel quite familiar. The C128 sprite commands, and the C65 and MEGA65 additions, are handy, but the sprites themselves mostly look like they did on the VIC-II.

    For the VIC-III video chip in the Commodore 65, Commodore added no new features to sprites. Sprite colors use the VIC-III system palette, and you can adjust the colors of the system palette to any of 4096 possible colors. Otherwise, they’re basically the same as they’ve always been.

    The MEGA65’s VIC-IV adds advanced sprite features, such as a full-color mode with actual-size pixels, four palette banks, a 64-pixel width monochromatic mode, variable pixel height, and high resolution sprites that use the actual pixel width and coordinate system of a 640-wide (80-column) display. BASIC 65 does not yet support any of these features with the BASIC sprite commands. You can adjust VIC-IV registers directly with POKE statements, but this may interfere with the behavior of the BASIC commands. I’m currently working to extend BASIC 65 with official support for VIC-IV sprite features, so stay tuned for updates!

    Managing sprite image data

    Playing with the built-in sprites is fun and all, but for our own programs, we obviously want to draw our own sprite images.

    Using the Sprite Editor

    Did you know that the Commodore 128 has a built-in sprite editor? The C128’s SPRDEF command opens a sprite editor that directly manipulates the BASIC sprite image data in memory. For whatever reason, Commodore removed SPRDEF for BASIC 10. The good news is, the MEGA65 has its own sprite editor, “SpritEd,” built into the Freezer.

    Hold Restore for one second then release to open the Freezer, then press S to start the sprite editor. This utility edits sprite image data at the BASIC sprite locations in memory.

    A word of warning. SpritEd is currently unfinished software. Up to platform release v0.95, SpritEd crashes the machine if you press the Up Arrow key. I discovered this while writing this article, and I committed a fix to prevent this that will be in release v0.96. I recommend upgrading to release v0.96 before doing any serious work in SpritEd.

    SpritEd is missing a bunch of its intended features, such as the ability to load and save images to disk. Even without these features, it is about as useful as the C128’s SPRDEF tool, and can edit sprite image data in memory. We’ll see how to get sprite image data from memory into your program in the next section.

    Press the Help key for a list of keyboard controls. Briefly, these are as follows:

    * To select a drawing tool: P for single pixels, L for a line, X for a box, Shift-X for a filled box.

    * Press Space to draw with the selected tool. Del uses the tool with the background component, such as to erase a pixel.

    * To erase the entire sprite: Ctrl+N.

    * To select a “component” (color) to draw with: + and - rotate through the choices. In monochrome mode, this is just the background (transparent) and foreground. In VIC-II double-width multi-color mode, there are two additional components for the shared sprite colors.

    * To change the color of the currently selected component: 0 through 9, A through F assigns one of the sixteen palette entries to the component.

    * To select other sprites: comma (,) and period (.) rotate through the eight sprites.

    * To change the sprite mode: * rotates through monochrome, VIC-II multicolor, and VIC-IV multicolor modes. Remember that BASIC does not yet support VIC-IV multicolor mode directly, so this last mode won’t be useful until we finish the new features.

    * To see what your sprite looks like when expanded horizontally or vertically: use H and V to toggle these modes.

    SpritEd supports drawing with a mouse connected to port 1. I discovered a small bug where the mouse can’t draw in the rightmost column, which should be easy to fix in a future version.

    To exit SpritEd, press F11 to make sure the current sprite is saved to memory, then press F3 to exit back to the Freezer menu. Each sprite image is saved to memory automatically when you flip between the sprites, so F11 is only necessary on the current sprite, if it was modified. (That feels like something else we can improve pretty easily. Just know that’s how it works for now.)

    Storing sprite image data on disk

    The gorgeous sprite graphics we created in SpritEd are now in memory, but they’ll disappear forever if we don’t get them out of memory and onto disk. BASIC 65 makes this easy: SPRITE SAVE "filename" saves all eight sprite images to a file on disk. SPRITE LOAD "filename" loads them back in.

    This provides a POKE-free workflow for managing sprites for BASIC programs:

    * Create sprite images in the SpritEd utility. Press F11, then F3 to exit back to the Freezer menu, then F3 again to resume BASIC.

    * Execute the SPRITE SAVE "filename" command to save all eight sprite images to a file.

    * Then in the program, use the SPRITE LOAD "filename" command to load these images.

    Animating sprite images

    For a game like Space Invaders, a ship can be a single sprite image whose only animation is to move around the screen, such as with the MOVSPR command. For a game like Pac Man, the player sprite should open and close its mouth, which means updating the sprite’s image data. We can’t exactly load a new Pac Man from disk each time he opens and closes his mouth, so we need another way to update sprite data within the program.

    The SPRSAV command copies sprite data between sprite slots and BASIC string variables. It takes two arguments: the source and the destination. One or both of these can be a number between 0 and 7 to refer to the sprite image. If the other is a named string variable, the variable is used as either the source or destination.

    For example, to copy the image data from sprite 2 to the string variable C$:

    SPRSAV 2,C$

    To copy that image to sprite 5:

    SPRSAV C$,5

    Combined with SPRITE LOAD, you can use SPRSAV to load all of your sprite patterns into string variables, then store them back into sprite slots during game play as needed.

    You can also use string variables and SPRSAV along with disk operations as an alternative to SPRITE LOAD. For example, you can store more than eight patterns in a single file. Each pattern is 64 bytes in length. See any good reference on disk commands for more information.

    Putting it together

    Sprite Attack is a simple game I wrote to demonstrate how the sprite features can be used together. Get it here:

    * Sprite Attack: spratk.d81

    Try it out with a joystick in port 2. It’s written entirely in BASIC, so type LIST to see the program listing. A few notes:

    * I used SpritEd to draw eight multicolor sprites: the player’s spaceship, the player missiles, the space alien death ray, four frames of an explosion animation, and the space alien itself. I exited SpritEd and the Freezer, then used the command SPRITE SAVE "SPRATK.DAT" to save the sprite data to disk. The program starts by loading this file with SPRITE LOAD.

    * I keep the player’s X position in a variable so I can fine-tune the speed that the player moves. Pixel locations are always integers, but sometimes you want a sprite to move in non-integer increments, such as 1.8 pixels per frame. The variable holds the non-integer location, and this value is rounded to the nearest pixel when I pass it to the MOVSPR command.

    * The game loop tests for joystick movement, adjusts the variable, and updates the player location with MOVSPR. Because the player only moves left and right, I use +0 as the Y coordinate argument to MOVSPR so that I don’t have to remember the ship’s vertical position after initializing it.

    * I use the VSYNC command to synchronize gameplay with the frame rate. This makes it easier to tune the movement speeds, and it prevents the sprites from “tearing” by making sure the location doesn’t change while the sprite is being drawn.

    * Player missiles use the movement animation system. The RSPPOS() with a second argument of 2 returns the current speed of a sprite, so I can test whether the missiles are moving. If the button is pressed and the missiles aren’t moving, I set their position to just above the player ship and set them moving in an upward motion, then I activate the missiles sprite. I also test once per loop if the missiles have gone off the top of the screen, and if so, I stop their motion by setting their speed to zero.

    * The alien also uses movement animation. If the space alien is ever stationary (speed is 0), the program chooses a new random location, and calls MOVSPR with the current location as the origin and the random location as the destination. This gives the alien an evasive behavior that still gives the player a chance to target it with missiles.

    * A collision handler detects when the missiles are in contact with the alien. When the alien is hit, the routine moves the explosion sprite to the alien’s location, disables the missiles sprite, then moves the alien sprite to another random starting point above the screen. It plays out the explosion animation using SPRSAV to copy in the explosion patterns we saved into string variables earlier, pausing between each frame. This causes all gameplay to pause while the explosion finishes. A more sophisticated game would handle explosion animations in the main game loop, so other events like player movement can take place during the animation.

    This game is a little unfair—to the alien. Try extending this program to have the alien shoot back at the player, using its death ray in sprite 2.

    VIC hardware sprites and the BASIC 65 sprite commands are a fun and easy way to code video game graphics. Combine them with PETSCII graphics to draw level maps, backgrounds, and informational displays, and you have all of the elements of a great looking game. Be sure to share your games with other MEGA65 owners by uploading them to Filehost!

    There are some advanced sprite techniques I wanted to mention here, but they’ll have to wait for another issue. You can help make more issues possible by supporting the Digest on Ko-Fi.

    As always, happy coding!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • Zijn er afleveringen die ontbreken?

    Klik hier om de feed te vernieuwen.

  • It’s time! We have a shipping schedule for the next batch of MEGA65 computers, and a candidate for the next platform release. Everyone is invited to help with testing, so let’s get to it!

    Shipping update!

    Trenz Electronic has announced that the next batch of MEGA65 computers will ship on June 1st, 2024.

    We currently expect that all preorders up to this point will be included in this batch. If you need to make adjustments to your preorder before then, contact [email protected].

    Once we clear the preorders, remaining stock will become available for purchase in the Trenz Electronic store, while supplies last.

    Please bear with us while we work through any last minute issues that might change these estimates. And thank you so much for your patience! I can’t wait for you to receive your MEGA65!

    v0.96 release candidate now available to test!

    To make the new delivery schedule, we need to hand over the gold masters of the next release of the MEGA65 firmware and system software, as well as the updated User’s Guide, to Trenz Electronic by January 31st. Release v0.96 of the firmware, ROM, and system software will be installed at the factory on all MEGA65s about to ship. Of course, it will also be available as a free upgrade for all existing MEGA65s. This next release has a ton of new features and bug fixes—and we need testers!

    If you have a MEGA65, you can install the release candidate on your machine to help test. If you don’t have a MEGA65 yet, you can still help by testing the new version of the ROM with an updated version of the Xemu emulator.

    Testing the release candidate on a MEGA65

    To begin, be sure to back up your SD card, or use an alternate SD card, before proceeding with testing. I usually just move the SD card to my PC, then copy all of the files from the SD card into a folder on my desktop. This doesn’t back up the configuration or Freeze states, but personally I don't keep important freeze states around long term. Alternatively, you could also use a disk imaging utility to back up both the hidden configuration partition and the files partition.

    If you’re using a fresh SD card for testing, remember to prepare the card first using the MEGA65’s SD Card Utility. Insert the card in your MEGA65, hold the Alt key while switching on the computer, then select the utility from the menu and follow the prompts. This erases all data on the card.

    Here’s how to get the files for the release candidate:

    * Release v0.96 RC core and system software. Select the latest build that begins with mega65r3-r-0.96, such as mega65r3-r-0.96-build-5.7z. The “r3” refers to all MEGA65s delivered up to this point. The MEGA65s shipping in June will be known as “r6.” Yes, we’re skipping R5 after all: we found one small non-electrical change needed for the board during R5 testing.

    * Release v0.96 RC ROM. Sign in with your Filehost account with your owner code redeemed to access this. Download the most recent version: 920391.bin.

    * MEGA65 command line tools: Windows, Mac, or Linux. These will be bundled with, and be the basis for, an upcoming version of the M65Connect app, and are generally useful on their own for the new Ethernet file transfer feature.

    * The MEGA65 User’s Guide, 2nd edition (PDF).

    Unpack the mega65r3-r-0.96-build-5.7z archive. Transfer the .cor file to the root of your SD card. Open the sdcard-files folder, and copy its contents (.M65 files) to the root of the SD card as well.

    Rename 920391.bin to mega65.rom, and transfer it to the root of your SD card.

    Install the SD card in your MEGA65. With the power switched off, hold No Scroll then switch on the computer. This opens the core selection menu. Hold the Ctrl key and press a number to select an appropriate core slot for the new core, then follow the prompts to select the .cor file and flash the core. See the User’s Guide for more information about upgrading cores.

    Using both the release candidate and the previous stable release with one MEGA65

    I recommend keeping both the release candidate and the previous stable release installed during testing. If you find any issues with the release candidate, it will be important to determine if those issues also exist with the previous stable release, or if they are new issues introduced by a recent change.

    Choose one or the other to be the default for your computer. Flash the core you wish to be the default to core slot 1, and name the default ROM as mega65.rom on the SD card. For the non-default release, flash the core to slot 2, and name the ROM file as mega652.rom. To start the non-default release (whichever one you chose), hold No Scroll while switching on the computer to open the core selection menu, then press and hold the number 2 until you see the READY. prompt (and probably a bunch of 2’s). This selects core slot 2 and also selects mega652.rom.

    There’s one tricky bit with a dual installation: you can only have one set of system software on the SD card. I have not had any issues running the new system software with the previous stable core and ROM, so my recommendation is to go ahead and use the release candidate system software as the system files on your SD card.

    It’s important to note that the release candidate ROM only works with the release candidate core. If you accidentally select the release candidate ROM (version 920391) and the previous stable release core, typing won’t work correctly and you’ll see the cursor disappear. If this happens, switch off the computer, hold No Scroll while switching it back on, then select a matching core and ROM. You can use the previous ROM (version 920377) with the new core, just not the other way around.

    You can confirm that you’re running the release that you intend with the new MEGAINFO utility. Open the Freezer—hold the Restore key for a second, then release—then press the Help key. This is a feature of the new system software, and it works with either release as long as the new release’s system software is on the SD card.

    Testing the candidate ROM in Xemu

    If you do not have a MEGA65, you can still help test the ROM in the Xemu emulator. Get these files:

    * Release v0.96 RC ROM patch. Follow the instructions in the ROM FAQ to put together the MEGA65 ROM 920391 using the free C64 Forever download from Cloanto.

    * Xemu “next” release. Look at the bottom of the page for “The ‘future next stable’ still unstable (“next” branch) builds” for your platform. Download and install.

    * The MEGA65 User’s Guide, 2nd edition PDF.

    Run xmega65, and when prompted for a ROM, use the new ROM.

    Just as the release candidate ROM (version 920391) depends on the release candidate core, it also depends on the “next” version of Xemu. If you try to use the new ROM with the previous stable version of Xemu, you will notice problems with typing.

    What to test

    This release is the culmination of 15 months of improvements and fixes across the board. Changes to the ROM are listed in the ROM change log. Changes to the core are numerous and we’re still assembling the core change log, but here are a few notable features:

    * Ethernet file transfer. See the updated User’s Guide or this wiki page for instructions on how to transfer files between your PC and the MEGA65 using just an Ethernet cable. Notice that this requires flipping a small switch on the mainboard, so you will need to open your MEGA65’s case.

    * Hardware accelerated typing. You should notice that typing at the READY. prompt and in most apps is more accurate, especially for fast typists. This should not affect MEGA65 software in any other way.

    * Improvements to mouse handling, with smoother motion and support for mouse and paddles in port 2.

    * Coming soon: New core flashing capabilities—and a way to flash slot 0. The special core slot 0 controls aspects of the MEGA65 boot process, and it is intentionally more difficult to flash so you always have the factory-installed MEGA65 core available. With this release, there will be a new way to update the core in slot 0 to claim the benefits of improvements made to the boot process. As of this writing, this feature is not yet in the release candidate. Stay tuned to the Discord for an announcement of when and how to test this.

    * Coming soon: Configurable cartridge booting. Flashing this core to slot 0 enables the ability to configure the boot process to use a specific core when a type of Commodore cartridge is connected. This is primarily so you can assign C64 cartridges to the C64 core, instead of the less capable GO64 mode of the MEGA65 core and ROM. This change also introduces a new cartridge signature and boot protocol for MEGA65 cartridges, though you’ll need an EasyFlash 1CR cartridge and a test image to test it.

    In addition to testing new features, we want to know about anything that worked in the last stable release and appears to have stopped working in the new release candidate (called “regressions” in software engineering parlance). This includes, but is not limited to:

    * Your favorite MEGA65 games, apps, and utilities

    * BASIC commands and features

    * The core menu, core flashing, configuration, “on-boarding,” and the SD card utility

    * The Freezer, and features accessible from the Freezer menu

    * Procedures and information described in the User’s Guide, 2nd edition

    * Anything that worked in GO64 mode with the previous stable release

    How to report issues

    There are two ways to report any bugs you find. We have an active thread on the Discord for collecting release candidate bugs. Look for the platform-testing forum. Alternatively, you can file issues directly to the Github repo for the core, the repo for the ROM, or the repo for the User’s Guide. If you’re not sure where the bug goes, file it in the core repo, and we’ll triage.

    If you find something that doesn’t look right, try to reproduce it in the previous release. File a bug either way, and make sure to note whether this only happens in the release candidate, or if it happens in both versions.

    Many thanks to everyone who is available to test! We’re on a tight schedule, so anything you can do before the end of January would be a huge help.

    About that User’s Guide


    Every MEGA65 includes a printed version of the MEGA65 User’s Guide, a book that includes set-up instructions, common procedures, an introduction to BASIC programming, and a BASIC command reference. We printed a large quantity of the 1st edition, and everyone who has received a MEGA65 so far has this edition. We can’t afford not to use the remaining stock, so we will be including copies of the 1st edition with some MEGA65s that will ship in June.

    The User’s Guide has been revised with new material on new features like Ethernet file transfer, and a renewed focus on non-developer activities like using virtual disk images and upgrading the firmware. The entire Guide has been polished with corrections, and the BASIC reference has been updated to include the most recently added features. We’re calling this the “2nd edition,” and we will be printing new Guides to include with MEGA65s after the stock of the 1st edition is depleted.

    Do you want a printed copy of the 2nd edition? I know I do! I’m working on setting up the User’s Guide, 2nd edition with a print-on-demand service, so anyone who wants an updated printed Guide can get one. Whether you have the 1st edition and want to upgrade, or you’re just enjoying Xemu and want a book to go with it, you’ll be able to order a copy.

    I’ll share the link to the purchase page in the next issue of this Digest. We’re using the release testing period to catch any last minute bugs in the Guide, and to make sure it matches the new slot 0 flashing procedure when it is finished. In the meantime, you can always download the latest draft PDF of The MEGA65 User’s Guide. (And report bugs!)

    The 8-Bit Guy, and me!

    YouTuber David Murray, aka “The 8-Bit Guy,” made a video about the Commodore 65 last December, borrowing Bo Zimmerman’s vintage C65 prototype to try it out. At the end of the video, David mentioned the MEGA65, mostly to say that he knew about the project but didn’t know anything about it. There were multiple attempts to get a review unit to David that fizzled out for one reason or another. When I saw that, I thought to myself, what can I do to help? I suppose I could
 just go down to Texas and bring my MEGA65 with me. So I did!

    Behold, the 8-Bit Guy’s video about the MEGA65, with special guest, me!

    David is a co-founder of the Commander X16 project, a retro fantasy hardware project with similar interests to the MEGA65. Based on the 65C02 CPU, the X16 has a Commodore-like architecture and uses a Commodore-derived KERNAL and BASIC, while updating other aspects of the design to use readily available components and interfaces. Check out the X16 FAQ for details, and give the in-browser emulator a try.

    Many thanks to David for hosting me and for appreciating the MEGA65. Thanks also to my Ko-fi supporters and to the MEGA65 team who helped make this possible.

    Yes, your support of this Digest on Ko-fi is already making new things happen! If you would like to support the Digest and my involvement with the MEGA65 team, please visit: ko-fi.com/dddaaannn

    Back again next month with more news, and more fun things to do with your favorite computer. Cheers!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • Our robotfindskitten adventure continues! In part 1, we introduced the robotfindskitten experience, and described tools and techniques for building an rfk game in BASIC 65. In part 2, we started building a similar toolkit in assembly language, starting with KERNAL routines, memory access techniques, and screen memory registers. This month, we complete the toolkit, and I present my own attempt at an assembly language version of the game.

    But first, a whole bunch of new stuff!

    R5 main board in testing!

    The new R5 main board test units have arrived and Paul has started the “bring-up” process, adapting the FPGA core to the design changes. With some minor corrections to the assembly, this should resemble the main boards that will ship with new MEGA65s going forward, including all pending pre-orders. Many thanks to Paul, Trenz Electronic, and the hardware testing team for the work they are doing.

    Unicone, by deathy

    deathy has another new game release! In Unicone, you are chasing a unicorn that poops ice cream. Move your ice cream cone left and right to catch falling ice cream scoops dropped by the unicorn. A fun game in the tradition of Kaboom! (or its lesser known ancestor, Avalanche), Unicone features high resolution graphics, sampled sounds, a wide variety of control schemes, and a unique ice cream balancing mechanic for extra challenge in later levels. Download Unicode from Filehost.

    Want to see how it works? deathy has generously released the C source code to Unicone using an open source license, and the assets using a Creative Commons license. The code builds with the Calypsi C cross-compiler, a modern retro development suite by hth313 that recently added support for the MEGA65’s 45GS02 CPU. Check it out!

    The Ghosts of Blackwood Manor, by Stefan Vogt

    Stefan Vogt, the author of the adventure games Hibernated and The Curse of Rabenstein, has a new adventure out for multiple platforms including the MEGA65. The Ghosts of Blackwood Manor is an interactive horror game with three possible outcomes, and each outcome fills out the story.

    And of course, Ghosts is getting another gorgeous boxed release from poly.play! Pre-order the boxed release, and get it digitally right now for a donation of your choice.

    Gurce’s BASIC 65 Dev Vlogs

    Gurce has been doing a series of live stream development vlogs coding a game from scratch in BASIC 65, using the Eleven programming environment. The game, currently titled “Way of the Imploding Foot” (or just “MegaFoot” for short), is a side-view fighting game, featuring low resolution block character graphics, animated fighting characters, and parallax scrolling.

    You can start with episode 1, and subscribe to find out about new live streams. Also check out the Github repository for the game, or just try the latest D81 disk image. When browsing the repo, be sure to locate the .ELPC files (such as FOOT.ELPC), which contain the code in Eleven syntax viewable as a text file on a PC.

    Gurce is welcoming contributions on this project! If you’d like to try implementing a feature in BASIC using Eleven, let Gurce know on the Discord.

    Discord upgrade!

    The MEGA65 Discord is the MEGA65 community’s real-time meeting spot, a great place to ask questions, show off your projects, and meet other MEGA65 enthusiasts. Thanks to MEGA65 Discord moderator KiDra, the Discord now has a fresh new structure and some really cool new features! Here are just a few highlights:

    * New section layout. Channels and resources are now organized in sections based on how you engage with the project, such as regular use, programming, and platform development. Click or tap a section title to collapse sections you use less often.

    * Discord forums. Sections now include Discord forums in addition to text chat channels. Forums are especially useful for asking technical questions: each question stays visible in a list, and answers and discussions stay organized by topic. Once you have the answer you need, you can close the discussion, and it stays in Discord search history for others to find.

    * Voice/video rooms. Sometimes it’s just easier to talk, you know? Hop into a voice room to start an audio or video chat. Show off your work, collaborate on a project, or just hang out.

    * The Pin-Board. All of the most important community resources in one well-organized section! Announcements, official project status, and links to resources.

    * Events. Want to organize a club meeting, schedule an online conference, or throw a party? Let everyone know by posting an event! Everyone will be able to express interest in your event and request an automated reminder when the event draws near.

    * Self-service posting roles. To help keep the announcements and events channels clean and on-topic, we ask that anyone who wishes to post to them read a brief description of how they are used, in the #role-setup channel. Acknowledging the description grants permission to post, automatically.

    * Starred posts. Did someone post something you think more people should see? Give it a ⭐ reaction emoji! If enough people star the post, it will be advertised in the #starred-posts channel. This works from any public channel.

    * Project channels. These discussion channels for specific MEGA65 projects by the community can be used for collaboration, on-going user support, or just dev logging and rubber ducking by the project developers. Want a channel for your project? Propose one in the #signup channel.

    We will continue to evolve and improve the Discord based on the needs of the community. If you have any feedback or questions on the new layout and features, feel free to discuss it in the #mega65 channel, or contact anyone on the admin team. Thanks again to KiDra for setting all of this up!

    Bad Apple
 in BASIC?!?

    As a follow-up to MEGApple, MirageBD’s high fidelity Bad Apple demo for the MEGA65, Nobato has a new version, this time in BASIC65! Bad Basic65 Apple Demo comes on multiple D81 disk images and can swap disks automatically from the SD card. The music is an original SID arrangement, using BASIC65 PLAY statements.

    Boot B65APPL1.D81 to start. It takes a few minutes to load and decompress data into upper RAM—this is all in BASIC, remember—but once it begins, it runs smoothly, start to finish.

    Don’t miss the Little Bad Basic65 Apple bonus disk, also included in the archive!

    45GS02 assembly language mousepads and posters

    A couple of weeks ago, I mentioned that I designed a 45GS02 assembly language quick reference, and you can purchase this design as a mousepad or a poster. Many thanks to everyone who has ordered a mousepad or poster so far! Proceeds go to supporting this Digest and my other work on the MEGA65 project.

    I especially like how the mousepad turned out. It’s fun to look at, I can keep it on my desk as a mousepad, and it’s actually useful as a quick reference for MEGA65 assembly language programming. I just used it a couple of days ago to remind myself how the stack-related instructions work.

    I’m using Zazzle to make and distribute these. They ship worldwide, and the shipping rates seem reasonable, only about 10 euros to ship the mousepad to Germany. I’ve had one report that there were technical issues trying to pay with PayPal. They also support credit cards. If you have issues, let me know, and I can try to figure it out.

    The mousepad is a perfect companion for our robotfindskitten project. Speaking of which


    Finishing robotfindskitten in assembly language

    To complete our robotfindskitten program in assembly language, we need to accept keyboard input, generate random numbers, de-duplicate choices, pause to animate the (very simple) ending sequence, and select from the list of item descriptions.

    Accepting keyboard input from the KERNAL

    A common way for a program to accept keyboard input is another KERNAL routine, getin at $FFE4. This loads a PETSCII code into the Accumulator if a key has been pressed, or 0 if not. This isn’t necessarily the best method for using the keyboard as a game controller, because it includes typing features like key repeat. But it’s easy to use, and for rfk, the built-in key repeat is reasonable behavior.

    getin = $ffe4; ...- jsr getin beq - cmp #17 beq cursor_down ; ...cursor_down: ; ...

    In older versions of the ROM, the getin routine uses CIA registers to scan the keyboard. With the latest beta test version of the core and ROM that I mentioned last month, getin uses a new typing event queue implemented in hardware for greater accuracy. Your program will get the same result from either version: the pre-conditions and post-conditions of getin have not changed.

    A program that doesn’t use the KERNAL can access the new hardware registers directly, or can implement its own keyboard scanner based on the CIA chips. See a Commodore 64 reference for information on how to do that.

    getin also supports features like the function key macros and input redirection, which don’t apply to a game but could come in handy for other types of programs. getin and chrout are both part of the KERNAL’s input-output system, of which the screen and keyboard are only two possible devices.

    Chaos

    We need a way to select randomized locations and appearances for the items. In BASIC, we used the RND() function for this purpose. What can we do from assembly language?

    The MEGA65 has a dedicated hardware register that produces random values. To use it, a program must loop to wait for a “not ready” flag to clear, then read the generated random number from a register. The act of reading the number restarts the process, setting the “not ready” flag while it works on a new number. Internally, the number generator is using a fluctuating oscillator to generate values, and it needs a brief amount of time between reads to produce good results.

    random = $d7efrandom_ready = $d7fe ; bit 7; ...- bit random_ready bmi - lda random ; A is a random number between 0 and 255

    Important note: If you test your software in the Xemu emulator, be sure to use the “next” branch release. As of this writing, the random number register implementation is not in the latest stable release, and the ready-wait loop will never exit.

    The distribution of values returned by this register is even across all possible byte values 0 to 255. Because this distribution is over a range sized by a power of two, you can reduce the range to a smaller power of two by ignoring some of the bits. For example, to get a random value from an even distribution of 0 to 63, use the and instruction to set the upper two bits to 0:

    and #%00111111 ; A is a random number between 0 and 63

    If the range size is not a power of two, it is feasible to simply “re-roll” for a number within the desired range. This causes all picks outside the range to be distributed evenly across the desired range, so it does not skew the results. Of course, this can take an arbitrary number of tries to roll a value in range, so you can speed this up by combining both techniques: get a number 0 to 255, zero out the unused bits, then test whether the result is in range and re-roll if not.

    - bit random_ready bmi - lda random ; 0 to 255 and #%01111111 ; 0 to 127 cmp #80 bcs - ; A is now a random number between 0 and 79

    To get a random number larger than 255, fetch two random numbers and treat them as a single 16-bit number. You can use similar techniques to narrow the range.

    Another option is to implement a pseudorandom number generator in your own code. Such algorithms range in power and complexity and can be difficult to get right, but applications like simple games can often get by with something as simple as a linear-feedback shift register (LFSR). Pseudorandom number algorithms generate a sequence of numbers based a starting number, known as the seed. It can be an advantage during testing to use a known seed to get a predictable result. For the final program, you can use another source of randomness, such as the hardware random number register, to determine the seed.

    If you’d like to try this, read the Wikipedia page on LFSRs carefully. See also this video from Retro Game Mechanics Explained on how the game Super Mario Bros. 3 nerfs its card shuffling algorithm by misusing an LFSR, apparently accidentally.

    Avoiding duplicates

    When we discussed random selection in BASIC last month, we put in some extra effort to store all previous choices in an array, and re-rolled the dice when we accidentally chose an already-selected character, location, or description. This ensured that no two items would be placed on the same location, which would not only appear as fewer items on the screen but might cause the kitten to be hidden by another item. Depending on how it was implemented, the robot might touch the location and only see the Non-Kitten Item even if the kitten was also at the same location. Ensuring diverse characters and descriptions also maintains variety in the gameplay, to avoid the disappointment of seeing the same description more than once in a game.

    The assembly language version of this isn’t different, it’s just a bit more cumbersome than in BASIC. I allocated some array-like memory within the program’s memory space for this purpose, like so:

    num_items = 20 ; max 127item_description: !fill num_items*2item_screen_code: !fill num_itemsitem_x: !fill num_itemsitem_y: !fill num_items

    (Alternatively I could have put this on the base page, or elsewhere between $1700 and $19FF, which is available for program use.)

    I wrote three assembly language routines that detect whether the value at position X is equal to the value at any position 0 through X-1, the idea being that as I fill the array from position 0 upward, I can check each item against the previous items. I needed three routines because each value is stored in a different way: characters are stored as one-byte screen codes, descriptions are stored as two-byte addresses (which we’ll see more of later in this article), and coordinates are stored as coordinate pairs in two separate lists.

    Here’s the simplest of the three routines I came up with that checks for duplicate screen codes:

    addrl = $00addrh = $01vall = $02is_unique_byte: ; Y,Z: starting address of byte set ; X: index of last item ; Returns: Carry Set if item at X appears elsewhere in the set cpx #0 beq @is_unique sty addrl stz addrh txa tay lda (addrl),y sta vall- dey lda (addrl),y cmp vall beq @is_not_unique cpy #0 bne -@is_unique clc bra @end@is_not_unique sec@end rts

    A few notes:

    * The routine accepts the starting address of item_screen_code in the Y and Z registers. I could have hard-coded the address into the routine, but this way I could potentially re-use it with a different array, or in another program.

    * It uses the Carry flag as the return value, where Carry is set if a duplicate is found. The routine is not responsible for choosing new random values or updating any memory. It’s important to separate responsibilities between routines to make code easier to write, test, and re-use.

    * It uses base page variables and indirect indexing (via the Y register) to access the array and remember the value under test. 6502-style CPUs have very few registers, so programs must rely on the base page (or the stack) to wrangle variables.

    * With the Acme assembler, a symbol whose name starts with an @ character is a “cheap local:” it is only valid between two global symbols (such as is_unique_byte). This way I can re-use these symbol names in my other duplicate test routines.

    These routines were challenging to get right! The algorithm isn’t complicated, but one errant instruction can cause all kinds of havoc. I found it useful to insert a brk instruction early in my program so that it would open the MEGA65 Monitor. From here, I would test these routines by writing values into the arrays, setting the registers, calling the routines, and inspecting the Carry flag.

    To do this, I needed to determine the raw addresses of the routines and the arrays assigned by the assembler. You can tell Acme to generate a report of all of the addresses it used throughout the program, using the -r command line argument:

    acme -r rfk_report.txt rfk.asm

    The monitor commands r and m inspect registers and memory, respectively. To update values, you can move the cursor up to the lines that these commands print, change a value, then press Return. (Remember that addresses and values are in hexadecimal.) To call a subroutine, use the j command. See my tutorial on the MEGA65 Monitor, as well as appendix M of the manual, for more information.

    Avoiding other bad choices

    There are two more cases of bad item placement worth considering, at least briefly.

    The robot also appears on the playfield along with the items. We need to make sure that an item doesn’t land on the robot’s starting position. My solution is crude but effective: I put the robot in the upper left corner of the playfield, then limit item placement to be within a one-tile border. This way, there is never an item where the robot starts, and the robot can move unimpeded around the entire edge of the playfield.

    With items placed entirely at random within the border, it is possible, however unlikely, that four items might surround a fifth item. And if that fifth item is the kitten, then the robot will never be able to find it! Tragedy! I admit, I did not bother to solve for this edge case in my implementations, but it’s worth thinking about how this might be solved. One way is to test a chosen item location for surrounding items, and re-roll if a bad case is noticed. A complete solution would have to handle extremely unlikely cases like 19 items forming a wall around the kitten, and would probably involve path finding algorithms or other magicks.

    A simpler solution is to only place items on odd numbered rows and columns. For example, within an 80-column width, pick a number from 0 to 38, double it, then add one. This produces a column coordinate from 1 to 77 and guarantees at least a one-space gap between items. Do the same for the row coordinate, and the robot is assured a clear path to every item.

    Calm

    One of the responsibilities of the CIA chips is to keep track of time. For coarse-grained timing, the CIA has a built-in “time of day” clock that counts up by tenths of a second. If your main loop executes faster than ten times per second, you can count upwards by tenths of a second simply by testing for when register $DC08 changes. The bottom four bits are a “binary-coded decimal” value between 0 and 9, representing the tenths-of-seconds value of the CIA’s clock. This can be a bit crude because you might be testing the register just before it ticks, so the actual delay might be off by as much as one tenth of a second.

    todtenths = $dc08wait_briefly: lda todtenths sta last_todtenths- lda todtenths cmp last_todtenths beq - sta last_todtenths- lda todtenths ; Wait two ticks to pause between 1/10th ; and 2/10ths of a second cmp last_todtenths beq - rtslast_todtenths: !byte $00

    You can achieve a more precise wait loop delay using a feature of the VIC video chip. The VIC uses a finely-tuned high speed mechanism to describe the entire screen to a connected display many times per second, one line at a time from top to bottom, known as the raster scan. The current raster line number is stored in the RC register, as nine bits: bits 0 through 7 are at address $D012, and bit 8 of the number is stored as bit 7 at address $D011. In the same way that you can wait for the CIA TOD tenths register to change, you can wait for these register values to change for much shorter durations.

    wait_very_briefly: ; Wait for bit 8 of the raster count to flip negative then positive, ; for a delay between 1 and 2 frames.- bit $d011 bpl -- bit $d011 bmi - rts

    The tricky bit (because there’s always a tricky bit) is that the number of raster lines and the rate at which the screen is drawn differs depending on the video mode of the MEGA65. Back in the day, PAL and NTSC were competing standards for analog video signals, used for both transmission and rendering on cathode ray tube (CRT) displays. Commodore sold computers with different VIC chips in different regions to be compatible with the technical standard used in the region for televisions. As a result, Commodore games that used raster-based timing ran differently depending on which VIC chip was in the machine. A game might animate slower or faster than was intended, or it might play music at a different speed. In other cases, a game would only function correctly with one kind of VIC chip, and just trip over itself when running with mismatched VIC timing.

    The MEGA65’s VIC-IV chip can generate PAL-like or NTSC-like video signals, as separate modes. Some MEGA65 owners are using displays (vintage or modern) that only support one of the modes. I asked everyone about their display modes in the 2023 survey, and 81% of the MEGA65 owners that responded have their video mode set to PAL by default, vs. 18% set to NTSC. Modern digital displays can often support both modes, but only 56% of owners were confident that their display could do this. A program can force the MEGA65 into one mode or the other using registers, but it’s best to leave it in the mode selected by the user in the configuration or Freezer menu.

    The upshot is this:

    * In PAL mode, the RC register counts up to 312 raster lines, at a rate of 50 times per second (50 Hz).

    * In NTSC mode, the RC register counts up to 263 raster lines, at a rate of 60 times per second (60 Hz).

    The actual image size is twice this many lines, fully refreshed at half these rates. The full image is drawn interlaced, with odd lines and even lines alternating with each refresh. 50 Hz or 60 Hz is the refresh rate; 25 Hz or 30 Hz is the frame rate.

    It is possible for a program to achieve precision timing independently of video mode using the CIA chips and a system feature known as interrupt handling. Interrupts can also be used for raster-based timing. High speed games are most likely to use raster-based interrupts for timing because it makes it easier to control screen updates, and they will either live with the consequences of the different video modes, or use sophisticated techniques to work around them. Interrupts are a big topic, so we’ll leave that for another Digest.

    robotfindskitten doesn’t need precise timing for anything, so raster timing is overkill in this case. I use CIA TOD tenths to add a simple delay to my found-kitten experience, and otherwise rely exclusively on keyboard events (and delays introduced by the key repeat handler) to drive the gameplay logic.

    Data

    We’re almost done! We have all the tools we need to display messages, choose and place items, animate the robot, move the robot based on keyboard input, and check for item interactions and the win condition. We just need a way to store, select, and display the 400+ possible item descriptions.

    We’ve already seen how to add the bytes of a text message to the program in Acme, and to assign a label to its address:

    message: !pet "\"I pity the fool who mistakes me for kitten!\", sez Mr. T.",0

    What we need is a way to select from a table of messages by an index. For my robotfindskitten implementation, I used a Python script that reads the NKI descriptions from a text file, and generates !pet directives for all of them, with labels such as i1, i2, and so on. The script also generates an address look-up table with all of the generated labels in it. This puts the starting address of each description into memory at regular two-byte intervals. The program can find the description for a given index by multiplying the index by two (the asl instruction will do the trick), adding it to the address of the lookup table (nki_table), then reading the description start address from that location. Each description ends with a 0 byte, so the message printing routine knows where to stop.

    nki_desc_count_mask = $01ffnki_desc_count = 401nki_table:!16 i0,i1,i2,i3,i4,i5,i6,i7!16 i8,i9,i10,i11,i12,i13,i14,i15; ...i0: !pet "\"I pity the fool who mistakes me for kitten!\", sez Mr. T.",0i1: !pet "That's just an old tin can.",0i2: !pet "It's an altar to the horse god.",0; ...

    Here’s the full procedure for assigning a unique description to a Non-Kitten Item, using the techniques we’ve discussed:

    * For each item, use the random number register to generate 16 bits (two bytes).

    * Apply a bitmask to cut down this 16-bit value to a 9-bit value, the smallest mask that would account for the maximum number of descriptions (512 > 401).

    * Compare the result to the actual maximum number of descriptions, and re-roll until the selected number is within range. This is the description index.

    * Multiply the index by two to get the offset into the lookup table. Add this to the lookup table’s starting address.

    * Read the description starting address from the lookup table at that location.

    * Store the description address in the item_description array, then test whether it is a duplicate. If so, start again from step 1.

    Using tools and scripts to generate data embedded in a machine code program like this is an essential skill, especially for games. Some assemblers have powerful directives that make embedding and manipulating data easy, such as Acme’s !binary directive that pulls in binary data from a file. Kick Assembler’s inline scripting capabilities are especially impressive. I find it useful to know a modern scripting language like Python so I can write my own data conversion tools that generate either assembly code or binary data that can be embedded in my programs.

    If you don’t want to write your own scripts to generate the NKI description table, you can borrow the source code for my version, linked below.

    The final robotfindskitten program

    Here are my final versions of robotfindskitten for the MEGA65, in both BASIC and assembly language:

    * rfk-bas.prg : robotfindskitten in BASIC 65; BASIC source code in petcat format

    * rfk-asm.prg : robotfindsktiten in MEGA65 assembly language; assembly language source code for the Acme assembler

    I don’t claim that either of these are the best possible versions of this program. If you find ways that either of these can be improved, or if you have used different designs or techniques in your program, please let me know!

    Whew! That’s a whirlwind of programming topics for three Digest issues. Hopefully this is enough for you to get started writing a robotfindskitten of your own, or extending these ideas to making other kinds of games. For example, you could add a system of walls or a maze generator to make locating items more challenging. Or, you could add other non-player robots that move when the player does, attempting to interfere with the search. Maybe when a non-player robot encounters an item, the item gets relocated on the playfield! It’d be a much less zen experience, but more like a game.

    Huge thanks to everyone who has jumped in to support the Digest on Ko-fi so far! We’re off to a good start to funding the Digest through 2024. If you would like to become a supporter, visit: https://ko-fi.com/dddaaannn

    See you next year!



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • Last month’s Digest introduced robotfindskitten, a programming exercise that unites several major concepts of game programming: updating the display, reading user input, generating random values, timing events, and including and manipulating large amounts of static game data. I offered examples of each of these tasks in BASIC 65, and proposed that these could be used to make a robotfindskitten experience for the MEGA65.

    In this issue, I want to start reviewing these topics again in assembly language. Without BASIC’s help, the program will need to turn to hardware registers and low-level programming techniques to achieve similar effects. Some of these topics are too large for a single newsletter, so we’ll take this in two parts. I’ll try to keep things simple by limiting this to just the needs of a robotfindskitten program. Applications that require higher speed or more memory may need more sophisticated techniques.

    This month’s Digest will focus on using the KERNAL, printing messages, and drawing characters to the screen—barely scratching the surface of the MEGA65’s graphics capabilities. Next month, we’ll finish robotfindskitten in assembly language with random values, user input, item descriptions, and a simple animation delay.

    Shipping update

    The work continues to finalize the new R5 main board hardware for the next delivery batch of computers. Getting the test hardware has taken longer than anticipated, and we are now expecting manufacturing lead times to put the batch #3 delivery in early 2024.

    Importantly, the team has decided to proceed with the full verification process for the new design, and not skip any steps just to accelerate the schedule. The MEGA65 is manufactured in small volumes in a not-for-profit operation, so we can’t afford to rush the process and risk having to re-make and replace hardware. We want every computer delivered to be as high in quality as possible.

    Some pre-orders have been pending for a very long time now, and we thank you for your patience! If you have a pending pre-order and need to make changes, contact Trenz Electronic customer support.

    Tristam Island

    Tristam Island, by Hugo Labrande, is a new text adventure game for multiple platforms, including the MEGA65. You can get the deluxe boxed edition, from publisher poly.play for 35 EUR. The deluxe edition includes the game on 3.5" floppy disk and on microSD card, a hint book, immersive props such as a rock sample and a postcard, and more. You can also get the digital-only edition for $3.99 USD.

    Thanks to Hugo for the great game and for supporting the MEGA65, and to poly.play for publishing fun collectible boxed software for our favorite platform!

    Updated ZX Spectrum core

    Did you know that you can turn your MEGA65 into a ZX Spectrum? You can, with the ZX Spectrum core! This core just received a major overhaul to use the MiSTer2MEGA65 framework, and now works with modern displays.

    Download the ZX Spectrum core from Filehost, then follow these detailed instructions for set-up and enjoyment. The core expects certain files in specific locations on the SD card, and uses ESXDOS v0.8.8 (not v0.8.9) for SD card access. It can load .tap and .trd files.

    Once again thanks to sy2002 and MJoergen for their amazing work on setting up the MEGA65 for retro core success!

    More arcade cores!

    muse continues the great work of porting arcade game cores to the MEGA65. Bombjack (1984) (installation instructions) and Bosconian (1981) (installation isntructions) are both available.

    The complete list of alternate cores for the MEGA65 so far:

    Ports and enhancements by MJoergen and sy2002:

    * Commodore 64 v5

    * ZX Spectrum v1.0

    * Game Boy v0.8

    Ports and enhancements by muse (shoestring):

    * Galaga v0.5.1

    * Bosconian v0.5.0

    * Xevious v0.5.0

    * Bombjack v0.5.0

    Along with a MEGA65 development core in slot 1 and a factory-installed stable core in slot 0, that’s more cores than there are core slots on a MEGA65! Just keep the .cor files on your SD card and flash them as needed.

    Conference talks

    MEGA65 enthusiasts have been giving talks at computer conferences this year, and several of them now have video online. Check these out!

    * Oliver Graf (lydon) at Vintage Computing Festival Berlin 2023

    * Jim Happel (jim_64) at Commodore Retro eXpo 2023

    * Dan Sanderson (dddaaannn) at Pacific Commodore Expo Northwest 2023

    If you have given a presentation on the MEGA65, even just to your local computer club, and there’s video online, please let me know so I can feature it here!

    robotfindskitten in assembly language

    Let’s take a look at how you might implement robotfindskitten in MEGA65 assembly language. This month will focus on using the KERNAL API and manipulating the display. Next month, we’ll cover the remaining topics to get a robotfindskitten program working, similar to what we did in BASIC last month.

    As before, I’ll be using the Acme assembler. Here’s a reminder of the starter code for an assembly language program that assembles to a PRG file that can be loaded and run. The !8 ... values describe a BASIC bootstrap program that invokes the first assembly language instruction.

    !cpu m65!to "rfk.prg", cbm* = $2001!8 $12,$20,$0a,$00,$fe,$02,$20,$30,$3a,$9e,$20!pet "$2014"!8 $00,$00,$00start: ; Program code will go here.

    Introducing the KERNAL

    Every Commodore computer has a built-in operating system powered by machine code etched into the computer’s Read Only Memory (ROM). You see this code running as soon as you turn on the computer: the READY prompt, the blinking cursor, and the BASIC interpreter and all of the BASIC commands are all built-in code. Included in this code is a collection of machine code routines and subsystems for accessing hardware such as the keyboard, screen, and disk drives. In computer architecture terms, these routines are known as the kernel, the centerpiece of the system used by other components. Commodore employee Robert Russell originally misspelled the word “kernel” as “KERNAL” in the documentation, and this became a nickname for the software. For the sake of tradition, I’ll continue to refer to the Commodore kernel as the KERNAL, using uppercase letters.

    A program can call KERNAL routines by way of a jump table, a list of jmp instructions built into the ROM at a fixed memory location. Each jmp instruction redirects to the actual location of the routine elsewhere in memory. The jump table exists to give programmers peace of mind that each jmp instruction will stay at a consistent address for all future revisions of the KERNAL. When changes in the KERNAL code inevitably push an internal routine to a new location, the jump table is updated accordingly, so programs that use the routine continue to function without needing an update.

    Here’s a useful example. The KERNAL maintains a system for printing PETSCII codes to the screen. As we’ve seen before, these codes manipulate a cursor that determines the location of the next printable character, and maintains other properties such as the text color and display attributes. The BASIC PRINT command uses this system to display strings of codes and characters. Machine code programs can also access this system using a routine called chrout (also called bsout in some documentation), available via the jump table entry at $FFD2.

    chrout = $ffd2 lda #147 ; clear the screen jsr chrout lda #65 ; the letter "A" jsr chrout

    The chrout routine has a pre-condition that the PETSCII code to print is in the accumulator (CPU register “A”). The effect of calling the routine is to print the PETSCII code at the current cursor position. If the code is a printable character, it plots the character, moves the cursor, and performs other effects like scrolling the display as needed. If the code is some other PETSCII code, such as code 147 to clear the screen and move the cursor to the top-left corner, that code takes effect.

    The jump table is part of the Application Programming Interface, or API, of the KERNAL. The API definition also includes the pre-conditions and post-conditions of each routine, and other important behavioral characteristics about what the routine does. All KERNAL jump table entries designed for the C64 and C128 are valid on the MEGA65—with some changes. While neither the C65 nor the MEGA65 have introduced new table entries, future versions of the MEGA65 ROM could extend the table further without changing any of the existing entries.

    It’s important to remember that the MEGA65 ROM is an active construction zone, and only some of the KERNAL APIs borrowed from previous Commodores are considered officially supported for now. Some things that C64 programmers may be used to aren’t official APIs, even if they appear to function today. When the dust has settled on the major bug fixes, the MEGA65 team will formalize more of the KERNAL API surface, adding documentation about supported features to the manuals and building automated tests to ensure that the APIs work properly. The KERNAL jump table is officially supported, as are certain specific facts about the memory layout, such as $2001 being the start address for BASIC programs.

    Once a machine code program is running, it is not obligated to use the KERNAL. In fact, many games and larger utilities jettison the KERNAL entirely, installing custom interrupt handler routines, defining a custom memory map, and manipulating the computer entirely through hardware registers. For such a program, the only API surface is the hardware itself, and there is no need to integrate with the KERNAL except to launch the program. If the program does use KERNAL routines and systems, it must honor the KERNAL’s documented pre-conditions, and stay out of its way.

    Printing a short message using the KERNAL

    The following code uses the KERNAL chrout routine to clear the screen and print a short message:

    lda #147 ; clear the screen jsr chrout ldx #0- lda message,x ; read a byte from message, offset by X beq + ; if it's a zero, we have reached the end of the message jsr chrout ; output the byte inx ; increment X bra - ; loop back+ rtsmessage:!pet 14,"robotfindskitten",0 ; Acme directive to generate PETSCII ; bytes

    This example uses the “X indexing” addressing mode to access characters in the message stored in program memory. lda message,x takes the address of the message, via the assembler symbol message, and adds the value in the X register to it. The X register is one byte, with a range of possible values of 0 to 255. This limits the length of the message to 254 PETSCII codes and one 0 byte to indicate the end of the message.

    There’s another way to print short messages, using another KERNAL routine. The primm routine at $FF7D will print a null-terminated message, with the message bytes immediately following the jsr instruction. It’s like having a PRINT command for assembly language!

    primm = $ff7d jsr primm!pet 14,"robotfindskitten",0 ; Program continues...

    It seems like a magic trick for the message bytes to be sitting in the middle of the code like this. How does the CPU know to skip over the message to the next instruction? The primm routine is quite clever. When the CPU encounters a jsr instruction, it remembers the address just after the instruction, so it can pick up where it left off when the subroutine exits with the rts instruction. The primm routine assumes that this address is the starting byte for the message and starts printing. When primm finds the 0, it updates the return address to just after the 0, then issues the rts. The CPU is blissfully unaware that primm has been messing with the return address and proceeds to execute the rest of the program. Pretty slick!

    Note that primm is also limited to messages of 254 characters. To print a longer message, we need a different strategy.

    Printing longer messages

    In the code above, message is a symbol whose value is determined by the assembler and inserted into the code where the word appears. Wouldn’t it be great if we could update the value of the message symbol as the program executes, like a variable? The value of message is written into the machine code, and this code is just bytes in memory. One option is to update the address bytes within the code by writing to the appropriate memory locations, then execute the code. This technique, known as self-modifying code, is quite common, and not that difficult with a bit of care.

    The following routine accepts the low byte and high byte of the message address in the Y and Z registers, and prints the message until it encounters a 0 byte. It relies on the knowledge that the lda $0000,x instruction assembles to three bytes: one for the instruction code, and two for the address. It uses the X register as before, but this time it tests whether X wraps around from 255 to 0, then increments the high byte of the address and continues printing. This gives us a maximum message length of 65,535 characters, which is more than enough.

    ldy #intro_message jsr print_long_message; ...print_long_message: ; Y,Z = address sty .load_selfmod+1 stz .load_selfmod+2 ldx #0.load_selfmod lda $0000,x beq .end jsr chrout inx bne .load_selfmod inc .load_selfmod+2 bra .load_selfmod.end rtsintro_message:!pet 147,14,5,27,"8" ; clear, lowercase, white, 80x25!pet "robotfindskitten in MEGA65 assembly language",13!pet "Based on the game by the illustrious Leonard Richardson (C) 1997, 2000",13!pet "Press Return to start.",0

    Changing the cursor location

    Another useful KERNAL routine for printing is the plot routine, at $FFF0. plot can do two things: it can either move the cursor to given coordinates, or it can report the coordinates of the cursor’s location. You use the carry flag to choose between the two actions. To move the cursor, clear the carry flag (clc), then set the X register to the column number and the Y register to the row number.

    plot = $fff0 clc ldx #12 ldy #1 jsr plot

    To ask plot to report the current location, set the carry flag (sec) before calling it. Instead of changing the cursor position, plot will overwrite the values in the X and Y registers with the current cursor location.

    A word of caution: When the KERNAL print system prints a character in the bottom-right corner of the screen, it assumes that more text needs to appear on the following line, and scrolls the text display to make room. When plotting characters for game graphics, this probably isn’t what you want. A simple albeit unsatisfying way to avoid this issue is to never print a character in the bottom-right corner.

    Accessing screen memory

    You could make a robotfindskitten game using just the KERNAL print system: use plot and chrout with PETSCII codes to draw items, and erase and draw the robot character as it moves across the screen. Most games don’t use the KERNAL print system to plot characters at all. Instead, they write directly to screen memory, color memory, and registers in the VIC-IV chip. This avoids issues like the KERNAL scrolling the text display, at the expense of doing other things manually, such as calculating memory locations for screen coordinates, and managing character attributes and colors.

    If your program uses the KERNAL print routines, it’s best to let the KERNAL manage screen memory as much as possible. The KERNAL uses internal variables to keep track of some screen properties, and these need to be consistent with its own understanding of the state of the video hardware. If you change the screen mode or relocate screen memory via VIC-IV registers without telling the KERNAL, actions performed by PETSCII codes, such as clearing the screen, may not function correctly.

    Handling screen memory is an essential skill for assembly language programmers. It’s also a deep topic. So let’s limit this discussion of screen memory to a few salient facts. To tell the KERNAL to set the screen mode to 80 x 25 text, print the Escape + 8 key sequence with chrout, as if you were typing it at the READY prompt:

    lda #27 ; Escape jsr chrout lda #'8' ; PETSCII "8" jsr chrout

    If you’re not using the KERNAL, you can select the screen mode with flag registers at location $D031. To get 80 x 25, clear the V400 register (bit 3) and set the H640 register (bit 7). Without the KERNAL, you will need to write your own message printing routines that write directly to screen memory; you can’t use chrout.

    The starting address of screen memory is in a VIC-IV register known as SCRNPTR, a 28-bit value stored at $D060-$D063, least significant byte first. The KERNAL will set this when you print the escape sequence for the screen mode. If you’re not using the KERNAL, you can set this to any address you like in the first 384K of memory by writing its address into the registers.

    The KERNAL’s preferred memory location for a 40 x 25 or 80 x 25 screen is address $0800. Strictly speaking, this is not a documented fact: a program that relies on the KERNAL’s setting must read it from SCRNPTR, and never assume its value. For propriety, the examples below will read the SCRNPTR value instead of assuming it, but—at least for now—I’m also relying on the fact that the address is within bank 0 (addresses $0000 to $FFFF) so we can use 16-bit addressing modes and don’t have to worry about accessing upper memory. Note that this won’t work with 80 x 50 text mode, because the KERNAL relocates screen memory to bank 1 for this mode.

    As with BASIC’s T@&() special array, screen memory contains screen codes that represent the characters in the character set. The codes are organized in columns then rows, from top-left to bottom-right: the first 80 bytes are the top row, the next 80 bytes are the next row, and so on, for 80 x 25 = 2,000 bytes.

    The following example uses the self-modifying code technique to store a value in screen memory. The sta instruction can only operate on 16-bit addresses, so it uses the lower two bytes of SCRNPTR, and assumes the upper bytes are zero (an address in bank 0).

    scrnptr = $d060 ; Use self-modification to write to the (16-bit, bank 0) ; SCRNPTR address lda scrnptr sta store_screen_selfmod+1 lda scrnptr+1 sta store_screen_selfmod+2 lda #1 ; Screen code for the letter Astore_screen_selfmod sta $0000

    Color memory

    In the regular text mode, color memory stores the foreground color and attributes for each character on the screen, organized in the same way. One way to access color memory is starting at address $D800.

    There’s one issue, though. By default, only the first 1K of color memory is visible here, from $D800 to $DBFF. That’s not enough for all 2,000 characters of a 80 x 25 display! This is solved by yet another of the MEGA65’s many modes. The CRAM2K register, bit 0 of $D030, swaps the registers from $DC00 to $DFFF with the remaining color memory. To do this, it hides other hardware registers normally at those locations, such as the CIA chip registers. The KERNAL expects to see the registers here and not color memory, so you must clear the bit before calling KERNAL routines. (The KERNAL IRQ is smart enough to stash and restore your CRAM2K setting, so you do not need to disable interrupts. That’s a topic for another time.)

    cram2k = $d030color_mem = $d800 lda #%00000001 ; Enable CRAM2K tsb cram2k lda #5 ; Paint the A green sta color_mem lda #%00000001 ; Restore registers trb cram2k

    From coordinates to screen memory addresses

    Given screen coordinates of column X and row Y, the offset into screen memory for that coordinate is Y times 80, plus X. The CPU doesn’t have an instruction that can multiple any two numbers, but it does have a quick and easy way to multiply a number by two: it can shift the bits of a number to the left, using the Arithmetic Shift Left instruction (asl). If it’s not clear that shifting the bits of a number to the left multiply it by two, write out a binary number, then write a zero at the end. For example, the binary number %0110 is 2 + 4 = 6 in decimal. Write a zero at the end, and it becomes %01100, which is 4 + 8 = 12 in decimal. Just as writing a zero at the end of a decimal (base ten) number multiplies the number by ten, writing a zero at the end of a binary (base two) number multiplies it by two.

    Using a combination of left-shift and addition operations, we can calculate the screen memory address for a given set of coordinates in three steps:

    * Calculate the row offset from the Y coordinate, stored in a memory variable (row_offset), using bit shift and addition operations to multiply Y by 80.

    * Add the base address and the row offset, stored in the address part of a sta ...,x instruction (self-modifying code).

    * Use X-indexing with the X coordinate, to determine the final address and set the screen code.

    row_offset: !byte 0,0plot_char: ; Pre-condition: ; - A is the screen code ; - X register is the X coordinate ; - Y register is the Y coordinate taz ; Stash the screen code in Z, so ; we can use A for other things lda scrnptr sta store_screen_selfmod+1 lda scrnptr+1 sta store_screen_selfmod+2do_plot: ; - Z is the value to store in memory ; Calculate Y * 80 into row_offset memory variable lda #0 sta row_offset+1 ; reset row_offset's high byte tya sta row_offset ; store the row number as row_offset's low byte asl ; x2 asl ; x4 adc row_offset ; x5 sta row_offset asw row_offset ; x10 asw row_offset ; x20 asw row_offset ; x40 asw row_offset ; x80 ; Add row_offset to store_screen_selfmod+1 lda store_screen_selfmod+1 clc adc row_offset sta store_screen_selfmod+1 lda store_screen_selfmod+2 adc row_offset+1 ; add with carry sta store_screen_selfmod+2store_screen_selfmod: stz $0000,x rts

    To update color memory, the only difference in this routine would be to use a different base address, and set CRAM2K while updating memory. I added a do_plot label above so I could share the common code between the two routines.

    color_char: ; Pre-condition: ; - A is the color ; - X register is the X coordinate ; - Y register is the Y coordinate taz ; Stash the color code in Z, so ; we can use A for other things lda #color_mem sta store_screen_selfmod+2 lda #%00000001 ; Enable CRAM2K tsb cram2k jsr do_plot lda #%00000001 ; Restore registers trb cram2k rts

    Base Page Indirect Addressing

    Each machine code instruction that accesses memory can operate in one or more addressing modes, ways for the CPU to figure out what address to use. We’ve seen three addressing modes in the examples so far:

    Immediate mode: use the value given in the instruction. This example loads the number 7 from the instruction into the accumulator:

    lda #7

    Absolute mode: use the 16-bit address given in the instruction. This example loads the value stored at address $20CF into the accumulator:

    lda $20cf

    Absolute X-indexed mode: take the given 16-bit address, then add the value from the X register to it, and use that as the address. This example sets the X register to $2F, then loads the value stored at the address calculated as $20CF plus the value in the X register ($20CF + $2F = $20FE) into the accumulator:

    ldx #$2f lda $20cf,x

    The X register can contain a value from 0 to 255, which limits the range of the X-indexed addressing mode. Earlier, I used self-modifying code to get around this problem, allowing for performing calculations on the entire address. The following example rewrites the 16-bit address portion of an instruction that’s using absolute mode addressing, then executes the modified instruction:

    lda #$cf sta .selfmod+1 lda #$20 sta .selfmod+2.selfmod: lda $0000

    Writing the address directly into an instruction like this is only really practical if only one instruction needs the address, and the modifying code knows exactly which address to modify. In many cases, it’d be better if we could store the address in one memory location like a variable, then tell the instructions where to find it.

    Base Page Indirect Addressing mode can do exactly that. This example stores a 16-bit address at memory location $10-$11, then accesses it using the Y register as an index:

    lda #$cf sta $10 lda #$20 sta $11 ldy #0 lda ($10),y

    So why didn’t I do this earlier? Well, there’s a catch: the address must be written to the base page, a region of 256 bytes that gets special treatment. Commodore 64 programmers know this as the zero page, within the addresses $0000 to $00FF. The CPU uses special forms of its instructions to access these addresses faster and with more compact code than absolute 16-bit addresses, so the base page is a great place to put variables. It’s so useful, in fact, that the KERNAL claims all of the zero page for its own use. If your program uses the KERNAL, you must protect the zero page so that it’s the way the KERNAL left it by the time you call a KERNAL routine.

    With the original 6502 CPU, the base page is always at address $0000 (hence the name “zero page”). The 65CE02 CPU (on which the MEGA65’s 45GS02 is based) adds a feature that lets you use any 256-byte page of the first 64K of memory as the base page. The B register holds the top two nibbles (two hexadecimal digits) of the address of the base page. Your program can stake out its own base page and set the B register to that location to use it. I recommend page B = $16 ($1600 to $16FF), which is reserved for use by your program.

    You must change B back to $00 before calling a KERNAL routine. The base page being set to $00 is a pre-condition of all KERNAL routines. (The B register is preserved along with other registers during interrupt handling, so you don’t have to worry about confusing the KERNAL IRQ.)

    To set the B register, put the desired value in the accumulator, then use the tab instruction (Transfer A to B). If you need to read the B register, transfer it back to the accumulator first, with tba. The requirement to go through A to set or read B sometimes requires a bit of register wrangling.

    Another register consideration to keep in mind: Base Page Indirect Addressing always uses an index register. The lda instruction supports using the Y or Z registers as indexes for this mode. If you just want to use the address directly, you must set the index register to 0.

    Here’s another version of the long message printer using Base Page Indirect addressing, preserving the zero page for the KERNAL and using page $16 for the program’s base page. Try to follow which register has which value:

    print_long_message_2: ; Y,Z = address lda #$16 ; A = $16 tab ; B = $16 sty $00 ; $1600-$1601 = the message address stz $01 ldy #0 ; Y = 0.loop lda ($00),y ; Load a character from the message address + Y beq .end ; If the value is 0, end. tax ; Stash the character in X so we can use A to set B. lda #0 ; A = 0 tab ; B = 0 txa ; A = the character jsr chrout lda #$16 ; A = 16 tab ; B = 16 iny ; Y = Y + 1 bne .loop ; If Y hasn't rolled over to 0, continue. inc $01 ; Y rolled over, so increment the high byte of ; the message address. bra .loop ; Continue..end lda #0 tab rts

    This is not necessarily better than the earlier version using self-modifying code, especially with all the register flipping required. But it illustrates the use of base page variables as address pointers.

    The 45GS02 CPU has another Base Page Indirect addressing mode, and it’s super useful: 32-bit Base Page Indirect Addressing lets you use a 32-bit address instead of a 16-bit address. With the Acme assembler in MEGA65 mode, this is indicated using square brackets instead of parentheses. Only the Z register is supported as the index in this mode.

    lda #$16 tab ; Store the address $0001.F800 at base page address $00-$03 lda #$00 sta $00 lda #$F8 sta $01 lda #$01 sta $02 lda #$00 sta $03 ; Store the value 7 at $0001.F800 lda #7 ldz #0 sta [$00],z

    Notice that other addressing modes do not support 32-bit addresses, so we can’t use the self-modifying code method to access upper memory, at least not in the same way. We can adapt the second version of the printing routine to be able to print long messages from anywhere in the MEGA65’s memory with minimal changes, but we can’t adapt the first version as easily.

    Earlier, I made a potentially unsafe assumption that the KERNAL used an address between $0000 and $FFFF for SCRNPTR in 80 x 25 mode, and I just ignored the upper bytes of the SCRNPTR address. With 32-bit base page indirect addressing, I don’t have to do that: I can just copy the entire address from SCRNPTR to a four-byte base page variable, then use 32-bit indirect addressing to access screen memory.

    Incidentally, upper memory addresses $1.F800 through $1.FFFF are another way to access the first 2K of color memory, with no need to set the CRAM2K flag. In my implementation of robotfindskitten, I use base page $16 for variable storage, and base page indirect addressing for plotting characters with the full four-byte SCRNPTR address and for plotting colors to 1.F800. I set the B register to $16 at the beginning of the program, and wrap my KERNAL calls to set B to $00 before the call and set it back to $16 afterward.

    As you can see, there are multiple ways to accomplish certain tasks. For high speed applications, you may need to make your choices based on the amount of CPU time each operation takes, measured in CPU cycles. Instruction cycle counts are listed in the manual. robotfindskitten is not speed critical, so I just went with what made my code easiest for me to understand.

    That’s a good start. With the KERNAL output routines and screen memory access, we have the tools to replicate BASIC’s PRINT, T@&(), and C@&() facilities in assembly language. Next month, we’ll look at another important KERNAL facility for accepting keyboard input, and some snazzy MEGA65 hardware features for generating random numbers and measuring time. We’ll close by designing data structures to access all of the item descriptions, and prevent two items from landing on the same place on the screen.

    For comparison and enjoyment, here’s my BASIC version of robotfindskitten. It’s faithful to Leonard Richardson’s version, which is not particularly creative of me, but hopefully it serves as a useful reference implementation.

    * rfk-bas.prg : robotfindskitten in BASIC 65; BASIC source code in petcat format

    Happy coding! See you next month.

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • A new month, a new feature, a new game, a new demo, and a coding exercise that really brings the room together. Let’s dig in!

    Available to test: New keyboard scanner

    We’re getting closer to having a complete release candidate, with features being finalized and bug fixes piling in. There’s one new feature that’s near and dear to my heart, and I’m thrilled to be able to share it with anyone up for early beta testing.

    The very first thing I noticed when I got my MEGA65 is how the typing experience felt nostalgic. Even with the new mechanical key switches and the 40 MHz CPU, the ability for the computer to recognize key presses felt exactly like a Commodore 64 did back in the day: sluggish and imprecise. I like nostalgia as much as anybody, but I type much faster today than I did when I was nine years old. I wished my MEGA65 could handle fast typing more like a modern computer, so I could enjoy on-device composition without slowing myself down. It was one of the first feature requests that I filed with the MEGA65 team.

    Paul and company started working on an idea for fast typing, and an early version of the chipset support required made it into the core last year. The feature wasn’t wired up to the KERNAL ROM, and only a few built-in applications used it. I brought it up again with the team this summer, and we had many design discussions and tried several ideas. I learned a bit of FPGA coding, and even built a high-speed Linux PC just to build and test new cores and ROMs.

    I’m proud to present the all-new MEGA65 hardware-accelerated keyboard scanner. Using the latest development core and ROM beta release, you can now enjoy a typing experience that is more accurate and more reliable for fast typists throughout the BASIC screen editor and many applications. These changes will be in the v0.96 release, and you can test it today and file any bugs you find. I also wrote a test plan and detailed description of how it works.

    I plastered this all over the instructions, but I'll repeat it here: the latest ROM beta versions (920387 or later) require the latest development core. If you use the newer ROM with an older core, typing won't work. You *can* safely use older ROMs with the newer core, so you can revert to the legacy keyboard scanner at any time if you encounter any issues just by going back to an older ROM (920386 or earlier). Also, the latest ROM betas will not work with the Xemu emulator until emulation for the new core feature has been added (hopefully soon), so stick with 920386 or earlier in Xemu for now.

    For me, the difference with the enhanced typing quality is like night and day. On-device programming and other typing applications are much more usable, and I just enjoy using the computer much more, confident that I won’t have to struggle with missed keystrokes. Try it out, and let me know what you think!

    Classy, by deathy

    Classy, by deathy, is a new match-3 game for the MEGA65. Careful with this one: it’s addictive! A joystick in either port or the keyboard sets you on your tile swapping journey. If the game is still running, it means you still have moves remaining. Keep looking!

    MEGApple, by MirageBD

    The MEGA65 gets its Bad Apple!!

    MEGApple is MirageBD’s MEGA65 version of the popular demo challenge: recreate the shadow-art music video of the Japanese pop song, “Bad Apple!!” The original video was a collaboration of animators on the Japanese website Nico Nico Douga, based on the pop remix by nomico of a track from the video game Touhou Fantasy Land: Lotus Land Story. Over a decade later, it persists as a popular meme to recreate the music video in unusual media, including (but not limited to) retro computers.

    To run MEGApple, download and expand the archive, then copy the files to the root of your SD card. Start your MEGA65, then type: MOUNT "MEGAPPLE.D81":RUN "*" The program on the D81 disk image loads the data from the other larger files.

    Xevious, new arcade core by muse

    muse has a new arcade cabinet core for us! Xevious (1982) and Super Xevious (1984) are early vertical scrolling shooter games by Namco. Fly your Solvalou starship over the planet’s surface to stop the Xevious forces by both land and sky. muse’s version supports a one-button joystick with a clever adaptation: press the button quickly to shoot at airborne enemies, and hold the button to drop bombs on turrets.

    As with the Galaga core, the installation instructions include searching for and downloading the original Xevious ROM files, running a Python script to validate the files and prepare a folder that you copy to your MEGA65’s SD card with the path /arcade/xevious, then installing the core in an available core slot. See the Discord announcement for additional notes.

    robotfindskitten

    “Yet another zen simulation.” — robotfindskitten.org

    In robotfindskitten, you are a robot, who finds a kitten.

    robotfindskitten was originally written by Leonard Richardson in 1997 for DOS, as his submission to the robotfindskitten contest put on by the webzine “Nerth Pork.” It took first prize. There were no other entries, but there didn’t need to be. The theme had found its perfect expression on the first try.

    In the decades that followed, many have made their own versions of the simulation, on many interactive platforms. And now, it is your turn.

    Richardson’s version depicts the robot with a single colored ASCII character on a monospaced field that spans the screen. The field is populated sparsely with other colored ASCII characters that represent many Non-Kitten Items (NKIs), and one kitten. To the robot, all items, including the kitten, appear as random colored characters. The operator uses cursor keys to move the robot around the field. When the robot comes into contact with an item, a message is printed describing the item. If the item is the kitten, the experience ends in joyful celebration.

    You can play robotfindskitten in your browser. Or, you can install a version for a modern terminal for Linux (sudo apt install robotfindskitten) or macOS (brew install robotfindskitten) or many other platforms. (Some versions are survived only by their archived screenshots.) Or you can build the Linux version from source. Or you can check out the Ultimate robotfindskitten Fan Site, by Leonard himself.

    Or you can make your own. Here are some techniques that you might use to rise to this challenge in BASIC 65. Next month, we’ll look at how to do similar things in assembly language.

    Display

    You will need to control what is displayed on the screen, so the operator can see the robot and the items.

    To clear the screen of all text, you can use the SCNCLR command. To set the color of text to be printed (from 0 to 31): COLOR number. Similarly, to change the color of the border or background: BORDER number or BACKGROUND number. To set the position of where the next text will be printed: CURSOR column, row. To print a string of text at the current cursor position: PRINT string.

    One word of caution with PRINT: if the string you are printing extends beyond the right edge of the screen, the screen below that point will scroll down by one line. This probably isn’t what you want in this exercise, so take care with the length and position of your strings.

    To plot a single character at a set of coordinates, you can assign the screen code of the character to the T@& array, and its color to the C@& array. These are two dimensional arrays, with the first index referring to the column and the second index referring to the row. T@&(0,0)=1 plots the letter A to the leftmost topmost position. (1 is the screen code for the A character. Notice that screen codes are not PETSCII codes.) C@&(0,0)=5 paints it green. You can read screen codes and colors from these arrays as well: IF T@&(0,0)=1 THEN ... and so forth.

    Recall that PETSCII codes in strings give you further control of the display via the PRINT command. PRINT CHR$(14) switches the display to the lowercase character set. Be aware that not all PETSCII graphics characters are available in the lowercase set.

    Here is a short program that clears the screen, switches to lowercase, and plots all of the available screen codes:

    100 COLOR 1110 SCNCLR120 PRINT CHR$(14)130 FOR R=0 TO 3140 FOR C=0 TO 63150 T@&(C,R)=R*64+C160 NEXT C170 NEXT R180 CURSOR 0,5

    Input

    To accept keyboard input, use either GET variable or GETKEY variable. These both take a variable name as their parameter. Given a string variable (such as A$), the key being pressed is loaded into the variable as a single-character string. Given a number variable (such as A), it is loaded as a PETSCII code. GETKEY pauses until a key is pressed. GET will not wait: if no key is pressed, it assigns an empty string or a zero, and moves on. If you want GET or GETKEY to provide the PETSCII code as a number, be sure to use a byte type variable, so that the number is in the range 0 to 255: GET K&.

    10 GETKEY K&20 PRINT K&30 GOTO 10

    Alternatively, you can accept joystick input using the JOY() function. The function takes the port number as an argument (1 or 2), and returns a number 0 through 8 indicating the state of the joystick. 0 says the joystick is centered. All other numbers indicate a direction, starting with 1 for “up” and going clockwise: 2 for “up-right,” 3 for “right,” and so forth.

    Chaos

    The items are assigned random characters, colors, and positions, so you’ll need a way to generate randomness. The RND() function generates numbers using a pseudo-random number generation algorithm. The function takes an argument that determines the “seed” for the algorithm. For most purposes, an argument of 1 suffices: RND(1). The function evaluates to a random fractional number between 0 and 1. To generate numbers within a range of integers, multiply the result by the size of the range, then take the INT() of the result to lop off the fractional part. INT(RND(1)*80) generates a random integer between 0 and 79.

    If you want the range of possible values to start at a value other than zero, do the inner multiplication by the size of the range, then add the starting value. INT(RND(1)*77)+1 generates a random integer between 1 and 77.

    The following program plots randomly colored random characters when one of the cursor keys is pressed. See if you can figure out what the variables CL, CH, RL, and RH do.

    100 SCNCLR110 CL=0:CH=79:RL=0:RH=24120 GET K&130 IF K&17 AND K&29 AND K&145 AND K&157 THEN 120140 IF K&=17 THEN RL=12 : REM CURSOR DOWN150 IF K&=29 THEN CL=40 : REM CURSOR RIGHT160 IF K&=145 THEN RH=12 : REM CURSOR UP170 IF K&=157 THEN CH=40 : REM CURSOR LEFT180 C=CL+INT(RND(1)*(CH-CL))190 R=RL+INT(RND(1)*(RH-RL))200 T@&(C,R)=INT(RND(1)*256)210 C@&(C,R)=INT(RND(1)*16)220 GOTO 110

    Like the Commodore 64, a positive argument generates a new number based on the previously generated number. Unlike the Commodore 64, the algorithm is initially seeded from the MEGA65’s Real-Time Clock during boot, so you are unlikely to see the same sequence twice with RND(1).

    Tip: For RFK, you probably want to prevent randomly selected values from repeating. A simple way to avoid this is to keep track of previously selected values, such as in an array, and scan the array each time a new value is chosen. If it’s in the array, restart the process to pick another value. Once a unique value is found, add it to the end of the array. In my version, I used this technique to avoid two items from appearing at the same location, and to ensure that each item uses a unique PETSCII character and a unique description.

    Calm

    To animate the joyful celebration at the end, you’ll need a way to pause between frames of an animation. The SLEEP seconds command pauses the program for the given number of seconds. The number can be fractional.

    10 FOR X=1 TO 520 PRINT CHR$(211);30 SLEEP 0.640 NEXT X50 PRINT

    Data

    Each Non-Kitten Item in robotfindskitten gets assigned a description at random when the item is created. One way to put a large list of descriptions in a BASIC program is with DATA statements. These statements don’t do anything when encountered by control flow. Instead, they make values available to the READ statement, which finds the next unread value and puts it in a variable.

    A traditional BASIC technique is to read the number of elements from the first DATA statement, DIMension an array of that size, then READ that many elements into the array. The program can then access any string from the array by its number index. This is a bit wasteful. It keeps two copies of the list in memory: one in the BASIC program listing, and another in variable memory. It also introduces a delay at the beginning of the program to load all of the elements into the array. The primary advantage is that each element can be accessed instantly by index.

    In BASIC 65 (and BASIC 7 for the Commodore 128), there’s a better way: use sequential line numbers for the DATA statements, then use the RESTORE command to set the READ pointer to a given line number. RESTORE accepts a number expression for the line number, so you can select a string programmatically by number.

    10 READ N20 K=INT(RND(1)*N)+130 RESTORE 1000+K40 READ NK$50 PRINT NK$60 GETKEY A$70 GOTO 201000 DATA 51001 DATA "THAT'S JUST AN OLD TIN CAN."1002 DATA "IT'S AN ALTAR TO THE HORSE GOD."1003 DATA "A BOX OF DANCING MECHANICAL PENCILS. THEY DANCE! THEY SING!"1004 DATA "IT'S AN OLD DUKE ELLIGTON RECORD."1005 DATA "A BOX OF FUMIGATION PELLETS."

    A DATA statement has a special syntax to allow for string values that contain almost any character: values are separated with commas, and a value that starts with a double-quote contains every character (including commas) up to the next double-quote. This requires special handling if you want a string value to contain a double-quote character. Because NKI descriptions only use letters, numbers, and punctuation, one solution is to use a special character as a substitute for double-quotes, then replace it in code:

    41 FOR I=1 TO LEN(NK$)42 IF MID$(NK$,I,1)="ÂŁ" THEN MID$(NK$,I,1)=CHR$(34)43 NEXT I1000 DATA 61006 DATA "IT'S A DVD OF ÂŁCROUCHING MONKEY, HIDDEN KITTENÂŁ, REGION ENCODED FOR THE MOON."

    You can use the original list of 406 NKI descriptions, or write your own. The truly patient can type all of these into DATA statements by hand, a zen experience of its own. Or you can use one of these that I made for you:

    * nkis_upper.bas / nkis_upper.prg : uppercase character set

    * nkis_lower.bas / nkis_lower.prg : lowercase character set

    Structure

    Your program will have at least a few phases of operation, such as one to decide on the locations and appearances of the items, and another where the player is moving the robot. Each phase will be a section of lines in your program. BASIC executes lines in a given section to produce the experience of that phase. To transition from one phase to another, the program directs BASIC to GOTO a line in the appropriate section.

    I based my RFK experience on Richardson’s version, which can be described as four phases:

    * Introduction. Display an intro message, then wait for a keypress. When a key is pressed, proceed to phase 2.

    * Initialization. Set up and draw the items on the screen, set the initial robot position. When complete, proceed to phase 3.

    * Game loop. Listen for player input, move the robot, display NKI descriptions. When the robot finds the kitten, proceed to phase 4.

    * Ending. Animate the joyful experience, then wait for a keypress. When a key is pressed, return to phase 1.

    My program code also ends with the NKI descriptions as a fifth section of data statements. Control never reaches this section, because DATA statements do not need to be performed like other commands. (The READ statement in an earlier section accesses this data.)

    One of the best things about BASIC is how it makes it easy to write and test each section separately. To start a section from the READY. prompt, provide the first line number to the RUN command:

    RUN 300

    You can temporarily add a STOP statement in the program to cause execution to return to the READY. prompt at that point. You can use commands to inspect the state of program variables, such as: ?NK$ When you are ready to resume execution of the program, type the CONT command. You can even assign new values to variables while paused, and it’ll use the new values when you continue the program. Don’t forget to remove the STOP statements when you no longer need them.

    When you’re finished

    As amusing as it would be for everyone to upload their RFK experiences to Filehost, that might not be the most polite use of the site. Let’s do this instead: send me a photo or screenshot of your robotfindskitten experience. I will try to feature a selection of submitted photos in an upcoming issue of the Digest.

    If you have any questions about BASIC programming or would like to discuss the exercise, let’s meet up in the #basic channel of the Discord chat. I’m usually there.

    Next month, I’ll share my BASIC RFK implementation, and we’ll look at similar tools for making an RFK game in assembly language. See you then!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • The MEGA65 Community Survey 2023 is now complete! It opened on August 14, ran for three weeks, and received 509 submissions. A HUGE thank you to everyone who submitted!

    Let’s do a quick update, then onto the results!

    Release testing update

    We do not yet have a formal release candidate for the upcoming v0.96 release, which is intended to be the factory installed release for the next delivery batch. We are still waiting on test hardware for the revision 5 main board to arrive. Once it does, we will clean up the changes and document a formal test process that you can try on your own computer.

    In the meantime, we’re sharing out early test plans for some major features. Before I get you all excited about early availability, please know that what’s currently available is not the release candidate. By definition, development versions are riskier than release candidates, and do not necessarily represent what will be in the release candidate.

    In particular, do not attempt to flash a development core to slot 0 unless you own a JTAG adapter and know how to use it to recover from a broken state. Keep a stable core in slot 0, and use any other slot for the development core. We’re working on making it safer to upgrade slot 0 without a JTAG adapter, but this is not yet ready for testing by people that don’t actually have one.

    While it is possible to have multiple MEGA65 cores installed and switch between them, this is not the case for system software files (.M65 files) on the SD card. We haven’t noticed any issues using newer system software with the earlier stable core, but keep this in mind while troubleshooting issues.

    Here are the development builds of the platform components:

    * mega65-core development builds; the mega65r3 build is for production units and DevKits

    * mega65-tools development builds; macOS versions can be built from the development branch of the repo

    * Latest ROM beta release (owner registration required); patch files (free access, patching instructions)

    Available to test: Ethernet file transfer

    You are invited to help test Ethernet file transfer, a feature in the development version of the core and tools. See these instructions for testing Ethernet-based file transfer. You’ll want to be familiar with your PC’s command line interface, as the file transfer tools are currently only available in command line form.

    A few things to notice:

    The core download includes a new system software file, ETHLOAD.M65, so be sure to copy that file to the SD card.

    This feature exposes the MEGA65 to be controlled remotely by another computer over a network. As a safety measure, the feature is locked by a DIP switch on the main board. You will need to open the case to set DIP switch #2 to the “on” position.

    You can connect your MEGA65 to your local network router, or directly to a PC using an Ethernet cable. You provide the file transfer tool with an available IP address on your local network, so you will need to know how your local network or PC networking settings are configured. Typically, the IP address of your computer’s network interface and the subnet mask together indicate the IP address range for the local network. When using a router, you will need to configure your router to reserve an IP address for the MEGA65, so that it doesn’t assign it to another device. (The MEGA65 doesn’t support DHCP directly.)

    You enable a remote control session on the MEGA65 by pressing the Shift + Pound key combination. The power light will blink to indicate that it is listening to the network. You can then run the mega65_ftp command-line tool to transfer files.

    Give it a go, and ask questions in the Ethernet Tools Testing thread on Discord.

    Available for review: User’s Guide, 2nd edition

    The next delivery batch will include a fresh printing of the User’s Guide. We’ve taken this opportunity to overhaul the Guide, update it with new information for the v0.96 release and R5 main board, and do a cover-to-cover editing pass over the whole thing including the BASIC reference. The BASIC quick reference card has also been updated, and there’s a snazzy new cover image. There are a few remaining to-do items related to features that are still in progress.

    Download the latest User’s Guide PDF, file documentation issues on Github, and discuss in the #manual channel on the Discord.

    MEGA65 Community Survey 2023 Results

    The following report attempts to summarize results while preserving the anonymity of respondents. Free text responses will be kept private and will not be quoted verbatim in this report. I will be summarizing based on my own judgement, and I will withhold outliers to preserve privacy. Please know that even if your opinion doesn’t seem represented in the report, your free text responses will still be read by the MEGA65 team.

    I will attempt to base conclusions on numerical data where possible. Interpretation of free text responses will inevitably be biased. This bias reflects on me and not the opinions of the MEGA65 team. Similarly, I designed the survey and am solely responsible for flaws and biases in the way questions were structured and worded. This will be pretty casual.

    Owners and non-owners

    The survey asked respondents whether they currently own a MEGA65, have one on preorder, are still considering placing an order, are not considering an order, or may have previously owned a MEGA65 and no longer do. Owners were shown additional questions about the configuration of their machine. Non-owners were given additional opportunities to explain their interests and concerns.

    This is a control question for interpreting other responses, and is not a useful indicator of a single population on its own. The relative sizes of the categories only describe the response pool, not the MEGA65 community at large. The survey was promoted in various channels that tend to skew variously towards owners (such as the Digest, Discord) or non-owners (such as Commodore user groups), and non-owners were encouraged to reply, with the rough guidance that anyone who has heard about the MEGA65 is invited.

    When the survey was sent, approximately 900 MEGA65s had been delivered. This helps extrapolate potential population counts from a sample of the owner category. 218 respondents said they own a MEGA65, which is 24% of all owners. In contrast, there is no good way to extrapolate answers from a sample of non-owners to a larger population.

    For some questions asked of all respondents, ownership status has a natural influence on responses. Someone is more likely to engage with community resources after they have received their computer. For example, 86% of current owners said they are aware of the Xemu emulator, compared to 58% of respondents who have not yet placed an order.

    I will try to separate results by ownership status where there appears to be significant difference. This does not intend to imply that responses from any particular group are more or less important. There are many non-owners that make major contributions to the community, as well as owners that have not yet engaged with the project. Grouping is merely a crude way to control for differences in sampling.

    What’s interesting about the MEGA65

    The survey offered a list of possible reasons why someone might be interested in the MEGA65 project, and asked for zero or more selections. Raw data from multi-select questions can be difficult to interpret, especially when the question is phrased like a buffet of ideas or desires. The survey could have asked respondents to rank these, or pick a primary reason, but that felt too limiting.

    Many respondents are interested in collecting vintage computers, reproducing the experience of the Commodore 65 prototype, and leveraging the MEGA65’s FPGA to reproduce the experiences of other Commodore 8-bit computers. The MEGA65 project’s goal of staying connected to history has always been a balancing act between recreating an incomplete, unreleased, and ultimately canceled design, and completing and extending that design to be practical and fun to use in the 21st century. As invigorating as it is to see the MEGA65 as an opportunity to design a new 8-bit computer, it is important to the community that the MEGA65 project values historical preservation.

    Several of the options discuss programming, which is also repeated later in the survey. Many respondents want to run MEGA65 software written by others, write programs for their own enjoyment, and/or write programs for others to use. I’m personally gratified to see 19% said they want to use the MEGA65 as a platform for learning how to program computers in general. I’m also excited to see 19% said they want to learn FPGA programming. There’s a lot of potential for the MEGA65 to be an all-in-one FPGA learning platform, especially with the MiSTer2MEGA65 template as a starting point.

    We can try to relate interest in recreating Commodore computers and interest in programming. 68% selected at least one of the Commodore recreation options. 72% selected at least one programming-related option. 50% of all respondents selected at least one option in both of the re-creation and programming categories.

    This section included a free-text prompt for mentioning other interests and motivations. Many took this opportunity to elaborate on their interest in using the MEGA65 as a Commodore 64, and potentially other Commodore computers, with several people appreciating that new hardware is more available and less likely to fail than vintage hardware. Others gave details about their interests in programming, with some specifically interested in FPGA development. Quite a few people praised the project for its nostalgic feel, and called out wanting to participate in the MEGA65 community.

    The survey asked follow-up questions to people who said they don’t use their MEGA65 or are not interested in ordering. The most common concerns are the price being too high and software being too scarce. (The survey phrased this as “Not enough software,” which was intended as “Not enough new third-party MEGA65-platform software.”) I won’t share specifics on these questions publicly due to low response rates in these categories, but all individual concerns will be seen by the team.

    Platform versions

    The survey asked owners to identify when they received their computers, to determine which delivery batch they received. We know that batch 1 (from mid-2022) and batch 2 (from early 2023) each delivered 400 units. Of these, 35% of batch 1 owners and 16% of batch 2 owners responded to the survey. This might indicate that batch 2 recipients are less engaged with our communication channels than batch 1 recipients.

    (This is not to be confused with the proportions within the responses. Among respondents who said they owned a MEGA65, 64% said batch 1, and 29% said batch 2.)

    I asked owners how often they use their MEGA65s. Batch 2 owners are slightly more likely to be using their computers more frequently than batch 1 owners, which would make sense if batch 1 owners have had more time to move on to other projects.

    * “More than once per week:” 19% of batch 1, 23% of batch 2

    * “A few times per month:” 37% of batch 1, 32% of batch 2

    * “Less often than once per month, but occasionally:” 29% of batch 1, 37% of batch 2

    * “I used it some when I first got it, but I don’t use it any more:” 13% of batch 1, 6% of batch 2

    The MEGA65 platform (core, ROM, and system software) is upgradable, and the MEGA65 team continues to improve the platform and issue new releases to be installed at the factory for each delivery batch, and made available to everyone as upgrades. Batch 1 owners started out with Release v0.9 and were invited to upgrade to Release v0.95, which was the default for batch 2. We’ve tried to make upgrading as easy a process as possible, but it’s not clear how easy it is to learn that new versions are available, or learn how to upgrade.

    I’m pleased to see that 72% of owners have upgraded their MEGA65 at least once. Naturally, more batch 1 owners upgraded than batch 2 owners, because batch 2 owners started with the current stable release. Quite a few batch 2 owners reported having upgraded, likely to help beta test new features. Excellent!

    17% of batch 1 owners report having not upgraded. The survey didn’t ask why they did not upgrade, but given the benefits of upgrading, it’s worth taking this as an indication that these owners may not know about the newer releases, or may not know how to upgrade.

    Everyone who said they have upgraded was asked what they have for their default core and MEGA65 ROM. Options included the MEGA65 stable release cores and ROMs, newer test versions of each, non-MEGA65 cores, and MEGA65-compatible ROMs such as the C65 prototype ROMs or the MEGA65 Open ROM project. In the following charts, I have included people who said they did not upgrade (and so were not asked which core or ROM they are running) in the results for the stable releases based on their reported delivery batch.

    21% of owners admitted that they do not know which core or ROM (or both) that they have installed. I would guess many of these might be people who were not in a position to check their version numbers when they took the survey. This could also suggest that we can do a better job making this information easier to find. While it’s an authentic retro experience to not know or care about the chipset and ROM version of a vintage Commodore, it’s important that we help everyone keep up with updates so that they get the most out of their machines.

    The survey also asked which cores everyone has installed, regardless of slot. 54% of owners have the C64 for MEGA65 core installed. Once again aggregating responses from people who said they have never upgraded:

    Video and audio configuration

    Owners were asked several questions about their video and audio configuration, and peripherals they are using.

    81% reported using the PAL video mode as their primary mode. Of these, 17% reported that their display only supports PAL.

    Similarly, 18% reported using the NTSC video mode as their primary mode. Of these, 24% reported that their display only supports NTSC.

    56% of owners reported that their display supports both PAL and NTSC display modes, so they can run software that switches to either mode. 24% reported that they do not know whether their display supports both modes.

    The survey asked which video and audio outputs you used primarily. Some displays support more than one input. (I actually keep both DVI and VGA connected so I can switch between them as needed.)

    I asked everyone to name the make and model of their display, as free-text. Not everyone knew their make or model, but many attempted to answer. I was hoping to compile a list of recommendations of displays that support both PAL and NTSC. Not surprisingly, almost everyone was using a different model of display.

    The most reported single model was the Dell P1917S, a 19" 5:4 flat panel LCD display that has both DVI and VGA inputs and supports both PAL and NTSC, and you can still buy it new. It doesn’t have built-in sound, so get a pair of powered computer speakers with a 3.5 mm audio input. Note that the Dell soundbar for this model is USB audio only and won’t work with the MEGA65. I have used this model, as well as a vintage Dell 2001FP with an older soundbar with a 3.5 mm audio jack. I can report that the P1917S handles the VGA signal much better than the 2001FP, and the P1917S doesn’t freak out about sound over HDMI either the way the 2001FP does for DVI video.

    I also asked about video capture equipment. Only a few people said they use it, primarily for making or streaming video of their MEGA65. Generic HDMI-to-USB capture devices seem to work just fine. I use an Elgato Cam Link for this purpose, and I got a ClonerAlliance Box Pro based on a recommendation from retroCombs which I also like a lot.

    Peripherals and supplies

    I asked everybody (not just owners) about what’s in their closet, in an attempt to survey what people can be expected to own that would extend their MEGA65 experience.

    In general, lots of respondents have joysticks, and quite a few have mice and paddles. 11% reported not having any of these.

    Of the paddle owners, 57% have Commodore paddles, and 41% have Atari paddles. Great job knowing what paddles you have! It was only last year that I learned there was a difference. As a kid I used Atari paddles with my Commodore and didn’t understand why my paddles had about half a turn of dead space.

    Many respondents, 68%, own a vintage 5-1/4" Commodore disk drive. I included a free-text field for other IEC devices, and plenty of people reminded me that SD2IEC devices are popular. Zero respondents reported owning a vintage dual drive unit, such as the Commodore 4040.

    I asked how many floppy disks you own, of any type and for any purpose. 62% said they have more than 20. 14% have none. I intended this as a rough measure of how many people might use the built-in floppy drive. Of course, the drive could still be used with a future purchase of MEGA65 software distributed on 3-1/2" floppy.

    Connectivity and development hardware

    88% of overall respondents said they could connect a MEGA65 to their local network via Ethernet from where they use a MEGA65, or from where would use one if they had one. Those new networking features of the MEGA65 will be a game changer for transferring files without extracting the SD card, and for doing cross-development. Anyone without convenient access to an Ethernet connection might be able to use a Wifi-ethernet bridge.

    29% of owners have a JTAG adapter for their MEGA65. 11% of owners have a UART serial adapter. JTAG and UART serial are powerful tools for programmers doing cross development and contributing to the MEGA65 platform, and some have used them just to transfer files back and forth between their PC and their MEGA65. The new Ethernet-based tools can move files and programs at much faster speeds, and are likely to eliminate the need to buy extra hardware for most people. JTAG is still needed for testing bitstreams, and JTAG/UART are still useful for remote debugging tasks, at least until someone makes a similar feature that works over Ethernet.

    Small but non-zero percentages of respondents own a MEGA65 DevKit, and/or a Nexys or Wukong FPGA development board, all of which are alternative ways of running the MEGA65 platform.

    Software

    The survey asked how many MEGA65 software titles have you downloaded off of the Internet. It asked this of all respondents, not just MEGA65 owners, because some people use the Xemu MEGA65 emulator as a temporary or permanent substitute for MEGA65 hardware.

    12% of owners say they have never downloaded MEGA65 software. 71% of non-owners have never downloaded software, which makes sense. The non-owner sub-categories break down as you would expect, with greater degrees of interest in the project correlating with more software downloaded.

    Retro software publisher poly.play currently prints two commercial titles for the MEGA65: Hibernated 1 by Stefan Vogt, and Showdown by Badger Punch Games. 14% of respondents have purchased at least one of these. 6% of respondents have purchased both titles. 40% knew about them but did not purchase either, and 45% did not know about one or both.

    Xemu

    The Xemu MEGA65 emulator by GĂĄbor LĂ©nĂĄrt (LGB) is the definitive PC emulator for the MEGA65 platform. 74% of respondents knew there was an emulator before taking the survey. Of the people who said they knew about Xemu, 48% said they use it.

    There are several reasons people use Xemu, so the survey asked about them.

    Selecting just for people who already own a MEGA65, the proportions of uses don’t actually change much except, of course, for respondents stating they use Xemu because they don’t own hardware.

    The survey gave everyone an opportunity to provide feedback on Xemu. We collected dozens of excellent suggestions and feedback in a wide variety of categories. Xemu is a well-loved tool and a cornerstone of the MEGA65 project, and we’re all grateful to LGB for working on it!

    Documentation

    Every MEGA65 ships with a first edition printed User’s Guide. 28% of owners use it regularly, 44% refer to it occasionally, and 26% rarely or never use it.

    The User’s Guide is just one of a set of books in progress that form the complete documentation for the project. The latest versions are available as PDF files, free for anyone to download. The survey asked all respondents how often they use the PDFs.

    When I first got my MEGA65 in May of 2022, I wrote Dan’s MEGA65 Welcome Guide as a supplement to the official documentation, intending to patch over the gaps between the intended experience and the first delivery batch that I knew would be fixed in later versions. It ended up being a generally useful resource for many. 62% of respondents were aware of the Welcome Guide.

    The survey asked about what medium you prefer your documentation. My personal preference would be professionally printed manuals, and the MEGA65 documentation was set up to maybe someday become a multi-volume printed set, similar to the printed User’s Guide. I wanted to gauge interest in crowdfunding a professional print run. Crowdfunding can be tricky with a small population, especially one that’s difficult to reach. Print-on-demand services are easy to use with no up-front or on-going monetary investment, and they have significant advantages for global fulfillment, but they’re lower quality than what I have in mind. My favored option for printing would require a minimum print run.

    In the survey, I proposed a hypothetical version of this project where an “entire set” (with the actual content to be determined) might cost $150 USD, and individual volumes might cost $35 USD. I asked everyone their preference: the entire set, a couple of volumes, print-on-demand, or digital only.

    If the responses are representative of the preferences of everyone who will own a MEGA65 by the end of 2023 and enough of them could be reached to announce a crowdfunding campaign and at least half of them backed the project, we could make fancy books a reality. It’d be a limited print run, followed up by a secondary print-on-demand version available in perpetuity. I like these odds well enough. Even if the crowdfunding campaign never happens, investing in content will improve the digital versions and we can easily do an official print-on-demand offering when we feel they’re in a state worth printing.

    I’m also going to try to get a web version of the documentation working. No promises—it’ll be a chunk of work to clear up the LaTeX for web export—but it’s a worthy goal.

    Dan’s MEGA65 Digest

    If you’re reading this, you’re probably aware of my monthly email newsletter, Dan’s MEGA65 Digest. I initially announced the survey in the Digest, so it’s not surprising that 60% of respondents were aware of the Digest before the survey. I’m delighted to see that 39% of respondents were unaware, because that means two things: 1) there are more people out there who might be interested, and 2) our efforts to promote the survey reached beyond people already aware of the Digest.

    Of the people aware of the Digest, 67% read the text version by email. 15% go to my website directly, and a few use RSS or the Substack website. It’s good to see that I could migrate the Digest to another newsletter provider if needed and probably nobody would miss it.

    Did you know that there’s an audio podcast version of the Digest? 42% of people familiar with the Digest did not know. 18% listen to at least some issues by audio. 51% of listeners use the Substack service to do so (because clicking on the email takes you there), and 37% of listeners use a podcast app. I enjoy making the audio version and I’m grateful that some find it entertaining.

    Thank you all for the generous comments in the free-text field! Some people asked for more advanced technical topics, and others asked for less advanced technical topics. 😊 Several people mentioned interest in a print anthology, or just a printed zine. I’m not sure I could fill a print zine each month—at least not without collaborators.

    Community resources

    62% of all respondents are aware of the MEGA65 Filehost, an essential community resource. 91% of owners who responded to the survey know about it.

    Of those who are aware, almost everyone has used the Files section to browse and download files. 47% of respondents who own a MEGA65 have redeemed their owner code, which is surprisingly low! You need to redeem your owner code to access release packages containing the closed ROM (though there are other ways to get the closed ROM). The survey asks about other features of Filehost, and it generally looks like people use them proportional to the amount of material posted in those categories. No surprises here.

    83% of all respondents are aware of the MEGA65 Discord, and 54% have an account. Of those that have an account, 29% visit it daily.

    76% of all respondents are aware of the MEGA65 section of Forum64.de, and 33% have an account. Of those that have an account, 18% visit it daily.

    25% of all respondents have both a Discord account and a Forum64 account. 75% of them visit the Discord at least once a month. 28% of them (7% of all respondents) visit the Discord daily.

    Programming

    The majority of respondents have more than 10 years of experience writing computer programs. The survey purposefully did not make a distinction between professional vs. hobbyist programming: the survey used phrases like “writing computer programs” to be inclusive of both.

    79% of all respondents said they are interested in writing their own programs for the MEGA65. Those that expressed interest were presented additional questions about programming tools.

    Of those that want to program, 75% are interested in assembly language, and 75% are interested in BASIC 65.

    The survey offered a free-text box to express interest in other programming languages. Python was mentioned multiple times. In my experiences with Python and with retro computing, I’ve seen many people wonder aloud if MicroPython could be ported to a vintage computer. In those discussions, the quality of C compilers that target retro platforms has been mentioned as an issue, so I wonder if it’s a topic worth revisiting in the context of llvm-mos. Pascal also got multiple mentions, which is more likely to be built from scratch for the MEGA65 by an enterprising hobbyist.

    The survey listed a bunch of popular cross-development tools and let everyone pick their favorites. Visual Studio Code, CBM prg Studio, Kick Assembler, and cc65 were top of mind for most people. Several people mentioned C64 Studio in the free-text responses.

    I know people that love cross development, writing programs for the MEGA65 using a modern computer. I also know people that love on-device development, preferring to shut off the modern computer and use the MEGA65 as its own programming environment. The survey asked for your preference, and results were split three ways: on-device development, cross development, and “depends on the project” all got roughly the same proportion of responses.

    Demographics

    65% of respondents are between 45 and 54 years old. Remaining respondents are roughly split between 35-44 years old and 55 years or older, with only a few respondents in other age groups.

    The MEGA65 community is international, with strong contingents in Germany and the United States.

    Discussion about the MEGA65 on Forum64.de is almost entirely in the German language, and making MEGA65 programming resources available in the German language is a frequent topic of discussion. For the survey, I asked two questions about spoken language: in what language(s) do you prefer to socialize online, and in what language(s) do you prefer to consume technical information?

    86% of everyone who answered these questions answered both questions with the same language or languages. 80% of these said English. 7% said they preferred German exclusively for both. 10% offered both English and German as their answer in both categories.

    14% of respondents gave different answers for preferred languages for socializing vs. technical information. Of those that gave different answers, 85% said English was preferable or at least acceptable for consuming technical information. 13% preferred technical information in German.

    Danish, Dutch, English, Finnish, French, German, Hungarian, Italian, Norwegian, Polish, Portuguese, Scandinavian, Spanish, and Swedish were all mentioned at least once. I won’t draw any conclusions due to sample size, but it’s exciting to list them all out!

    The survey asked for everyone’s preferred social media service. This is a bad question. Outside of the Digest, the survey was promoted almost exclusively on social media, and so response rates are most likely to correspond to visibility of the survey announcements on those platforms. Nevertheless, it’s good to know that Facebook and X.com (nĂ©e Twitter) are still important ways to reach people.

    Despite how the survey was promoted, 22% of respondents say they do not use a social networking service. There was some ambiguity in the question about whether Discord qualifies as social media. The survey did not include it in the list, but it included a free-text prompt for other services and many used it to mention Discord. Combining social media non-users and users of services the survey did not list, that’s 28% of respondents.

    Other vintage and modern-retro computers

    Nearly every respondent has owned or used a Commodore 64 in their lifetime. 76% of respondents currently own a Commodore 64. Only 2% of respondents have never owned or used a Commodore computer.

    45% of respondents own an SD2IEC device. 35% own an Ultimate 1541 (any model). Of potential interest to future MEGA65 cartridge authors, 21% of respondents own an EasyFlash 3, and 10% own an EasyFlash 1 or 1CR (purchase link).

    34% own, have preordered, or intend to order at least one of several retro-style modern computers that the survey listed. The breakdown between the models isn’t interesting, mostly corresponding to the current availability of those machines.

    Modern computers

    53% of respondents use a Windows computer. 22% use an Apple laptop or desktop. 20% use a Linux laptop or desktop.

    Of the Windows users, 44% are using Windows 11, and 52% are using Windows 10. Several people are using Windows 7.

    Of the Apple users, 73% have an Apple Silicon (M1 or M2) processor, and 26% have an Intel processor. 53% are using macOS 13 Ventura, the latest stable release. 31% are on the macOS 14 Sonoma public beta. 13% are using older versions of macOS.

    I did not ask about Linux distributions or variants, nor did I ask about Intel vs. ARM for Linux or Windows. Tablets (iOS, Android), BSD variants, Windows Subsystem for Linux, AmigaOS 4.1, and MorphOS were represented in the minority replies.

    MEGA65 project feedback

    The survey concluded with an invitation to provide free-text feedback to the MEGA65 project. I will try to summarize common themes and provide my own commentary based on my experiences with the project in the last year. This will naturally reflect my own biases.

    Enthusiasm. Nearly everyone took this opportunity to express words of encouragement and praise for the project. Thank you all for your kindness and generosity! It is gratifying to know there are so many people out there who believe in the MEGA65 project and are enthusiastic about the community and what everyone has accomplished so far.

    Price and shipping cost. As of this writing, the MEGA65 production model, with the mechanical keyboard, injection molded plastic case, and built-in 3.5" floppy disk drive, has a retail price of 666.66 € ($722.38 USD), not including taxes or shipping costs. The total cost to buy one delivered to where I am in the United States is 790.20 € ($856.79 USD). This price alienates some people who are interested in the project, due either to the value proposition or the ability to pay. Less expensive options include running the MEGA65 core on a Nexys Artix A7 FPGA development board, or running the MEGA65 ROM in the Xemu emulator. The central FPGA chip dominates the price, and burning the chipset design into cheaper ASICs would require several orders of magnitude more people interested. (And of course, ASIC-based computers would not be upgradeable.) Counterintuitively, eliminating the floppy drive does not meaningfully reduce the cost, and new plastic case shapes would require an up-front investment in new moulds.

    Shipping delays and shipping updates. Many who have preordered a MEGA65 have experienced shipping waits longer than one year. Estimating shipping dates has been nearly impossible over the past two years due to the unavailability of essential components, and a reliable estimate is only possible after all parts have been acquired by our assembly and distribution partner Trenz Electronic. Trenz has been great about responding to customer service inquiries with rough guesses, but it is not currently a regular practice to send periodic emails to pre-order customers during the process. Some survey respondents expressed concern about the lack of proactive order status communication. Due to privacy laws in Germany, Trenz Electronic is not allowed to share their list of pre-order customers with the project team. The best we’ve been able to offer so far is to use other communication channels to encourage everyone to subscribe to the newsletter or follow project announcement channels on the Discord, YouTube, or Paul’s developer blog. It has been a challenge to make sure pre-order customers are aware of these resources.

    Sources of technical information. The MEGA65 has a substantial amount of technical documentation available, but this can be difficult to notice given how that information is stored and disseminated. Survey respondents pointed out that having information spread over PDF manuals, a Confluence Wiki, and Filehost articles is inconvenient, and it’s unclear where to find each kind of information. Sometimes the easiest way to get an answer to a technical question is to ask the Discord chat, but answers to questions previously asked are difficult to find, and both the community and its discussion archives are only available to Discord users. Discord is an ephemeral medium and does not function as a technical resource, at least not a passive one, and it’s unreasonable to expect all users to read every discussion. Moreover, none of these resources are reliably indexed by search engines, either by design (Discord cannot be crawled; Confluence blocks crawlers) or by unintended technical limitations. Multiple survey respondents wished for a more traditional open-access web forum, and some are disappointed that only a subset of the community participates on Forum64.de.

    Better software. Many MEGA65 owners want to use their computer to run games and applications written by others. Without a large library of quality titles (for some relative definition of “quality”), the MEGA65 is mostly useful for learning to program, writing programs from scratch, or running C64 software via the C64 core (or GO64 mode). Some respondents emphasized that they would be willing to pay for quality MEGA65 software. Some respondents said they are waiting for the software library to grow before investing in a purchase.

    German-language technical resources. Multiple respondents used the free-text feedback field to emphasize the need for German-language technical information. There is a German MEGA65 handbook that is highly valued. The topic of German-language video tutorials, livestreams, and classes comes up occasionally on Forum64.de.

    Technical issues. Several respondents mentioned some of the common technical issues we have experienced in the first year, both in the electrical hardware and in the core and ROM. The new main board revision will help with some of these, and the core and ROM are active projects that welcome contributors. Many respondents expressed gratitude for everyone who is contributing fixes, and are excited to see the work continue.

    Feature areas. Many respondents were excited about the potential for new features, including networking applications, D64 disk image support, more alternate cores, and more on-device programming environments and tools. Several respondents wished for more programming tutorials and recipes. Several respondents expressed an interest in a more compact version of the keyboard case without the floppy drive. Others reminded us that some owners of R3A boards would be interested in buying a bare R5 board as an upgrade. (I considered asking about interest in an R5 upgrade as a survey question, but we don’t know how much such an upgrade would cost. We don’t realize economies of scale in the hundreds of units, so it doesn’t help to forecast sales.)

    More community events and publications. Respondents expressed an interest in more live streams like the MEGAVISION live stream that took place earlier this year. Conferences were also mentioned. There were multiple suggestions for a print magazine.

    Reach

    One of the biggest questions I wanted to answer with the survey was, how effective have we been at connecting the MEGA65 community with the project, and how can we improve? Communities around projects tend to form layers of engagement, and we want to foster the growth of all of those layers and reach as many people as possible that would benefit from the project. We have known issues with making resources available in search engines and providing information to pre-order customers. We can only hope that as people get more interested, they look for community resources more aggressively.

    The first test was simply, how many people can we get to take the survey? 509 respondents feels downright miraculous considering that only 900 people currently own a MEGA65 (DevKit or production model). We aren’t privy to the number of pending pre-orders but we believe it is over 1,000. The survey promotion reached quite a few people who are interested enough in the project to take the survey but have not yet pre-ordered, but it’s impossible to guess the size of that population from the survey alone.

    Our limited ability to reach out to the community makes it difficult to promote resources like Dan’s MEGA65 Digest, and difficult to promote community projects that require financial support. A small number of free-text responses in the survey ask for things that already exist, which suggests that we could be doing more to promote the resources we already have.

    The survey asked about several specific community resources, projects, and concepts, and made a distinction between “I know about that resource but don’t use it” vs. “I didn’t know about that resource.” These replies are a useful indicator of how well information about the project has disseminated. The following numbers are shown as percentages of owners. Owners are more likely to be familiar with resources, and have a known population size as a basis for the sample. This is not meant to exclude non-owners from consideration, only to have a basis for comparison.

    * 10% of owners replied that they did not know about the JTAG or UART serial adapter.

    * 4% did not know about the DevKit.

    * 13% did not know about the Nexys FPGA dev board.

    * 34% did not know abut the Wukong FPGA dev board.

    * 20% did not know about Hibernated 1 by Stefan Vogt. The numbers were similar for Showdown by Badger Punch Games.

    * 13% were unaware of the Xemu emulator.

    * 5% were unaware of the PDF manuals.

    * 16% were unaware of the MEGA65 Welcome Guide.

    * 22% were unaware of Dan’s MEGA65 Digest.

    * 8% were unaware of Filehost.

    * 7% were unaware of the MEGA65 Discord.

    * 14% were unaware of Forum64.de.

    Conclusions and next steps

    The MEGA65 is an open source volunteer-run project. It doesn’t have development resources so much as interested parties. Nevertheless, many people who work on the project want the project as a whole to succeed, and want to work on important things, so seeing which tasks can have the most impact can influence contributors.

    I can’t speak for anyone else, but personally, I’m more motivated to work on information visibility. This was already my area of focus with the Digest. I have ideas for making our information easier to find in search engines, and I hope to use my web development background to improve our web-based resources and community tools. I also want to evolve the Digest to make it more visible and interesting to a larger audience. The Digest is our primary tool for disseminating news and project status—including best available information on shipping updates—and I want everyone who is interested in the project (at any level) to at least be aware of it.

    I’m excited to see that we might be able to afford a high-quality print run of the manuals, if we can finish them. Print books are a fun addition to the retro experience, and they’re one of my favorite things to make. It’s good to be reminded by the data that many people would prefer browser and e-reader-friendly resources, and hopefully we can produce both print and web resources using the same content.

    There’s an opportunity for German content creators to fill a need. Bloggers, YouTubers, and live streamers capable of producing tutorials and walkthroughs in German—at any level of technical complexity or production value—could have a big impact. I’ve seen people ask for German-language BASIC programming introductions on Forum64.de. You don’t need to know a ton about the internals of the machine to help others with their first steps, and simply blogging your own learning adventure can attract a grateful audience. We can also consider crowdfunding a professional German translation of the manuals once they are reasonably complete.

    There’s no shortage of interest in improving the platform or the hardware, just a shortage of time. I believe our open source processes are in decent shape, so if anyone is interested in helping out, please reach out on the Discord. Bug reports are always welcome, even if you are unable to submit bug fixes.

    As for growing the software library, the number of owners is expected to more than double by the end of the year. It’ll be exciting to see what everyone comes up with!

    That’s it for this year’s survey! Thanks again to everyone who responded. Let me know if you have any feedback on the survey itself or this report. We might do this again next year.



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • Hey all! I’m keeping this issue short, because there’s something more important for you to do instead of reading.

    The MEGA65 Community Survey 2023

    The MEGA65 Community Survey 2023 is now open. This survey is for anyone even a little bit interested in the MEGA65, whether you own one, have preordered, are still considering it, or don’t intend to order but still enjoy seeing what’s going on. This includes anyone not subscribed to this Digest, so please share this link.

    Responses are anonymous. We will share aggregate anonymized results in a future Digest. Full-text replies will be kept confidential to the MEGA65 Steering Committee.

    We’re targeting 400 responses for this year’s survey. If everyone subscribed to the Digest responds, we’ll hit that easily. (Please only take the survey once, so we get accurate counts.)

    Here’s that link again: please take the survey. Your response will go a long way to guiding the future of the MEGA65 project. Thank you!

    New Galaga core!

    After you have completed the survey, it’s time to hit the arcade! Run don’t walk to the Galaga core for the MEGA65 by muse. This isn’t just a version of Galaga for the MEGA65, this is Galaga, a port of the original arcade hardware architecture running directly on the MEGA65 FPGA. The core even supports connecting a vintage VGA monitor turned on its side to fully replicate the arcade experience.

    Installation requires a few steps, including fetching the original Midway Galaga ROM from the Internet (using the link provided) and running a Python script. See muse’s installation instructions.

    When starting the core, give it a minute to go through the arcade hardware test routine. The core displays its keyboard controls briefly; press the spacebar to dismiss. Press 5 to insert a quarter, then press 1 to start a one-player game. You can control the game via a joystick in port 1, or use the keyboard: A and Z move left and right, and the Cursor Up key fires. The P key pauses. As with the C64 core, press the Help key to open a settings menu.

    Huge thanks to muse for this effort, and to all of the original implementors of the core. (And to Midway too, but they already have all of my lunch money.)

    R4 is now R5

    Last month I mentioned that there will be a new revision of the main board that will start shipping with the next delivery batch, known as R4. Due to restricted availability of a component, the board needs one more revision. This gives us an opportunity to further refine the cartridge interface before the revised board goes into production, so we’re taking that opportunity. The core needs a corresponding adjustment, so the board is now known as “R5” to distinguish between the core builds. R4 boards will not be manufactured. The next delivery batch will receive R5 boards.

    The cartridge interface enhancements will make it possible to support fancier utility cartridges. As with the other revisions, only time will tell what differences will actually be notable in practice. The most important reason to know which main board revision you have is to download the correct versions of core files.

    Pudding Mountain Miner 65

    I said I’d keep this short, but I can’t resist including a bit of BASIC fun.

    Of all the Commodore 64 games that could have been a staple of my childhood, an unlikely contender was “Pudding Mountain Miner” by Charles Brannon. Brannon was an editor for Compute!’s Gazette magazine, and originally wrote “Pudding Mountain Miner” as a short type-in to appear in newspapers promoting the magazine when it was getting started. He wrote up an explainer in the April 1985 issue of Gazette, in the “Horizons” column.

    The game is a one-button shooter where you’re a fighter pilot dropping bombs on Pudding Mountain, digging for buried treasure. If you hit the dollar sign, you win the big bucks. If you hit the mantle underneath the pudding, it’s game over.

    I liked Miner because it was fun and cute, and also because it was only 17 lines of BASIC code. I don’t think I ever bothered to save it to disk. I would just type it in any time I wanted to play it.

    Here’s the program listing converted to a form where you can use it with petcat to generate a PRG in case you don’t want to type it in (but what’s the fun in that?). This version runs just fine with the MEGA65’s GO64 mode.

    100 v=(peek(0)=76):w=40+18*v:t=1024-6656*v:c=55296+16896*v:s=53281+16402*v110 c$=chr$(147):printc$:pokes,1-26*v:for i=0tow-1:q=22*w+i115 poket+q,160:pokec+q,7:next120 s$=chr$(32)+chr$(158)+chr$(18)+chr$(188)+chr$(146)+chr$(156)+chr$(185)130 s$=s$+chr$(31)+chr$(175):q=rnd(1)*(w-7)+3+22*w:poket+q,164:pokec+q,5140 fori=0tow-1:forj=0to7*rnd(1)+3:q=(21-j)*w+i:poket+q,160:pokec+q,2:next:next150 printchr$(142);chr$(19);:y%=4*rnd(1)+1:fori=1toy%:print:next:x=0160 l$=chr$(157):prints$;l$;l$;l$;:x=x+1:geta$:ifa$=""andx

  • In last month’s Digest, we introduced cross development, the practice of writing MEGA65 programs using a modern PC. We looked at several tools for writing programs in the BASIC 65 language and in 45GS02 assembly language, and we welcomed a new BASIC-like compiled language with MEGA65 support called XC=BASIC.

    Let us take one step further into the world of compiled languages. The C programming language is one of the most widely used programming languages in computing history, suitable for everything from microcomputers to mainframes. It was the language that built the Unix operating system—or maybe it was the other way around. Fifty years later, C is still in widespread use, for better and for worse.

    As fun as it is to write in assembly language, larger programs benefit from a language with a bit more structure to manage the inherent complexity of software. There are several cross-development tool chains for writing Commodore programs in C, and these can also be used to write programs for the MEGA65. In this issue, we will try using one of these tools to write our first C program, and walk through the concepts involved. We’ll look briefly at other tools and resources for getting started with C programming for microcomputers. And we’ll consider a much newer language vying to be the C of the next fifty years, called Rust.

    Featured Files

    We’ve been talking about coding tools lately, so let’s do an all-tools edition of Featured Files!

    The Coffeebreak Compiler by TOS22. Matthias wanted a comfortable way to hack on assembly language code directly on his MEGA65 that he could extend with modern conveniences. The result is a lightly structured custom language and IDE that accepts inline assembly code and produces machine code programs, similar to ubik’s Eleven for BASIC. Press the Help key to browse the built-in documentation and tutorials.

    MEGA65-Forth alpha by carthibar. MEGA65-Forth is a project to build an interpreter and interactive environment of the Forth programming language for the MEGA65. This is an early release with some features still in progress, but enough has been implemented to start learning the language. It is based on FIG Forth 1.1. Check out the source code and release notes on Github, as well as the Getting Started documentation.

    bf65 by dddaaannn (that’s me!). The experimental minimalist programming language known as Brainfuck was invented by Urban MĂŒller in 1993 as an attempt to design a language with as small a compiler as possible that is still Turing complete. The language is famous for its funny name and for having only eight parameterless instructions. I was motivated to write bf65 when I had the idea to take advantage of the MEGA65’s built-in BASIC editor as the editor for bf65 programs, including the ability to combine BASIC and bf65 code in the same program. The D81 disk image includes the bf65 interpreter and several demo programs. See documentation and source code on Github.

    C64 for MEGA65 V5 is official!

    We’ve mentioned the Commodore 64 core for the MEGA65 a few times in this Digest, and with good reason. For many owners, the potential of the MEGA65 to be an FPGA-based multi-Commodore platform is a major attraction, a chip-level recreation of an entire line of vintage computers that share a non-PC keyboard layout, made from all-new components and modern hardware conveniences. The Commodore 64 core by MJoergen and sy2002 is a huge step toward this potential.

    C64 for MEGA65 version 5 is now officially released. For installation instructions, see the May issue of the Digest, and the excellent documentation.

    Don’t miss the epic video trailer for the new release!

    MEGAVision video now available

    The first ever MEGAVision live streaming event took place on July 1st and was a huge success! Hosted by RetroCombs, Gurce, and lydon, MEGAVision featured nine short talks about MEGA65 projects. Watch the replay online, then visit the MEGAVision wiki page for links to resources for everything discussed in the presentation. I was happy to present my bf65 toy language interpreter at the event.

    This was so successful that we’re excited to do another one sometime soon. Start thinking about topics you’d like to know more about, or topics you’d maybe like to talk about at the next MEGAVision. If you have an idea for a talk, send a message to Gurce or lydon on Discord.

    Huge thanks to the organizers, to everyone who gave a talk, and to everyone who attended!

    R4 mainboard announced

    The MEGA65 project continues to invest in improving every aspect of our favorite computer. On June 30, Paul posted an in-depth article to his developer blog describing some of the recent improvements made to the design of the MEGA65 main board. The next revision of the main board, known as R4, will start shipping with the next delivery batch later this year.

    Several of the improvements in the R4 board are electrical. There’s a fix for an HDMI back-power issue, improved audio quality from the 3.5 mm jack, a new Real-Time Clock (RTC) unit, and improved RF shielding for the major components. The design has also been reworked to use one fewer FPGA chip. These changes resolve some minor issues, but they otherwise do not affect the operation of the computer.

    Two changes enhance the capability of the system slightly. There is now additional RAM hardware that can be used by FPGA cores, enabling porting of a larger variety of MiSTer cores in the future. Also, the joystick ports are now bi-directional, a capability used by a few peripherals like the Protovision Protopad and the Commodore version of the AtariLab science kit that I had as a kid.

    Nothing about the MEGA65 platform changes with this revision. Any program written for the MEGA65 will run on both R3 and R4 boards. While the RAM hardware is intended to enable broader development of alternate cores, no core currently exists that needs it, and it’ll be a while before one does. Moreover, future cores that don’t need the extra RAM are unlikely to use it, so that they will work on all MEGA65s.

    Nevertheless, it’s natural to wonder: will MEGA65 owners with the R3 main board be able to buy the R4 board as a replacement? Hopefully someday! The first priority is to fulfill all of the remaining preorders for complete MEGA65s. Beyond that, it’s not obvious that Trenz Electronic can feasibly stock spare parts, especially pre-assembled main boards with expensive FPGAs. So far, preorders have been fulfilled in batches, and it’ll take time to figure out the costs, risks, and logistics of switching to an in-stock distribution model. I know I’d love to be able to someday buy MEGA65 parts for upgrades, repairs, and building new machines with custom configurations.

    For now, I’m excited by how the R4 main board is an investment in the MEGA65’s continued success. More than anything else, it means we will all get more out of our computers, no matter which version we have.

    A single-file C program

    A compiler is a tool that takes a computer program written in some programming language and generates an equivalent program for the target platform’s machine code. You can write a program in the C programming language, then use a C compiler to generate the equivalent machine code program for the MEGA65.

    As with other development tools, a compiler could be a program that runs on the target device directly, like how Mega Assembler runs on the MEGA65. There is not yet a C compiler that runs natively on the MEGA65, but it is possible to use a cross development workflow as we did in the previous issue of the Digest. You create a source file on our PC, then use a cross compiler to generate a MEGA65 PRG file.

    As much as I want to, I can’t fit a full C language tutorial in this Digest. Nevertheless, let’s start with a small C program, so we have something to play with:

    #include int main() { puts("IT'S A C PROGRAM!\n");}

    Put this in a file named hello.c. This is our source file.

    Most C programs consist of multiple source files, with filenames ending in .c for definitions and .h for declarations (“header” files). Exactly one .c file defines a function named main(), which is where the program begins. A source file can #include header files to learn about functions provided by other modules. In this case, #include brings in the declarations from a module of the C standard library, including a declaration for the puts() function used by the main() function. Refer to any good book on C programming for an explanation of how C programs are organized.

    An ideal compiler targeting the MEGA65 would know all about the inner workings of the MEGA65’s CPU, so it can use all of the CPU’s features in its machine code. So far, nobody has written a C compiler that targets the MEGA65 specifically. Instead, we’ll take advantage of the MEGA65’s Commodore lineage and use a cross compiler that targets earlier Commodore computers. Several Commodore cross compilers can be adjusted to generate programs that run on the MEGA65.

    Installing llvm-mos

    llvm-mos by Daniel Thornburgh and John Byrd is a cross compiler toolchain for target platforms based on the 6502 CPU. It provides a version of Clang for compiling C programs. Thanks to Mikael Lund (wombat on the Discord), llvm-mos supports building programs for the MEGA65. It supports generating code for CPUs in the 6502 lineage up to the 65C02, which will run fine on a MEGA65.

    Visit the llvm-mos Github page, then scroll down to find the download link for your PC’s operating system. As usual, macOS requires an additional step to allow unsigned command line tools to run. A complete procedure for macOS users:

    * Download llvm-mos for macOS.

    * tar xzf llvm-mos-macos.tar.xz

    * xattr -d com.apple.quarantine llvm-mos/bin/* Ignore the list of “No such xattr” warnings.

    * Verify that the mos-mega65-clang command line tool works: ./llvm-mos/bin/mos-mega65-clang --help

    As noted in the llvm-mos documentation, you can add the bin/ folder to your command path for convenient access. macOS users, heed the warning that doing so may conflict with other versions of the Clang compiler you may have installed. The Apple Xcode Command Line Tools provide another version of Clang, and you may have this installed if you use Homebrew even if you don’t otherwise use Xcode. You do not need to have llvm-mos on your command path to use it: simply provide the full path to the llvm-mos commands when using them.

    You can compile the hello.c example program with the following command:

    ./llvm-mos/bin/mos-mega65-clang -Wall -Os -o hello.prg hello.c

    This produces the file hello.prg that you can run in Xemu or on your MEGA65, as we discussed in the previous issue. It loads to the top of BASIC memory with a BASIC bootstrap header, similar to the one we used for our assembly language program.

    The equivalent program

    So far, a compiler sounds a lot like an assembler: it takes a source file and produces a PRG file that does what we want. What’s different is how the tool decides what machine code to generate. When we write a program in assembly language, we must say exactly which machine code instructions the target machine’s CPU should execute. Assembly language mnemonics like LDA represent machine code instructions in a somewhat-human-readable syntax, and the assembler translates the assembly language to machine code, one instruction at a time.

    When you write a program in a compiled language, the compiler reads through your program, then decides which machine code instructions will do what you intend. You can ask llvm-mos to show you the assembly language program that it came up with for your C program with this command:

    ./llvm-mos/bin/mos-mega65-clang -Os -o hello.s -Wl,--lto-emit-asm hello.c

    This generates an assembly language listing as the file hello.s. Open this in a text editor to see the result. It is quite large because it includes the code for the puts() function from the standard library.

    To get a better idea of what compilers can do, consider a simpler program that doesn’t involve a call to a large function:

    int square(int num) { return num * num;}int main(void) { return square(5);}

    There’s a website called Compiler Explorer, aka “GodBolt.org,” that can show C code and the compiled assembly code side by side directly in your browser. It supports many compilers and target CPUs, including llvm-mos and the MEGA65, so you can see the result in 6502 assembly language.

    Follow this link to see one possible version of square() and main() produced from this C code.

    In this example, you can see how llvm-mos converts the square() function into several dozen instructions. The labels that begin with two underscores, such as __rc0, refer to addresses in the base page that llvm-mos sets up to be used as temporary variables by the generated code. Later in the listing is the implementation for the main() function that sets up the argument (5), calls the square() function, and ends with the result in a variable. The C language requires that the main() routine returns a number, which is used by some operating systems as a result code from a program. The MEGA65 just ignores this return value.

    But that’s just one possible assembly language program. Check out this version with the -Os flag enabled.

    Given the -Os flag, llvm-mos generates different assembly language code for the same C program. It’s much shorter and much faster than the previous version. How can a compiler look at the same program and produce two drastically different results?

    In the first version, llvm-mos took our C program literally: we wrote it as two functions, so it generated code for two functions. In this new version, llvm-mos studied the C source code, realized that this program always returns the number 25, so it produced machine code that returns the number 25. Both of these assembly language programs are equivalent to the original C program: they both return 25.

    An optimizing compiler uses many complex techniques to calculate the smallest and fastest machine code possible that is equivalent to your original program. The -Os flag enables all of llvm-mos’s optimization rules. Optimization is typically smart enough that you can leave it enabled for nearly all purposes. It’s not always perfect—I can’t explain why llvm-mos generates a few instructions for the square() function in the optimized version even though it never calls them—but it’s a huge benefit.

    Just as modern chess computers can play chess better than any human, modern compilers can write machine code so efficient that it’s almost not worth writing in assembly language at all. We still write assembly language programs for the same reason we still play chess: for fun.

    CMake, mega65-libc, and mega65-llvm-template

    Running the mos-mega65-clang command is fine enough for simple one-file experiments. When your project grows to multiple source files or involves third-party libraries, you will want a build management tool. CMake and Ninja are popular with the modern C crowd. (I still use GNU Make, but I’m old school.)

    One third-party library you’ll want to consider early on is mega65-libc, the MEGA65 project’s own set of utility functions. This library provides functions that access files from a disk or the SD card, access memory, power a console-like user interface, and more. The library is useful enough for things like debugging that you pretty much always want to include it in your project, even if you don’t intend to use most of it. The compiler will only generate code for the functions that you use.

    Thanks to kibo, there’s an easy way to get everything you need to set up your MEGA65 C project, including CMake and mega65-libc. mega65-llvm-template is a Github project template that you can either use to create a new Github repository, or just download to try it out. See the template’s documentation for instructions.

    MEGA65 C tips and tricks

    Before you dive into a good book on the C language, it’s important to note that llvm-mos has a few limitations when it comes to standard C. For starters, it does not support the float or double fractional number types. The 6502 CPU does not have built-in support for floating point math, and llvm-mos does not provide a floating point math library. If you’re ambitious, you could consider third-party assembly language routines for this purpose, such as “Floating Point Routines for the 6502” by Steve Wozniak, from the magazine Dr. Dobb’s Journal in August 1976.

    llvm-mos provides a stripped-down version of the C standard library implemented for Commodore computers, using C64-style kernel calls for things like printing messages. The implementation is incomplete, and some functions may not work correctly on the MEGA65. It’s worth trying, just don’t expect everything to work.

    If your C program returns from main(), either with the return statement or by allowing control to reach the end of the function, the program llvm-mos generates will attempt to return to BASIC. This doesn’t always work with the MEGA65 kernel. I sometimes get weird display artifacts, false BASIC errors, or crashes when returning from main(). Consider ending your program with an infinite loop (while(1);) and not relying on exiting to BASIC.

    In C, character values ('x') and string values ("xyz") are treated as ASCII byte values. These are neither PETSCII values nor Commodore screen codes, so you will need to account for this when defining and printing text messages to the screen. Using uppercase ASCII letters in your C source code along with the MEGA65’s default uppercase character mode will print uppercase letters.

    If you’re writing a game—or pretty much anything, honestly—your program will need to access registers and memory addresses directly, similar to POKE and PEEK from BASIC, or lda and sta in assembly language. This is possible in C, taking care to use C’s pointer dereferencing features correctly. Use an appropriate value type for bytes (such as uint8_t from stdint.h), and be sure to refer to an I/O register as volatile to prevent the optimizer from taking shortcuts. mega65-libc’s memory.h provides useful macros and functions for accessing registers, so it looks cleaner in your code and you don’t have to remember the details:

    #include // From mega65-libc:#include ... POKE(0xD020, 5); uint8_t joy2 = PEEK(0xDC00); // Without mega65-libc: (*(volatile uint8_t *)(0xD020)) = 5; uint8_t joy2 = (*(volatile uint8_t *)(0xDC00));

    Programs generated by llvm-mos start by unmapping the BASIC ROM to make more room for program memory. The program code starts at address $2001, including the BASIC bootstrap program. The space beyond the end of the program up to address $CFFF is used for memory managed by the C language, a total of 44 kilobytes for both program and memory. Memory allocated by the program using the C standard library malloc() function, a mechanism known as the heap, starts just after the program and “grows upward” toward higher addresses. The stack, used for keeping track of function calls and local variables, ends at address $CFFF and “grows downward” toward lower addresses. The I/O registers remain in $D000-$DFFF, and the kernel ROM in $E000-$FFFF.

    Sometimes you’ll want the ability to write assembly language code inside your C code. Clang supports the GCC inline assembly syntax, expecting to output 6502 assembly language for llvm-mos’s assembler. This requires giving the optimizer some hints about what the assembly code does, so it can make decisions about using CPU registers and relocating code. The following example from mega65-libc takes an unsigned char variable from the C code and calls a “Hypervisor trap” with a bit of assembly language, informing the optimizer that this code must be executed in this location (volatile) and that it uses the accumulator ("a"). Notice how the assembly language text is a single C string with newline delimiters (\n).

    unsigned char the_char;void debug_msg(char* m){ // Write debug message to serial monitor while (*m) { the_char = *m; asm volatile("lda the_char\n" "sta $d643\n" "clv" ::: "a"); m++; } // ...};

    A sophisticated program might want to install interrupt handlers that call C functions, such as a raster interrupt handler that is called once per frame. This is an advanced technique that requires disabling interrupts, setting the address of the function, and updating the MAP register to disable the kernel. I won’t include a complete example here, but here’s one way to get the address of a C function as two bytes, using volatile once again to make sure the optimizer keeps the function even if it isn’t called by the rest of the program.

    volatile void do_frame(void) { // ...}// ... unsigned char addrlow = (long)do_frame & 0xff; unsigned char addrhigh = ((long)do_frame >> 8) & 0xff;

    Enable compiler warnings. The C language gives you plenty of opportunity to make mistakes, and Clang is very smart about noticing potential issues in your code. The command line flags -Wall -Wextra -Wpedantic tell the compiler to go crazy with the constructive feedback. To enable this using the mega65-llvm-template, add this to the file CMakeLists.txt:

    target_compile_options(hello.prg PRIVATE -Wall -Wextra -Wpedantic)

    Learning more about C

    The most famous book for learning the C programming language is The C Programming Language by Brian W. Kernighan and Dennis M. Ritchie. Ritchie invented the C language, and this concise book is a computer science classic.

    My favorite book for learning C is C Programming: A Modern Approach, 2nd edition, by K. N. King. It’s excellent for self-learning with high quality and well tested examples and exercises. I’ve literally read this book cover to cover and have done nearly all of the exercises, and I still go back to it to remind myself of language intricacies.

    I wouldn’t be surprised if many of the examples from these books worked on the MEGA65, but I would be surprised if they all did. If you’re new to the C language, I would recommend starting with a C compiler for a modern computer first: Xcode for macOS, GNU C for Linux, Visual Studio Community for Windows. You will only need a subset of C’s features to write substantial programs for the MEGA65.

    There are several other C compilers that work reasonably well for MEGA65 development. cc65 is popular with C64 programmers and has a long history. It is used by the MEGA65 project in many places. KickC is another, using the venerable Kick Assembler for generating machine code. Calypsi by hth313 is a C and assembly development toolkit for several vintage computers. Calypsi’s MEGA65 support is in early stages, but it already supports 45GS02 instructions, 64-bit integers (long long), and floating point math.

    I chose llvm-mos for this Digest because it takes advantage of the LLVM ecosystem to have the most complete implementation of the C language and the best optimizer. With a built-in MEGA65 configuration, it’s also just the easiest to get running for MEGA65 projects.

    Other llvm-mos tools

    The LLVM project reinvents the way cross compilers are built: instead of a single compiler dedicated to a single language and target system, LLVM is divided into separate layers for the language, the optimizer, and the target. llvm-mos is a target backend for Commodore computers, and is able to take advantage of a suite of cutting edge tools and language frontends. Because it is based on LLVM, llvm-mos is able to power multiple language compilers, and use the state-of-the-art optimizer from the LLVM core.

    The llvm-mos package you just installed includes not only the C compiler called Clang, but also a C++ compiler Clang++. Start writing C++ programs for your MEGA65 today with the mos-mega65-clang++ command!

    The clang-tidy command is a tool known as a static analyzer. It can examine your C code, find bugs, and recommend improvements. Programming IDEs like Visual Studio Code can be configured to run such tools automatically to highlight problems as you are coding. Tell VSCode to use the language server included with llvm-mos, called clangd.

    You can find all of these and more in the bin/ folder of llvm-mos.

    Rust

    Take everything you’ve just learned about C and throw it in the bin! The new hotness that all the kids are on about is Rust.

    #[start]fn _main(_argc: isize, _argv: *const *const u8) -> isize { let mut rng = sid::SIDRng::new(c64::sid()); for offset in 0..80 * 25 { let character = [77u8, 78u8].choose(&mut rng).copied().unwrap(); unsafe { mega65::DEFAULT_SCREEN .add(offset) .write_volatile(character) }; } println!("HELLO MEGA65 FROM RUST"); 0}

    Rust is an important new language that intends to be just as powerful as C while making it easier to write programs that are more secure and have fewer bugs. I won’t go into detail on Rust for this Digest—I’m still learning it myself—but I wanted to take a moment to highlight the work wombat has done to bring Rust programming to the MEGA65. See wombat’s MEGAVision talk for a brief video overview.

    rust-mos by Mariusz Krynski is a version of the Rust compiler customized for Commodore microcomputers. It requires llvm-mos, with modified installation instructions. Setting up the tool chain is somewhat involved, so read the README file carefully, or consider using a pre-made Docker image if you’re familiar with how to do that. wombat’s mos-hardware is a Rust “crate” with libraries and examples for interfacing with MEGA65 hardware. There’s also a project template: mos-hardware-template.

    For learning the Rust language, start with Learn Rust, the official online book and other resources. We’re still figuring out the best way to write Rust programs for the MEGA65, so be sure to join us in the #rust channel on the MEGA65 Discord.

    Compared to assembly language, languages like C and Rust provide abstractions that make programs easier to write and understand. They are essential tools for producing large programs whose complexity can be difficult or expensive to manage. Even without perfect compilers that take full advantage of the MEGA65 CPU and memory system, the tools currently available provide plenty of power for MEGA65 development. I still try to write in assembly language occasionally to feel a sense of camaraderie with early programmers that didn’t have these tools, but it’s good to know that they’re just an arm’s reach away.

    Happy coding!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • There’s something wholesome about writing a program on a vintage computer. Such a computer was designed to give equal attention to programs written by their operator and programs written by software companies, and included everything you would need to get started writing such programs. Compared to modern software development, the constraints of on-device retro coding can be comforting and inspiring. When all you have is a Commodore, some graph paper, and a reference manual, you can concentrate on creating programs and solving problems without distraction.

    Professional software companies didn’t always do it this way. Larger companies often used other computers to produce Commodore software, such as a mainframe computer with larger storage, computation, and multi-user collaboration capabilities. They would write code using languages like C, and use specialized tools that combined the efforts of programmers and artists into data that could be written to a disk and run on a Commodore. Known as cross development, this workflow gave these companies a competitive advantage: they could work faster, collaborate better, reuse code across projects, and even develop their programs for multiple kinds of computers at the same time.

    Today, many hobbyists use modern computers to write programs for vintage machines. There are so many good cross-development tools at our disposal that we can’t cover them all in one Digest. This month, we’ll consider the advantages of cross development, and survey a few tools you can use to write MEGA65 programs in BASIC and assembly language. We’ll highlight recent developments in these tools made specifically for MEGA65 programming. And we’ll introduce an exciting new cross-development language that has just added MEGA65 support: XC=BASIC.



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • The MEGA65’s VIC-IV video chip has multiple graphics modes. Each mode and feature pulls ideas from some point in vintage computing history: terminal-style text output, character graphics, hardware sprites, palette banks, full-screen scrolling, and even Amiga-style blitter objects and graphics-optimized DMA operations. Several VIC-IV modes are fully backwards compatible with the VIC-II of the Commodore 64 and 128, and the VIC-III of the Commodore 65.

    In today’s Digest, we’ll be looking at the VIC-III bitplane graphics mode. While this mode doesn’t show off all of the MEGA65’s capabilities, it’s one of the more fun modes to use with BASIC 65 thanks to its library of 31 drawing commands and functions. In Featured Files, we’ll see a new game that takes advantage of BASIC 65’s graphics system to draw vector art. We’ll also try using a built-in feature to display full-screen high color photographs and illustrations.

    Featured Files

    This month’s Features Files are all brand new, hot off the presses!

    Onion Cake and the Hungry Dinosaurs, by Gurce. This short comedy adventure game combines a text command interface with gorgeous full-screen vector art by Gurce’s sister Ayca and original music. You get to watch the BASIC code fill in the image as it loads each scene, and the code cleverly uses the MEGA65’s memory and DMA features to cache the render so they display instantly on subsequent visits.

    Gurce wrote a MEGA65 vector art editing tool, called VART, to develop the image format used by the game. Both the game and the editor are written in the Eleven programming environment.

    Onion Cake and the Hungry Dinosaurs is inspired by another MEGA65 game, Escape from Onion Cake by MrZaadii, from his Mega65 Games Pack from 2018. MrZaadii’s game also uses bitplane graphics with pixel art, pre-dating some of the newer graphics features that were added by the MEGA65 team.

    Don’t miss Gurce’s behind-the-scenes presentation of the making of Onion Cake.

    Old Mine Hoist by GeirS. This addictive one button game has you lowering a box of supplies down a perilous mine shaft. Struts on the mineshaft walls and barrels of dynamite risk damaging your payload. How far can you get?

    Rescue Inc. by SirLazarus. An original solitaire strategy game written in BASIC 65. Launch probes to locate missing battleships in the dark ocean waters. Try to find all the ships with as few probes as possible.

    C64 for MEGA65 V5 alpha releases

    In last November’s Digest we mentioned the Commodore 64 core for the MEGA65 by MJoergen and sy2002, the best way to run Commodore 64 software on MEGA65 hardware. The core completely reconfigures the FPGA for a precise recreation of the Commodore 64 chipset, capable of running software with a very high degree of accuracy and compatibility. The latest stable release is version 4, with support for D64 disk images on the SD card, joystick port peripherals, built-in RAM expansion, and multiple display modes for modern displays.

    The C64 for MEGA65 project is ramping up for a major upgrade with release 5. sy2002 has been posting alpha releases to the Discord, and you’re invited to help test! As of V5 alpha 22, the core supports:

    * Running virtual cartridges as CRT files from the SD card

    * Running Commodore 64 PRG files directly from the SD card

    * Connecting IEC devices to the MEGA65’s IEC port, including external disk drives and printers

    * Connecting C64 hardware cartridges to the MEGA65’s expansion port, with support for EasyFlash 1 cartridges

    * Installing a licensed JiffyDOS ROM for use with IEC disk drives

    As this is an alpha testing release, it comes with a few caveats and has known issues. Be sure to read through the list before installing an alpha release.

    For simpler C64 hardware cartridges, you can turn off the MEGA65, connect the cartridge, hold the No Scroll key while turning it on, then select the C64 core from the core selection menu. Remember that if you allow it to boot with the MEGA65 core, it’ll just try to run the cartridge software in its C64 mode, which is not the same as the C64 core and is less likely to be successful. lydon is working on improving the MEGA65 core such that the boot-up process can be configured to automatically select different cores for different types of hardware cartridges.

    For EasyFlash and some fancier cartridges, the core selection menu won’t work at all with the cartridge connected. To get this to work, you have to do something we would have considered unthinkable in the days of static-sensitive PLA chips: start with the cartridge not connected, boot with No Scroll, select the C64 core, then connect the cartridge and press the reset button on the side of the machine.

    EasyFlash 1 or 1CR works with the latest alpha release. EasyFlash 3 does not yet work. You can buy an EasyFlash 1CR from Daniel Mantione (dmantione in the MEGA65 Discord). Be sure to also order a Protoparts enclosure from Daniel (or from Protoparts directly) to ensure the best fit in the MEGA65 cartridge port.

    When using the IEC port with the C64 core to connect disk drives, keep in mind that the C64 core always uses device number 8 for the virtual drive for D64 disk images. Set your external drive to any other device number for use with the C64 core. You can use this set-up to copy D64 disk images to physical floppy disks and vice versa.

    Whether you’re installing the C64 core’s latest stable release V4 or trying out the V5 alpha release, the installation process is the same:

    * Download the C64-for-MEGA65 release that you want to install, and unpack the archive.

    * Copy the .cor file to the root of your MEGA65 SD card.

    * Make a folder in the root of the SD card named c64.

    * Copy the file named c64mega65 to the c64 folder. Also take this opportunity to copy any D64, CRT, and C64 PRG files you want to try to the c64 folder as well.

    * Reinstall the SD card in your MEGA65.

    * With the MEGA65 turned off, hold the No Scroll key, then turn it on. This opens the core selection menu.

    * Select a core slot to overwrite with the core, then hold Ctrl and press the number for that slot. Follow the prompts to install the C64M65~1.cor file.

    If you’re juggling multiple versions of the C64 core, be sure to use the c64mega65 file that comes with that version. This file saves your menu preferences, and the file format has changed between V4 and V5.

    Visit the #c64-core channel in the MEGA65 Discord for alpha release downloads, release notes, and troubleshooting issues.

    Saying hello to BASIC 65 bitmap graphics

    Gurce’s Onion Cake and the Hungry Dinosaurs and MrZaadii’s original Escape from Onion Cake both use the bitmap graphics system built in to BASIC 65. This subsystem allows for rendering high resolution pixel perfect images using BASIC commands. Bitmap graphics are implemented as a separate graphics mode from the text mode you see when writing programs, so you can only see either the text screen or a graphics screen on the display at one time. There are 31 commands and functions you can use to manipulate screens and draw figures in your BASIC programs.

    Because the graphics screen hides the text screen, this isn’t easy to experiment with from the READY. prompt. Instead, you can use a short program like this one:

    10 SCREEN 320,200,220 PEN 130 LINE 25,25,295,17540 GETKEY A$50 SCREEN CLOSE

    In this example, line 10 opens a new screen that is 320 pixels wide and 200 pixels tall, with a palette of four colors (a “bit depth” of 2). Line 20 sets the color used by subsequent drawing commands (the “pen” color) to palette entry 1 (the second of four colors), in this case using the default palette’s color of white. (See the PALETTE command for a way to change the palette colors.) Line 30 draws a line using the pen color from screen coordinate (25,25) to (295,175), a diagonal stripe.

    Line 40 pauses until the user presses a key, and line 50 closes the screen and returns to text mode. This is a useful recipe when you’re experimenting with graphics commands. If your program exits without closing the screen, the MEGA65 will stay in graphics mode and you won’t be able to see the READY. prompt. This can happen if there is an error in your code that stops the program before it closes the screen. If your program appears to get stuck showing a graphics screen, hold Run/Stop and press Restore to reset the display to text mode and a fresh READY. prompt.

    The graphics system supports widths of either 320 or 640 pixels, heights of either 200 or 400 pixels, and color bit depths from 1 (two colors on screen at a time) to 8 (256 colors). You can have up to 16 colors (bit depth 4) with a 640x400 screen, and up to 256 colors (bit depth 8) for the other possible resolutions. It is possible to allocate multiple screens and switch between them, though this limits the possible sizes and bit depths due to available memory. Each color palette entry can be any of 4,096 possible colors, with 16 possible values of each of the red, green, and blue components.

    It’s worth noting that the MEGA65 video hardware is capable of 24-bit color. The BASIC 65 graphics system only uses a subset of the MEGA65’s graphics capability.

    As tempting as it is to tour all 31 commands of the graphics system in this Digest, for now I will leave it to you to discover them in your User’s Guide. Look for SCREEN, BOX, CHAR, CIRCLE, DOT, ELLIPSE, LINE, PAINT, PALETTE, PEN, POLYGON, and SCNCLR, for starters.

    Saving the graphics screen to disk

    BASIC 65 includes a command for saving the currently active bitmap graphics screen to disk. The SAVEIFF command takes a filename, and optional drive and unit numbers. It only works with a graphics screen active, so it’s best to make it part of the program.

    35 SAVEIFF "LINE-EXAMPLE"

    The image is saved to disk in the IFF-ILBM file format, a bitmap graphics file format common to Amiga computers. The file appears on the disk as a PRG file, but it’s actually just the IFF-ILBM data, without the two-byte address header of an actual PRG file.

    IFF-ILBM files use a simple form of data compression to reduce file sizes. The image produced by the program above of a single line on a blank screen at 320x200x2 occupies six blocks on disk to store 1,502 bytes. More complex images, or higher resolutions or color bit depths, will require more space.

    Loading the graphics screen from disk

    A file saved with SAVEIFF can be loaded back to the active graphics screen with another command: LOADIFF. As before, the graphics screen must be active.

    10 SCREEN 320,200,220 LOADIFF "LINE-EXAMPLE"30 GETKEY A$40 SCREEN CLOSE

    Due to how multi-color bitmap graphics are stored, the color bit depth of the active screen must match the file. Loading an image that was saved from a smaller resolution than the active screen (for example, loading a 320x200 image onto a 640x400 screen) will simply load the image into the upper-left corner of the screen, leaving the rest of the screen intact.

    SAVEIFF includes the current palette settings with the image data in the IFF-ILBM file. You do not need to restore the palette separately in your program. Notice that the current palette will be overwritten by LOADIFF.

    Exploring the IFF-ILBM file format

    The IFF-ILBM file format is a standard format developed by Electronic Arts in cooperation with Commodore in 1985. IFF, or “Interchange File Format,” is what is known as a container (or “envelope”) format, capable of representing multiple chunks of data of many kinds. Amiga fans mostly know IFF files as still images of the inner format ILBM, or “Interleaved Bitmap.” The IFF-ANIM format was a variant for storing multiple ILBM images as an animation in a single IFF envelope, also popular on the Amiga. As a kid, I only knew that IFF files contained either stills or animations, and you could make them with Deluxe Paint.

    Here is the beginning of the IFF-ILBM file created by the BASIC program above, as hexadecimal values:

    00000000 46 4f 52 4d 00 00 05 de 49 4c 42 4d 42 4d 48 44 |FORM....ILBMBMHD|00000010 00 00 00 14 01 40 00 c8 00 00 00 00 02 00 01 00 |.....@..........|00000020 00 00 00 00 01 40 00 c8 43 4d 41 50 00 00 00 0c |[email protected]....|00000030 00 00 00 ff ff ff ff 00 00 00 ff ff 42 4f 44 59 |............BODY|00000040 00 00 05 9a d9 00 d9 00 d9 00 d9 00 d9 00 d9 00 |................|

    An IFF file contains one or more chunks. Each chunk has a four-byte type ID and a four-byte size, followed by that many bytes of data. The SAVEIFF command creates a single outer chunk of type FORM, so it begins with those uppercase letters encoded as ASCII (46 4f 52 4d). The size is a signed 32-bit integer in Big Endian format (largest digits first), so 00 00 05 de represents a size of hexadecimal $05de, or 1,502 bytes. It’s not obvious from looking at it, but this is actually a bug in SAVEIFF: the actual data size is 1,494 bytes, but it is erroneously including the eight bytes of the FORM header in this size. Because of this bug, some tools will complain about an “unexpected end of input file” when reading this.

    According to the IFF specification, a FORM chunk is a record with an inner type and one or more inner chunks. In this case, the inner type is ILBM, so those are the next four bytes (49 4c 42 4d). The inner chunks have types BMHD, CMAP, and BODY, which are part of the ILBM specification for still images. You can see these identifiers in the hex dump, along with their four-byte sizes and data.

    Reading along with the ILBM specification for the $00000014 (20) bytes of the BMHD chunk, we can see the following properties of the image:

    * 01 40 00 c8: The image is $0140 = 320 pixels wide, and $00c8 = 200 pixels tall.

    * 00 00 00 00: The image starts at coordinate (0,0) on the screen.

    * 02: It has a color bit depth of 2.

    * 00: It does not use the mask feature of the ILBM format.

    * 01: The data uses Run-Length Encoding for compression (type 1).

    * 00: This is unused.

    * 00 00: This is related to the mask feature, not used here.

    * 00 00: This file describes its aspect ratio as 0:0 ($00 $00). This is not actually a valid aspect ratio. Some tools will complain, and just assume a ratio of 1:1.

    * 01 40 00 c8: The intended screen size for the image is 320x200, the same size as the image.

    The CMAP inner chunk describes the color palette. With a bit depth of 2, there are four possible colors in the image, each described as one byte for each of the red, green, and blue components, $0000000c (12) bytes in total.

    * Color 0: red = $00, green = $00, blue = $00, aka black

    * Color 1: red = $ff, green = $ff, blue = $ff, aka white

    * Color 2: red = $ff, green = $00, blue = $00, aka bright red

    * Color 3: red = $00, green = $ff, blue = $ff, aka cyan

    The IFF-ILBM format supports RGB component values from 0 to 255 (8 bits). The MEGA65 only supports component values from 0 to 15 (4 bits). LOADIFF uses the most significant four bits of each RGB component value when setting the palette, effectively rounding each number down to the nearest 16.

    The spec describes the RLE algorithm that is used for the BODY chunk. For example, $d9 $00 represents forty zeroes, and you can see this repeated in the excerpt above. The decoding algorithm will build out 320x200 bits for each of the four bitplanes. There’s a bit in each bitplane for each pixel of the image. Take the pixel’s bit from each of the bitplanes, starting with the lowest bit in the first bitplane, to get the pixel’s color number.

    ILBM is useful for Amiga and MEGA65 BASIC bitmap graphics because these systems represent the screen as bitplanes in memory, so it’s easy to save the image just by compressing memory, and load it again just by decompressing it. The MEGA65 has other graphics modes that don’t use bitplanes.

    Do you believe in ImageMagick?

    Most modern graphics software does not support the vintage IFF-ILBM image format. To use an image saved with SAVEIFF, it must be converted to a modern format, such as PNG.

    ImageMagick is the ultimate software suite for converting and manipulating image data in a wide variety of formats. It’s free, packed with features, and runs on most operating systems. You typically use ImageMagick from the command line, which makes it great for automation scripts. See the ImageMagick Downloads page for installation instructions for your operating system. On a Mac using Homebrew, install this with: brew install imagemagick

    In most cases, you can convert images between formats using the magick convert command:

    magick convert line-example.iff line-example.png

    (If you have an older version of ImageMagick installed, this command is just convert ..., without the magick.)

    There’s a slight problem when trying this with files made with the MEGA65’s SAVEIFF command. Those SAVEIFF bugs about the FORM chunk length and 0:0 aspect ratio cause the inner workings of ImageMagick to believe that the conversion failed. When I run the magick convert command on a SAVEIFF file, I get these messages, and no PNG file:

    ilbmtoppm: warning - illegal aspect ratio 0:0, using 1:1ilbmtoppm: input is a 2-plane ILBMilbmtoppm: Unexpected end of input fileconvert: delegate failed `'ilbmtoppm' '%i' > '%o'' @ error/delegate.c/InvokeDelegate/1924.convert: no decode delegate for this image format `ILBM' @ error/constitute.c/ReadImage/781.convert: no images defined `line-example-test.png' @ error/convert.c/ConvertImageCommand/3342.

    As shown in these messages, ImageMagick delegates IFF-ILBM conversion to a tool called ilbmtoppm, part of another software suite called NetPBM that’s included with ImageMagick. When I run the ilbmtoppm tool directly, it complains about the issues with the file, but successfully converts the IFF-ILBM file to the PPM format:

    ilbmtoppm line-example.iff >line-example.ppm

    The PPM format is supported by some modern software, and can be further converted to other formats by ImageMagick.

    magick convert line-example.ppm line-example.png

    The PPM file can also be converted back to IFF-ILBM format with the SAVEIFF errors corrected:

    magick convert line-example.ppm line-example-fixed.iff

    Converting images to be displayed on a MEGA65

    You can reverse the conversion process to prepare any image, including high color photographs, as an IFF-ILBM file, so it can be displayed on your MEGA65 with the LOADIFF command in a BASIC program.

    For this to work, it needs to not only be in IFF-ILBM format, but also be the right size and color depth for a BASIC 65 screen. You can try adjusting your image to 320x200 and 256 colors (8-bit color) using image editing software, or you can let ImageMagick do it for you.

    The latest version of ImageMagick as of this writing (7.1.1) does not appear to recognize the .iff filename extension as IFF-ILBM. Instead, you can conver to IFF-ILBM in two steps, using NetPBM again:

    magick convert photo.jpg -resize 320x200\! +dither -colors 256 -depth 8 photo.ppmppmtoilbm -maxplanes 8 photo.ppm >photo.iff

    The magick convert command converts photo.jpg to photo.ppm with the following options:

    -resize 320x200\! : Resize the image to 320 pixels wide and 200 pixels high. The \! tells ImageMagick to stretch the original image to fit this aspect ratio, which may or may not be what you want. ImageMagick has other options for resizing that can crop or extend the image instead. See any ImageMagick tutorial for examples.

    +dither : Disable dithering. Dithering is a technique for representing color and value gradations in digital images, using noise patterns and just a few colors. In this case, we’re converting a JPEG, which may introduce compression artifacts. Disabling dithering prevents these artifacts from being preserved as dithered patterns in the final image. If you’re converting from another format, you may be able to leave dithering enabled.

    -colors 256 -depth 8 : Set the color depth to 8, with the maximum of 256 colors.

    The ppmtoilbm command needs the -maxplanes 8 argument when the image uses a bit depth larger than 5. For some reason, the command defaults to generating a 24-bit image in these cases unless this argument is specified.

    I had some issues with ImageMagick and NetPBM that were resolved by updating to the latest versions. If you already have these tools installed from a while ago, consider updating. With Homebrew: brew update && brew upgrade

    Four-Byte Burger

    In 1985, Jack Haeger created an illustration of a hamburger falling through the air, with a 3-1/2" floppy disk for the hamburger patty. Jack painted the image using an early version of the Graphicraft art software for the Commodore Amiga, one of the first works of art created on the machine. At the time, Graphicraft lacked any way to save an image to disk or export it to print, so Jack photographed the screen with a 35mm film camera. Presumably, Jack eventually turned off the machine, and the digital record of the work was lost forever. The photograph appeared in the Graphicraft manual and the first issue of Amiga World magazine.

    In 2023, YouTuber Stuart Brown aka Ahoy recreated “Four-Byte Burger” as digital art. Ahoy described his research and his process in a 30-minute video, including the realization that Jack must have drawn the image sideways then rotated the photograph to give it more height, as shown by the CRT scan lines running up and down the photo. Ahoy concluded that Jack used just fewer than 32 colors, and the original image was 320x200 in size.

    Ahoy published a PNG file of his recreation, and by popular demand also produced an IFF-ILBM file of the same image for potential display on an Amiga. Naturally, I wanted to display it on my MEGA65, so I loaded it onto a D81 disk image and wrote an appropriate LOADIFF program, with a screen 320x200x5.

    I was a bit surprised that it rendered as mustard and ketchup colored garbage instead of the actual image. So I peeked into the hex dump as we did above. Everything looked as I expected it to, until I got to the compression type field of the BMHD chunk, which was $00 instead of $01. According to the ILBM spec, this indicates that the BODY data uses no compression at all, and not Run-Length Encoding. So I looked at the ROM code for LOADIFF, and sure enough, LOADIFF always assumes the BODY region uses RLE, and ignores the compression type field. (That should be another easy fix in a future version of the ROM.)

    There’s an easy workaround: use ilbmtoppm to convert the IFF-ILBM file to PPM, then use ppmtoilbm to convert it right back.

    ilbmtoppm four-byte-burger.iff >four-byte-burger.ppmppmtoilbm four-byte-burger.ppm >four-byte-burger-fixed.iff

    With “Four-Byte Burger,” the resulting file was naturally smaller, and had the compression field set to $01. It loaded fine on the MEGA65. If you have an IFF image file of a compatible size and color depth and it still isn’t loading correctly with LOADIFF, this is an easy workaround to try.

    One more tip: If you find an IFF-ILBM file and want to know its dimensions and color depth, use the magick identify command:

    magick identify four-byte-burger.iff

    IFF MegaShow65

    Want to display a set of IFF-ILBM images as a slideshow? Check out IFF MegaShow65 by Nobato. This clever program can browse and display multiple IFF image files on a disk. It uses BASIC 65’s graphics system and LOADIFF command behind the scenes, reading the BMHD section of the file to determine the resolution and color depth.

    The BASIC graphics system originated at Commodore, and retains a vintage feel. Even though it doesn’t use the MEGA65’s capabilities to their fullest, it’s a ton of fun to play with and use from programs, much easier than using bitmap graphics on a Commodore 64.

    Dirty old Onion Cake has kidnapped you. You know that it is your own fault since you have not written enough MEGA65 software. Better get started!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • PETSCII is a set of 256 values that can be printed to the screen of a Commodore computer. Most of these codes refer to characters, such as letters, numbers, punctuation, and Commodore’s unique set of graphics glyphs that can be typed from the keyboard. Other codes are control codes that manipulate the state of the screen and printing system, such as to change the color of subsequently printed text. The PETSCII character set is part of what gives Commodore computers their distinctive style. Drawing pictures by typing PETSCII characters and codes is one of the first things everyone does with a Commodore, and there is a long tradition of crafting murals of PETSCII art for demos, games, and computer bulletin boards.

    If you’re reading this, you’re probably pretty familiar with the capabilities of PETSCII on a Commodore 64. In this Digest, we’ll review the PETSCII character set, and see how the MEGA65 can learn a trick or two from Commodores that predate the 64. We’ll also take a look at PETSCII control codes that are newer than the C64, and see how we can make special use of PETSCII strings on the MEGA65.

    Featured Files

    Here’s more stuff you can download and try on your MEGA65 today!

    M3wP Solitaire by M3wP. Every computer needs some card game fun, and this Solitaire game has it in spades! Connect a mouse to port 1 and play the classic Klondike Solitaire with rich multi-color playing card graphics. You won’t be able to resist just one more hand.

    Don’t have a vintage Commodore 1351 mouse or Amiga mouse? Get the mouSTer adapter and connect a modern USB mouse. Make sure the mouse mode is set correctly in the MEGA65 Configuration menu (hold Alt while turning on the computer, then select 1) to match the mouSTer configuration. If you’re one of the lucky ones to receive a modern Amiga Tank Mouse from their Kickstarter campaign, that also works with the MEGA65.

    Lemonade for two by ubik. An innovative two-player version of the microcomputer classic business strategy game. Use your limited funds to buy supplies based on the weather forecast, sell lemonade in your neighborhood, and leverage your profits into expanding your business. Out-match your opponent and win it all!

    Procedurally Drawn Galaxy by grim_fandango. This high resolution graphics demo renders a gorgeous spiral galaxy. Once you’ve admired the image, check out the BASIC program listing to see how it’s done.

    The lost glyphs of the PET

    The PETSCII text encoding standard was originally invented for the Commodore PET computer in 1977. It uses 8-bit code points for 256 possible values, of which 192 represent typeable characters. Some characters are assigned to multiple code points; the actual number of distinct typeable characters is 128. The remaining 64 code points are used for control codes, or otherwise have no effect when printed to the screen.

    While PETSCII was based on the ASCII code standard in use by most computers by that time, the Commodore PET had its own ideas about how to make the best use of the code space. An unexpanded PET did not have a bitmap graphics mode, so PETSCII extended the character set with graphics symbols that could be used to draw boxes, diagrams, and game images. PETSCII actually describes two character sets: one with mixed case letters and some graphics symbols (the “text” character set), and another with only uppercase letters and more graphics symbols (the “graphics” character set). On Commodore machines, the graphics character set is the default. This is why you sometimes see ASCII messages mis-printed on Commodore machines with lowercase letters as uppercase and uppercase letters as graphics symbols. The user can toggle between character sets as needed by pressing the Commodore key and the Shift key together. (This is Mega + Shift on the MEGA65.)

    The PETSCII codes for the 128 typeable characters map to screen codes that describe what actually appears on a location on the screen. There’s a second set of screen codes that represent those characters in reverse video mode, for a total of 256 possible screen codes in a character set. With two character sets, the complete definition of a Commodore typeface has 512 possible glyphs, of which only the first 256 or second 256 can be on the screen at one time.

    Fun fact: The PET adds a one-pixel vertical space between each line when the display switches to “text” mode, to give it more of an ASCII terminal feel. You can see this in the image above, which I produced in an emulator with a program that prints the PETSCII control code to switch to this mode. (It’s also possible to use the text character set on a PET without the vertical gaps.)

    The C64 typeface

    The original Commodore PET typeface was designed with the PET’s built-in monochrome display in mind. These glyphs were used in 40-column and 80-column PET models. The same glyphs were also used in the VIC-20. To reduce costs, the VIC-20 did not have a built-in display and was designed to be connected to the color television set already in your living room. To make the text legible on blurry TVs, the VIC-20 only supported 22 columns of text and stretched the PET glyphs extra wide.

    Commodore sought to return to a 40-column text display for the Commodore 64, but there was a problem: the PET glyphs were too thin and spindly to be readable on a TV at narrow character widths. So Commodore redesigned the character set with thicker vertical lines. Nearly every occurrence of a single pixel with space on either side was doubled in some form.

    The result is the Commodore typeface we know and love, used unchanged all the way up to the MEGA65. It looks pretty great in 80 columns on a modern display.

    The missing glyphs

    The redesign met its goal, but at a cost. Several PET glyphs simply did not survive being made thicker.

    For example, the glyph set includes vertical lines of every width on both the left and right side of the tile. Take a look at your MEGA65 keyboard and you can see a few of these are typeable by holding down Mega and pressing keys like L, N, and M. On the PET, CBM+G and CBM+M were vertical lines one pixel wide. Starting with the C64, they are now two pixels wide, redundant with CBM+H and CBM+N, respectively.

    Some PET glyphs have been deleted entirely. A fine-grained 1-pixel checkerboard pattern was replaced with a duplicate of the 2-pixel checkerboard pattern. Dotted and line pattern glyphs just became extra empty spaces.

    Early MEGA65 contributor Markus Neeb (X2themax on the Discord, aka MPBBS) noticed the missing glyphs. At the MEGA eV open house of August 2022, he proposed a radical idea: restore the missing PET glyphs for the MEGA65. All of the restorations only replace glyphs that are redundant with others elsewhere in the typeface, and because they are both redundant and obscure, they likely haven’t even been used by MEGA65 software. The restored glyphs are authentic to Commodore history, and are demonstrably useful on modern displays in both 40-column and 80-column modes.

    It’s intriguing to imagine how re-introducing these glyphs enhances the character of the platform. I know I would have used the fine checker, dotted, and lined pattern tiles all the time if I had them—and a sharp enough display to support them—back in the day.

    The MEGA65 Steering Committee decided against modifying the default ROM with these changes, primarily because it’s actually quite easy for any program that wants to use these glyphs to install them. It’s even easier on the MEGA65 than on previous Commodore computers. BASIC programs can just use the CHARDEF command, and machine code programs merely have to write the new glyphs to a memory location.

    The following are CHARDEF statements that restore the missing PET glyphs. Feel free to use them in your programs, or in your AUTOBOOT.C65 file.

    10 chardef $42,$10,$10,$10,$10,$10,$10,$10,$1011 chardef $43,$00,$00,$00,$ff,$00,$00,$00,$0012 chardef $60,$aa,$00,$aa,$00,$aa,$00,$aa,$0013 chardef $65,$80,$80,$80,$80,$80,$80,$80,$8014 chardef $67,$01,$01,$01,$01,$01,$01,$01,$0115 chardef $c2,$ef,$ef,$ef,$ef,$ef,$ef,$ef,$ef16 chardef $c3,$ff,$ff,$ff,$00,$ff,$ff,$ff,$ff17 chardef $e0,$ff,$00,$ff,$00,$ff,$00,$ff,$0018 chardef $e5,$7f,$7f,$7f,$7f,$7f,$7f,$7f,$7f19 chardef $e7,$fe,$fe,$fe,$fe,$fe,$fe,$fe,$fe20 chardef $15e,$aa,$55,$aa,$55,$aa,$55,$aa,$5521 chardef $160,$aa,$00,$aa,$00,$aa,$00,$aa,$0022 chardef $165,$80,$80,$80,$80,$80,$80,$80,$8023 chardef $167,$01,$01,$01,$01,$01,$01,$01,$0124 chardef $1de,$55,$aa,$55,$aa,$55,$aa,$55,$aa25 chardef $1e0,$ff,$00,$ff,$00,$ff,$00,$ff,$0026 chardef $1e5,$7f,$7f,$7f,$7f,$7f,$7f,$7f,$7f27 chardef $1e7,$fe,$fe,$fe,$fe,$fe,$fe,$fe,$fe

    PETSCII control codes

    The ASCII standard includes codes that do something other than print a character when sent to a terminal or teletype. These codes cause the terminal device to perform some other action, such as to move the cursor (or print head) to the beginning of the next line, or signal the operator by ringing a bell.

    PETSCII also includes non-printing code points that, when printed, perform an effect, such as:

    * Change the color or style of subsequently printed characters

    * Move the cursor position (potentially scrolling the terminal-like text display)

    * Switch the display between the uppercase and lowercase character sets

    * Enable or disable the ability for the user to switch between the uppercase and lowercase character sets

    * Clear the screen

    * Ring the terminal bell

    Control codes can be typed directly into the screen using a key sequence. This is a great way to experiment with control codes and see their effects immediately. For example, hold Ctrl and press 3 to change the printing color to red. Ctrl + 2 changes it back to white. Printing is very similar to typing in this way: it causes the effect of typing each code to occur, in the order the codes appear in the string.

    Your User’s Guide has a good reference of PETSCII character and control codes, and their keyboard equivalents, in Appendix B.

    Including control codes in strings

    The CHR$() function takes a PETSCII code as a number and evaluates to a one-character string for that code. You can concatenate this string with other strings.

    PRINT "IT'S "+CHR$(28)+"VERY"+CHR$(5)+" COOL"

    The CHR$() function works for all 256 PETSCII codes, but it’s not especially convenient: you have to use a table to look up the control code numbers, and type quite a few characters to spell it all out.

    Thankfully, the Commodore screen editor has an alternate way to type control codes into strings just by typing the key sequences that cause their effect. The screen editor knows that you intend to include the code in the string, and not have it take effect immediately, when it is in quote mode. The editor enables quote mode when you type the first double-quote (") character of a string, and disables it when you type the closing double-quote character.

    You may have seen vintage magazine program listings represent these typeable codes using labels, like so:

    PRINT "IT'S {red}VERY{white} COOL"

    Try typing this command, entering Ctrl+3 for {red} and Ctrl+2 for {white}. They appear as reversed characters inside the string.

    Quote mode takes some getting used to. It’s easy to forget that cursor movement keys get quoted, so if you try to cursor left while typing a string, it quotes the cursor-left PETSCII codes instead. A few codes intentionally do not get quoted, such as pressing Return. If you need such a code in a string, the only way is to use the CHR$() function (CHR$(13) for Return).

    There is one other way to access quote mode. When you press Shift+INST/DEL, the editor inserts a space at the cursor location and does not move the cursor. It also enters quote mode only for the inserted spaces, so you can type a control code if you need to. This quote mode effect happens even if the cursor is not located inside double-quotes! That’s not particularly useful, but it’s a tradeoff for the fact that the screen editor doesn’t try to understand what you are typing until you press Return.

    If you find that you’re in quote mode and you don’t want to be, press Esc then O (the letter O).

    It’s useful to know that the screen editor will interpret whatever is on the screen when you press Return, including reversed characters inside double-quotes, no matter how those characters were typed. Technically, you can type a quoted {red} code while not in quote mode by turning on reverse mode and typing the £ (pound) symbol, which is what it would look like if you typed Ctrl+3 while in quote mode. I’ve never done this in regular practice—I typically use the insert method to type quoted codes when modifying an existing line—but it’s fun to know that it works.

    Try this:

    * Type: PRINT " HELLO{wht}", without pressing Return.

    * Cursor back to the space before HELLO.

    * Enter Ctrl+9 to enter reverse mode, then type ÂŁ.

    * Press Return.

    Print modes and colors

    The Commodore 65 supports text modes for underlining, flashing text, and reverse text. These modes can be combined.

    To enable underlining, press Ctrl+B. To enable flashing text, press Ctrl+O. One way to enable reverse text is Ctrl+R, though as we just saw, this is also available as Ctrl+9 aka “Rvs on.” There are PETSCII codes to disable each of these individually, and if you’re just typing them onto the screen you can press Esc then O to disable all three modes. Reverse can also be disabled with Ctrl+0 (zero) aka “Rvs off.”

    * Underline on: Ctrl+B, CHR$(2)

    * Underline off: CHR$(130)

    * Flashing on: Ctrl+O, CHR$(15)

    * Flashing off: CHR$(143)

    * Reverse on: Ctrl+R or Ctrl+9 aka “Rvs on”, CHR$(18)

    * Reverse off: Ctrl+0 aka “Rvs off”, CHR$(146)

    The printing system keeps track of the text color as its own mode, using that color for printing characters. The blinking cursor is drawn in the current text color. C64 fans know the color changing keys quite well: Ctrl or Mega plus a number key 1 through 8 accesses sixteen colors, as labeled on the number keys themselves. The corresponding PETSCII codes are scattered a bit (white is 5, red is 28, green is 30, etc.), so you’ll just want to look those numbers up in the User’s Guide if you need them.

    On the MEGA65, you can access a system palette of 32 colors for text printing. All 32 colors can be used on the same screen simultaneously. To access them using PETSCII control codes, there is a print mode for that: Ctrl+D causes the 16 color codes to refer to colors 0-15, and Ctrl+A causes them to refer to colors 16-31.

    * Access colors 0-15: Ctrl+D, CHR$(4)

    * Access colors 16-31: Ctrl+A, CHR$(1)

    Don’t forget that you can change an entry in the 32-color system palette to any of 4,096 colors using the PALETTE COLOR command. You can also change which color is used for printing with the FOREGROUND command (or the COLOR command). See the User’s Guide for more information.

    Moving the cursor

    It was very common for Commodore 64 BASIC programs to position text on the screen using PETSCII control codes that move the cursor. To print the message "HELLO WORLD" in the center of the 40x25 screen, a program might print the Home code to move the cursor to the top left corner, followed by 12 cursor-down codes and 14 cursor-left codes, then the message.

    * Home cursor: Home, CHR$(19)

    * Cursor down: Cursor down, CHR$(17)

    * Cursor right: Cursor right, CHR$(29)

    * Cursor up: Cursor up, CHR$(145)

    * Cursor left: Cursor left, CHR$(157)

    BASIC 65 has a dedicated command for positioning the cursor: CURSOR col,row This may be more useful for positioning text on the screen, depending on what you are trying to print.

    The terminal display supports tab column positions, similar to ASCII teletypes (and old typewriters). I won’t describe the whole system here. You can experiment with the Tab key (9) and “tab set/clear” (24) code to see what they do.

    Screen effects

    Pretty much every Commodore 64 BASIC program I ever wrote started by clearing the screen. This felt so powerful, the first step in my program taking control of the machine. The reversed heart character of the quoted clear-screen PETSCII code resonates as nostalgically for me as the blue-bordered home screen.

    Press Shift+Clr/Home to clear the screen. Press it in quote mode to insert the PETSCII control code into a string, such that it clears the screen when that part of the string is printed.

    * Clear screen: Shift+Clr/Home, CHR$(147)

    As we mentioned last month, the text screen can display either the uppercase character set or the lowercase character set. Each set can have 256 unique glyphs, but only one set can appear on the screen at one time. The default character set keeps uppercase letters and graphics characters in the first set, and lowercase and uppercase letters in the second set.

    You can toggle between the two character sets interactively by pressing the Mega and Shift keys together. (Try it!) This toggle effect is not a PETSCII code, and in fact supersedes many program functions so you can do this while a program is running. If your program intentionally uses one set or the other, you can print PETSCII codes to select the set, as well as to disable the Mega+Shift behavior.

    * Select uppercase: Ctrl+N, CHR$(15)

    * Select lowercase: CHR$(142)

    * Enable Mega+Shift: Ctrl+K, CHR$(11)

    * Disable Mega+Shift: Ctrl+L, CHR$(12)

    Old terminals had a special code that caused a bell to ring, such as to alert an operator at the end of a long job, possibly on a printer in another room. Newer screen terminals support the bell code, mostly using it to indicate an error. The Commodore 65 also has a bell! Press Ctrl+G to hear it.

    * Ring the bell: Ctrl+G, CHR$(7)

    Patterns in control codes

    PETSCII codes 1 through 26 are typeable as Ctrl plus a letter of the alphabet A through Z. Ctrl+S is overridden as an equivalent to No Scroll; code 19 can be entered with the Home key. Ctrl+M is Return, and Ctrl+T is Delete, so these can’t be quoted; use CHR$() for these. As quote mode characters, these codes appear as reversed versions of their corresponding letters. (This pattern extends to other codes and PETSCII characters, though they’re less easy to remember.)

    In most cases where a code is usefully paired with another, one code is in the range 0-32 and the other is the same code plus 128 ($80), similar to shifted characters. For example, code 2 enables underlining, and code 130 ($82) disables it. Not every code has a useful pair, and for whatever reason the shift enable and disable codes are simply 11 and 12.

    The Commodore 65 assigns several PETSCII codes to keys that have no behavior when printed, such as the function keys. These codes are only useful when reading a keypress with the BASIC GETKEY command. In some of these cases, the corresponding Ctrl keys perform behaviors in the screen editor that do not occur when the code is printed. For example, there is no way to print a PETSCII code with the same effect as typing Ctrl+P.

    Escape codes

    The screen editor has some advanced features that go beyond the available PETSCII control codes. This extended set is accessible by pressing Esc followed by another key. See the appendix in your User’s Guide for a complete list. (Be sure to download the latest PDFs, which include minor updates to this appendix specifically.)

    Only a few escape codes are useful from PRINT. You activate them by printing the PETSCII code for Esc, which is CHR$(27), followed by the appropriate character. As we saw last month, Esc followed by the character 5 switches to 80x50 mode in the latest version of the ROM. You can activate this mode from a BASIC program by printing these codes:

    PRINT CHR$(27)+"5"

    Esc then M disables scrolling of the text display. This can be useful within a program to PRINT on the bottommost line of the screen. Esc then L re-enables scrolling.

    PRINT CHR$(27)+"M{home}{24 down}YOUR SCORE: ",SC

    Programmable function keys

    Your MEGA65 includes a row of function keys, numbered F1 through F14. The seven keys act as the odd numbers; hold Shift and press one to access the even numbers. Technically, there are sixteen function keys, with the last two being the Help key and the Run key, respectively. (Press Shift + Run/Stop to act as Run.)

    By now, you or your cat may have pressed these keys in the BASIC editor and noticed that they do various things. Some are super useful, and others are not obviously helpful. I know I’ve tried pressing the Help key on a Commodore 128, only to be disappointed that it just shouts HELP back at me and doesn’t appear to do anything else.

    In the BASIC editor, the purpose of the function keys is to type strings of PETSCII codes. These strings are programmable! When you press a function key, it types its string as if you typed it out manually. For example, the default definition of the Help key is a string of five codes: HELP followed by the Return key. On a blank line, this enters the BASIC command HELP, which displays information about the most recent error encountered by your BASIC program. (If your program didn’t recently encounter an error, the HELP command prints nothing.)

    To see a list of all of the function key definitions, type the KEY command:

    KEY

    Knowing what we know about PETSCII codes, we can see how the default definitions of the function keys work. Several definitions use CHR$(27) to refer to the Esc key, entering escape codes. Others use CHR$(13) to type the Return key to enter commands. Some definitions use quoted control codes to type the equivalent key sequences.

    Notice that key sequences that control the BASIC editor don’t work with the PRINT command, but they do work in function key definitions. For example, function key F9 is defined as a synonym for Ctrl + P, which scrolls a line of a BASIC program listing onto the screen from the bottom. Paired with the default definition of F11, Ctrl + V, these keys are a handy way to browse a BASIC program listing, and more convenient than using the control sequences directly.

    To redefine a function key, use the KEY command with arguments: the function key number, a comma, and the string definition. For your convenience, this is how the KEY command displays the current definitions, so you can cursor up to one of those lines, make a change, and press Return to register the new definition.

    It can be really handy to define function keys for project-specific tasks. For example, say you’re troubleshooting a subroutine on line 3500 that has different behaviors depending on the value of the X variable, and you want to try it with different values. You can define the function keys F1 and F3 as follows:

    KEY 1,"X="KEY 3,":GOSUB 3500"+CHR$(13)

    Now you can test the subroutine quickly: press F1, enter a value for X, then press F3.

    Once you have function key settings that you like, you can save them to a file on disk, then load them again later. These commands are KEY SAVE "filename" and KEY LOAD "filename", respectively. Save your project-specific definitions on disk with your other project files. You can even have multiple definition files and load them as needed.

    KEY SAVE "MYPROJ-KEYS"

    Control codes in petcat

    In the December 2022 issue of the Digest, I mentioned a handy tool for developing MEGA65 BASIC programs on your PC called petcat. This tool is distributed with the VICE suite of Commodore emulators. It converts between PETSCII characters and an ASCII text-based syntax, so your programs can include all of the possible characters even though your PC doesn’t have a Commodore keyboard.

    For the more unusual PETSCII characters and control codes, petcat has a label syntax using curly brackets, similar to what we used earlier for codes like {red}. You can type these labels directly into your text file, and petcat will generate the equivalent PETSCII code when it makes the PRG file.

    To my knowledge, there isn’t an existing prose document that describes all of the petcat syntax. So I wrote one. See my new petcat syntax reference in the MEGA65 Wiki. Feedback welcome!

    PETSCII is a defining feature of Commodore computers, providing a ton of display power that’s easy to use in BASIC programs. I hope it inspires you to do something great!



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • A Rorschach Test on Fire. Dan’s MEGA65 Digest for March 2023.

    This month, we have featured files, featured features, new hardware, and a classic programming exercise to play with. Let’s get started!

    Featured Files

    Get this month’s Featured Files from Filehost and keep them on your SD card for showing off to your friends!

    LUMA by Shallan50k. Shift the components around on a playfield to fire lasers at targets. Use a joystick in port 2: select a piece, hold the button, then push it in a direction. Try to solve each puzzle in as few moves as possible.

    Wave Hero by GeirS. A watersports-themed one-button runner with smooth gameplay, a gorgeous color palette, and authentic SID sounds. Use just the button of a joystick in port 2. This adaptation of a C64 game includes source code written in Millfork.

    Mandelbrot Explorer 65 by lydon, with assembly source. The fractal so famous there’s a song about it. See also Mega-Mandelbrot by Liquidream, in BASIC.

    An external floppy disk drive for the MEGA65

    In addition to the 3-1/2" floppy disk drive built into the MEGA65, the computer supports connecting a vintage Commodore 1581 external floppy drive to the IEC port. These drives are difficult to obtain, with working units listing for upwards of $400 USD on eBay. If you want a second drive for your MEGA65, there’s a new option!

    Foenix Retro Systems is taking pre-orders for a new Commodore-compatible 3-1/2" floppy drive, the FNX1591. Like the 1581, it supports double-density (DD) disks, for 720KB of storage per disk. The FNX’s firmware can be updated over USB, and it can store multiple firmware options that can be selected by a switch. Another switch can set the IEC unit number. The drive uses a modern power supply and power switch, and sports two IEC connectors for daisy-chaining devices.

    The FNX1591 is intended to be compatible with all computers that work with the 1581, including the MEGA65. You can preorder one today for $275 USD + $45 USD flat rate shipping. Delivery is estimated for April 2023.

    The drive’s resin-printed case is designed to match the Foenix F256K, an all-new 65C02-based wedge-style computer. The F256K is not currently open for orders, but the F256 Jr, a low-cost bare-board version, is for sale for only $199 USD. If your MEGA65 needs a friend, you can’t go wrong with an F256 Jr.

    An embroidered dust cover for the MEGA65

    Sew Ready, a maker of boutique dust covers for vintage Commodore equipment out of Norfolk, United Kingdom, now offers an embroidered dust cover for the MEGA65! Grey with stylish red piping and a rainbow “65” logo, this cover protects your MEGA65 (or your Commodore 65, if you have one) while leaving the ports exposed, so you can keep it connected and covered at the same time. £22.99 plus shipping. While you’re there, get matching covers for all your Commodore gear.

    Looking for other dust cover options? Some large-size keyboard covers like this one tend to fit the MEGA65, and the cheap ones are practical. I found a generic stretchy keyboard cover that just fits, though it won’t protect it from things set on top of it or cats walking across it. For something more durable, lydon found this acrylic keyboard cover that is sized correctly, and works well with these clear elastic buffers. Others have found acrylic display stands that, with the right dimensions, can do the trick and look pretty stylish.

    Want to mount your MEGA65 to the wall? 8-Bit Resurgence (COREi64 in the Discord) made a video on making 3D-printed presentation brackets.

    Recently added features of the ROM

    As I mentioned last month, the MEGA65 ROM is getting new updates. February saw a series of updates that promoted features that were contributed over the last year, using a new testing process to eliminate bugs and confirm backwards compatibility with existing MEGA65 software. See the ROM FAQ for a reminder on how to obtain and install the latest beta release.

    The following new features have been added to beta releases since the last release package, up to the most recent ROM version as of this writing, ROM 920383. Many thanks to Bit Shifter for these contributions, and for all of his work on the ROM over the years!

    80x50 text mode

    The MEGA65 operating environment starts up in a text mode with 80 columns and 25 rows. You can change the environment’s display mode to 40 columns and 25 rows by pressing the Esc key followed by the 4 key. To switch back to 80x25, press Esc then 8.

    Starting with ROM 920382, you can switch the operating environment to 80 columns and 50 rows, plenty of screen space for BASIC program code and directory listings. To switch to this mode, press Esc then 5.

    Be advised that some software might not run correctly if started with the computer in a state other than the default boot state. Technically, this is true for anything you can change about the state of the computer, and is not particular to the new 80x50 mode. Some programs would also be confused if you start them in 40x25 mode. When writing a program, it’s best to not assume any undocumented default state: either test the state, or set it to be as you need it.

    To set the text screen mode from a BASIC program, use the PRINT command to emit the PETSCII codes for Esc (27) and the appropriate number character. You’ll probably want to also emit the code to clear the screen (147).

    PRINT CHR$(27)+"5"+CHR$(147)

    MOUSE ON default sprite

    BASIC 65 has built-in support for the mouse. When you enable the mouse with MOUSE ON, BASIC 65 uses the first sprite of its sprite system (sprite 0) as a mouse cursor. In previous versions of the ROM, the BASIC program had to provide its own sprite image for the cursor. You can still provide a custom image, but now you don’t have to: the default image for sprite 0 is an arrow-shaped mouse cursor.

    If you have a compatible mouse (or a modern USB mouse and the amazing mouSTer adapter), try this command to see the BASIC mouse pointer in action:

    MOUSE ON

    In a BASIC program, you can read the position and button state of the mouse into variables using the RMOUSE command. See your User’s Guide for more information.

    In addition to the mouse sprite, the other seven sprites are now set a simple default pattern, so you can experiment with the BASIC sprite system without first loading image data.

    CHARDEF 512

    The CHARDEF command in BASIC 65 can replace the glyph of a screen code with a custom pattern. (We played with CHARDEF a bit in the September 2022 issue of the Digest.) In previous versions of the ROM, CHARDEF could only modify the first 256 screen codes in the uppercase character set. Now you can use CHARDEF with all 512 screen codes, numbered 0 through 511.

    Remember that your program can only display either the uppercase character set or the lowercase character set on the screen at one time. To switch to the lowercase set, PRINT PETSCII code 14:

    PRINT CHR$(14)

    Surprisingly, there is no PETSCII code to switch back to the uppercase character set. [Update: Thanks to Rhialto for the correction:] To switch back to the uppercase (“graphics”) set:

    PRINT CHR$(142)

    You can also use the VIC register at $D018 (53272) to switch between uppercase and lowercase. For the default character set on the Commodore 65, the lower four bits should be 4 for uppercase, or 6 for lowercase.

    POKE $D018,PEEK($D018) AND $F0 OR $04POKE $D018,PEEK($D018) AND $F0 OR $06

    If your program depends on the character set not changing, you may want to disable the ability for the user to toggle between the two sets by pressing Mega+Shift. Print PETSCII code 8 to disable it (and PETSCII code 9 to re-enable).

    PRINT CHR$(8)

    MONITOR PC handling and the BRK instruction

    In last month’s Digest we explored the MEGA65 Monitor as an essential tool for learning machine language, understanding how the computer works, and troubleshooting machine language programs. With the latest ROM, the Monitor just got even more useful.

    We saw how you can start the Monitor by typing the MONITOR command at the READY. prompt. The MEGA65 will also activate the Monitor when a machine language program executes the BRK instruction. This is super handy for investigating a problem with the state of the computer from inside your program: just add a BRK instruction and run your program, and it’ll stop at exactly that spot and open the Monitor so you can inspect registers and memory.

    With the latest ROM, the Monitor has been improved so it knows exactly where the BRK instruction left off. You can now continue your program from the Monitor using the G command without arguments, assuming you did not modify the program counter while you were in the Monitor.

    Run/Stop+Restore enters the Monitor

    Anyone who has written a machine language program knows how it feels when a bug in the program causes it to get stuck, ignoring all input, appearing to do nothing—or worse. For these cases, Commodore provided us an escape hatch: hold Run/Stop and press Restore. This triggers an interrupt that tells the CPU to stop what it’s doing and hand control to the kernel.

    Traditionally, the kernel would handle this interrupt by clearing the screen and displaying a READY. prompt. This isn’t particularly useful when troubleshooting a machine language program. The latest ROM does something a bit smarter: it opens the Monitor, with the program counter set to wherever you interrupted it, as if there had been a BRK instruction at that location. In many cases, you can even resume your ML program after interruption, using the G command!

    With the new ROM installed, try assembling the infinite border color program from last month’s Digest, then execute it to enter an infinite loop. Press Run/Stop+Restore to break into the Monitor. Then enter the G command to resume the fireworks.

    An 80x50 Mandelbrot Set

    Rendering the Mandelbrot set is a rite of passage coding exercise, similar to implementing Conway’s Game of Life. lydon’s Mandelbrot Explorer 65 and Liquidream’s Mega-Mandelbrot show off the MEGA65’s color bitmap graphics capabilities. To celebrate the launch of 80x50 BASIC text mode, let’s try a low-res version!

    The Mandelbrot set is the set of complex numbers c for which the function f(z+1) = f(z)^2 + c does not diverge to infinity when iterated from z = 0. In other words, take a complex number c, then starting from zero, repeatedly add the complex number and square the result. If the results run off to infinity, the number c is not in the set. If the results never run off—maybe they bounce around locally or converge toward zero—then c is in the set.

    The most famous image of the Mandelbrot set represents the points on the complex plane where c = x + iy, where i is the imaginary constant defined as i^2 = -1, centered on the origin (0, 0) and zoomed in fairly close. Points that are in the set appear in the image as black, forming bulbous round shapes.

    A simple computer program can draw the image as a bitmap by testing every pixel (x, y) as a coordinate on the complex plane, starting the function at the point and iterating until either it starts to look like the value is diverging, or a maximum number of iterations is reached. If the value is still near the starting point after the maximum iterations, the program concludes it is in the set. Traditionally, the program assigns diverging (non-member) points a color based on the number of iterations it took to detect divergence, giving the figure a glowing effect that shows how points near members of the set take longer to diverge.

    (See also Dr. Holly Krieger’s excellent explanation in The Mandelbrot Set episode of Numberphile.)

    Let’s write a BASIC program to draw this using 80x50 text mode. First, adjust the color palette to provide a gradient of colors for the non-set points. You can experiment with different values to adjust the colors to your taste.

    10 PALETTE COLOR 0,0,0,020 FOR N=1 TO 15:PALETTE COLOR N,N,0,4-(N-4):NEXT N

    A BASIC program can set the screen mode by printing the PETSCII code for the ESC key (27) then the character for 5, similar to if you typed it.

    100 PRINT CHR$(27)+"5"

    To draw the pattern, the program visits each character position once, using a nested FOR loop. For this program, we’ll set every character on the screen to a solid rectangle, then set the color based on our calculations. The BASIC 65 special array T@&() gives us access to the characters on the screen, and the special array C@&() gives us access to the colors. These arrays are indexed with a row and column number, and you can read or assign to these values, similar to other arrays.

    110 FOR K=0 TO 79120 FOR R=0 TO 49130 T@&(K,R)=160

    The program fills the screen with solid rectangles (screen code 160). The rest of the code will test the point for set membership and set its color accordingly.

    The first thing we need to do is determine the actual x/y coordinates on the complex plane for each position on the screen. The y-axis should be in the center, so the x coordinate is 0 when the column number K is 40. Similarly, the x-axis should also be centered, so the y coordinate is 0 when the row number R is 25. We also need to scale down the coordinate ranges to be much smaller, so we can see something interesting. These calculations for X and Y should produce interesting results:

    140 X=(K-40)*0.06150 Y=(R-25)*0.06

    These variables represent the complex number c = x + iy that corresponds with the coordinate on the screen. We need to keep track of the iteration value, a complex value stored in the variables ZX and ZY. We also need to keep track of the number of iterations, in variable N. Initialize these variables to zero.

    160 ZX=0:ZY=0:N=0

    BASIC 65 does not have built-in support for complex numbers or the imaginary constant i, but it turns out we don’t need it. We can calculate the new values of ZX and ZY using separate equations for the real and imaginary parts. Remembering that i squared is -1, the square of a complex number can be figured as follows:

    (x + iy)^2x^2 + ixy + ixy + (iy)^2x^2 + 2ixy + (-1)y^2(x^2 - y^2) + i(2xy)

    To complete the equation, add the components of the original complex value, X and Y. The complete BASIC code for updating the ZX and ZY variables is as follows:

    170 ZX=ZX*ZX-ZY*ZY+X180 ZY=2*ZX*ZY+Y

    Each time we iterate this function, we can determine whether the function is diverging by testing whether the updated point is far away from where it started. We’re using starting points that are very close to the origin, so to keep the math simple, we can take the distance of the new point from the origin. This distance, known as the magnitude of the complex number c = x + iy, can be found using the Pythagorean Theorem, the square root of the quantity x^2 + y^2.

    In BASIC 65, the square root function is spelled SQR(), so we get our magnitude like so:

    190 A=SQR(ZX*ZX+ZY*ZY)

    We’ve just completed an iteration, so we need to increment the iteration counter N:

    200 N=N+1

    Now we can test whether we’re done iterating. If the magnitude of the value hasn’t gotten large enough to conclude that the function is diverging, and we haven’t yet reached the maximum number of iterations, we continue iterating.

    210 IF A

  • I spent six years of my early childhood on my Commodore 64, between ages 6 and 12. I wrote many programs, all using the built-in BASIC language, learning everything I could from reading the Commodore 64 Programmer’s Reference Guide and typing in program listings from Compute!’s Gazette magazine. I learned a lot from writing BASIC programs, but the one lesson I took away over and over again was this: to make anything really cool, like Marble Madness or Skyfox, I’d need to know machine language.

    Machine language felt like dark magic. In Compute!’s Gazette, all the games with the cool graphics and high speed action were printed as columns of numbers, a pages-long incantation that if you typed it correctly would conjure a video game. The Programmer’s Reference had a chapter on machine language that I stared at endlessly trying to make sense of it, but it only made a passing reference to the fact that I needed additional software to write it. If I were older or had a friend with more experience, I would have known what utility cartridge to ask my parents for as a birthday gift, but it was too much for my kid self to figure out all by myself in a basement.

    In fairness, Compute!’s Gazette did publish the occasional machine language coding tool, like Fast Assembler in the January 1986 issue. The companion disk to the issue even included the source code for Fast Assembler itself, the first time I had ever seen a complete machine language program listing. I remember making a small change and running the assembler on its own code, which produced a new version of the assembler that printed my name instead of its own. But that’s as far as I got.

    In this issue of the Digest, we’re going to answer the questions I had when I was a kid. What is machine language? What is an assembler? And what in the name of Chuck E. Cheese is hexadecimal? We’ll also look at ways you can start learning machine language right now with your MEGA65.

    Featured Files

    It’s time once again for Featured Files, where we highlight stuff you can download from the Filehost and try with your MEGA65 today!

    Mega Wizards, by RBJeffrey. A game for one to four players, using the joysticks. Use your wizardly wiles to bounce the magic ball, take out your enemies, and defend your crystal. Three and four players require a four-player joystick interface.

    WORDUP by geehaf. A faithful variant of the popular daily word game Wordle, playable on your MEGA65. Guess the secret five-letter word in six or fewer tries, using hints produced by each guess.

    xmas65 by MirageBD. A holiday greeting for the MEGA65 community with an impressive graphical effect and a rockin’ MOD-style backing track.

    New Intro Disk!

    The intro disk is the first thing you see when you turn on the MEGA65 for the first time, a bundle of games, demos, and music ready to play and show off your new computer to your friends. Thanks to Gurce, there’s now a second intro collection for your enjoyment!

    Intro Disk #02 goes beyond the bounds of a single D81 disk image with dozens of titles and music files, all browsable from a colorful menu. Unpack the zip file and copy the files to your SD card, then boot the INTRO2.D81 disk image.

    There are a lot of files for this one. I had success keeping the files in a subfolder on the SD card. You may want to move the MODS/ subfolder to the root to make these music files easier to play with the new version of the Manche MOD player, included on the intro disk.

    What’s new with the ROM

    The MEGA65 ROM is the built-in program code that powers the kernel, the BASIC programming language, and the operating environment. It’s what Commodore would have burned into a physical ROM chip had they released the Commodore 65 as a product. In the case of the MEGA65, the ROM is actually a file on the SD card, loaded during boot by the firmware.

    Commodore canceled the C65 project before finishing the original C65 ROM. The MEGA65 team has made significant investments into finishing planned features, fixing bugs, and generally making improvements in the spirit of the original Commodore design. The latest MEGA65 ROM is much more useful thanks to these efforts. Release package version 0.9, which shipped with the first batch of MEGA65s in May of last year, bundled the ROM with the version ID of 920287. The most recent release package as of this writing is version 0.95, which shipped with the second batch last October, with ROM 920377.

    The work continues on improving all aspects of the MEGA65 platform, including the ROM. You are invited to help test new “beta” releases of the ROM, starting with version 920378, now available. If you own a MEGA65 and are signed in to Filehost with your account, you can download the latest beta ROM and install it on your SD card. If you do not own a MEGA65, you can put the ROM together for use with the Xemu MEGA65 emulator, using the original C65 ROM, the MEGA65 ROM patch file, and the M65Connect app (also available on Filehost). (The C65 ROM is available for free for personal use as part of C64 Forever Free Express Edition from Cloanto.)

    If you discover an issue with any version of the ROM, please report it using the Issues tab of the mega65-rom-public Github repo. Check out the new MEGA65 ROM FAQ article with answers to common questions and instructions on how to download and use the latest ROM. Also, be sure to join the #closed-roms channel on the Discord for updates.

    Addressing the computer

    One of the first things I learned to do with the Commodore 64 was this command:

    POKE 53280,4

    This command still works today on your MEGA65. (Try it!) If you haven’t memorized what these numbers mean, it’s difficult to tell what this command does just from looking at it. Newer Commodores added an equivalent BASIC command that better describes its function, also available on the MEGA65:

    BORDER 4

    The POKE command takes two numbers: an address and a value. It instructs the CPU to send the value to whatever device inside the computer is wired to that address. The effect this has depends entirely on what’s there. In the case of 53280, the address is connected to the VIC video chip, specifically the part that controls the color of the screen border. The different values represent different colors.

    In many cases, the device at an address remembers the last sent value, and the CPU can retrieve it with another command:

    PRINT PEEK(53280)

    The POKE command and PEEK() function are most often associated with computer memory, a device whose sole purpose is to remember the most recent value sent to an address for as long as the computer is powered on. Here’s an address on the MEGA65 connected to memory:

    POKE 6144,255PRINT PEEK(6144)

    Most addresses are connected to memory chips. Some are connected to other devices, like video and sound generators, disk drives, the keyboard, joysticks, and so on. Non-memory addresses are known as registers, or more specifically I/O registers for their purpose of reading input from and writing output to the devices that live there. Not all registers accept new values. For example, the CPU can read a register connected to a joystick port to see which way the joystick is being pushed, but there is no way to send a value to the joystick.

    There are 256 possible values you can send to or read from an address, numbered 0 to 255. The meaning of the value depends entirely on how it is used. It can be a color, a character of text, a set of pixels on the screen, the pitch or volume of a sound, a piece of a larger number, or anything else that can be represented by a value.

    Bits, bytes, and binary

    Internally, the computer represents a value as one or more digital electronic signals. This fundamental unit of digital data is known as a bit, with two possible values, typically represented by the numbers 0 and 1. Bits can be combined to represent more possible values: two bits can represent four values, 00, 01, 10, or 11; three bits can represent eight values. The value you send to or read from an address is eight bits, also known as a byte, with 256 possible values. The MEGA65 CPU mostly deals with byte-sized values, which is why it’s called an “8-bit computer.”

    It’s very common to describe bit patterns as numbers—specifically, integers counting up from 0—even when they don’t represent numbers in the data. The binary number system puts these bit patterns in order. The first six binary numbers are 0, 1, 10, 11, 100, and 101, equal to the decimal numbers 0 through 5.

    Just as decimal place values are powers of ten (1, 10, 100, 1000), each binary place value is a power of two (1, 2, 4, 8). You can convert a decimal number to its binary equivalent by setting the bits whose place values add to the number to 1. To convert from binary to decimal, add the place values where bits are set.

    Addresses are numbered starting from 0 and counting up, and it should be no surprise that the computer uses bits to represent addresses. A Commodore 64 uses 16 bits (two bytes) for addresses, for 65,536 possible addresses. The MEGA65 uses 28 bits for addresses.

    Because the MEGA65’s 45GS02 CPU is an evolution of the Commodore 64’s 6510 CPU, MEGA65 machine language programs mostly work with 16 address bits, and use other features of the 45GS02 CPU to complete the address. It’s kind of like telling a taxi driver where to go using just the house number and street name, and assuming the driver knows the city, state, and country. See the chapter on memory in the manual for more information about how this works.

    Hexadecimal to the rescue!

    We use decimal numbers in our daily lives, but it gets unwieldy when working with computer programs. Computers are designed around binary, so all of the useful value ranges are convenient in binary—and confusing in decimal. 255 feels like a weird stopping point for a byte, but in binary it’s just the largest eight-digit value: 11111111. As more bits get involved, the possibilities get even more difficult to track. Why is 65,536 an important number? How much is 1,048,576? What is at address 268,251,168?

    POKE 268251168,3

    Writing programs using binary numbers would quickly drive us mad. A 28-bit address would literally be twenty-eight 1’s and 0’s. We need a concise way to represent these numbers that doesn’t make them more confusing. That’s where hexadecimal comes in.

    Hexadecimal is a numbering system that uses sixteen possible values per digit, so a single hex digit completely represents all possible values of four bits. A byte value can be represented by two hex digits instead of eight binary digits.

    Earlier we saw that the border color address is 53280 in decimal. It looks like a random number, if you haven’t memorized it. In binary, a hint of a pattern emerges, but it’s still difficult to manage: 1101000000100000 To convert this to hexadecimal, split the bits into four-bit groups, then find the hex digit that represents each group. 53,280 in hexadecimal is D020.

    To avoid confusing a hex number with a decimal number, it is often written with a dollar sign in front: $D020. This convention is common to microcomputer programming. (Modern languages use different conventions for hex numbers, such as 0xd020 in Python.)

    Commodore 64 BASIC only knows decimal notation for numbers, so C64 programmers are well practiced at converting between bit values and decimal notation. MEGA65 BASIC can handle hexadecimal numbers directly, so you don’t need to bother. Just use the dollar sign notation:

    POKE $D020,$04

    This makes it easy to use MEGA65 BASIC as a hexadecimal calculator. To convert a hexadecimal number to decimal, simply print the value:

    PRINT $D020

    To see the hexadecimal representation of any number or expression, use the HEX$() function:

    PRINT HEX$(53280)

    The MEGA65 I/O registers are in the address range $D000 – $DFFF. In hexadecimal, all of these addresses start with a D. This is easier to understand than using decimal notation for the range: 53248 – 57343.

    Most books on this subject discuss at length how to convert between hexadecimal and decimal. This is fine for getting accustomed to the idea. In practice, as long as your programming tools support hexadecimal notation, you rarely need to convert between hexadecimal and decimal. It’s more convenient to leave addresses and values in hexadecimal, and understand how hex digits represent bit patterns in groups of four. Adding one hexadecimal number to another takes some practice—but you always have your handy MEGA65 to help you.

    The CPU always follows instructions

    The CPU’s job is to perform the instructions of a machine language program. When it’s not running the instructions of your program, it is running the instructions of the MEGA65 kernel to blink the cursor, perform BASIC commands, access disk drives, and so forth. If it doesn’t look busy, it’s busy waiting.

    Machine language instructions manipulate memory, interact with I/O registers, perform simple calculations, and make decisions about what instructions to perform next. There are surprisingly few things the CPU knows how to do. Most of its power comes from being able to perform very many instructions very quickly.

    The CPU reads its instructions from bytes in memory. It keeps track of which address has its next instruction using an internal register called the program counter (PC). The CPU reads the instruction from the address stored in the program counter, then does it. By the end of the instruction, the program counter contains the address of the next instruction to perform, and the process repeats.

    Those columns of numbers in a Compute!’s Gazette magazine program listing are machine language instructions (and data) for the program. As you type them in, Compute!’s “MLX” data entry program stores those values at their corresponding addresses. (MLX magazine listings also include a checksum value as the last number in the line, so it can catch your typing mistakes.)

    To start a typical Compute!’s Gazette program, you use the BASIC SYS command with the address of the first instruction. SYS sets the CPU’s program counter to that address, and the program takes it from there.

    You can write your own machine language routine in a similar way, setting values in memory that represent instructions then calling the routine with SYS. Try entering these commands on your MEGA65:

    POKE $1800,$EEPOKE $1801,$20POKE $1802,$D0POKE $1803,$60SYS $1800

    If you mis-type any of these numbers, your computer might do something strange. You can always restart the computer and try again.

    A human-friendly machine language

    Yes, EE 20 D0 60 is a machine language program. You’re not expected to know what it means, nor are you expected to write programs that way. It’s possible to do so, in the same way that I used to sit in that basement drawing pixel art on graph paper and converting it to byte values for my DATA statements, but it’s slow going. (I tried this recently as an exercise for a different microcomputer. It’s fun, the first time.)

    When most people say they’re writing a machine language program, most often they’re actually using assembly language, a programming language that is roughly similar to the computer’s machine language, along with a tool that converts it to machine code called an assembler. Assembly language consists of the same instructions that the CPU knows how to perform, just spelled out in a way that’s easier to read and write.

    Here’s that short machine language routine again, this time written as assembly language instructions:

    INC $D020RTS

    The first instruction tells the CPU to increase the value at address $D020 by one. The second instruction returns from the subroutine. As we’ve seen, address $D020 controls the border color. Each time you SYS to the first instruction, the border color changes, and control returns back to BASIC.

    Registers, instructions, and addressing modes

    The CPU contains a little bit of memory of its own to use as scratch paper while performing computations. The MEGA65’s 45GS02 CPU has four general purpose registers, each the size of a byte: an accumulator (often referred to as just A), and registers X, Y, and Z. The program counter (PC) is an example of a special purpose register, holding the address of the current instruction.

    The CPU maintains eight one-bit registers, called flags or just status registers (SR), that indicate useful aspects of the machine’s operation. For example, the Zero flag is set after a math operation results in zero, which is useful for countdowns or comparing whether two numbers are equal.

    The CPU reserves a small area of memory to use as a data structure called a stack. Much like a stack of cards, you can push new values onto the stack, and pull the last pushed value off of it. The CPU uses the stack to remember its place when calling a subroutine, like the SYS command does, so it can return to that place when the subroutine performs the RTS instruction.

    The CPU gives special treatment to a single page of memory, 256 bytes starting at an address that ends in $00. It can access this memory faster than other locations, so it’s useful for storing variables that change frequently. In the Commodore 64 (and the 6502/6510 CPU), this is known as the zero page because it is always located at address $0000. In the MEGA65, the 45GS02 CPU can change which page it uses for this purpose, so it is known as the base page. The location of the base page is stored in a register (B).

    Nearly all CPU instructions manipulate a value in working memory, a value at an address, or both. Here are just a few examples:

    * LDA $1900 : load the value from address $1900 into the accumulator

    * LDX #$FF : load the value $FF into the X register

    * STA $D020 : store the value in the accumulator to address $D020

    * ADC #$1A : add the value $1A to the value in the accumulator

    * AND $C901 : set the accumulator to just the 1 bits that are present in both the accumulator and the value at address $C901

    * BNE $180C : set the program counter to $180C (“branch to”) if the last math operation resulted in something other than zero

    * JMP $18FF : set the program counter to $18FF (“jump to”)

    * JSR $1900 : remember the address of the next instruction, start executing the subroutine at address $1900, then return to this location when the subroutine performs RTS

    * PHA : push the accumulator value onto the stack

    * PLA : pull the most recently pushed value from the stack, and set the accumulator to that value

    * TXA : swap the values in the accumulator and X register

    Instructions that access addresses often have variants for different addressing modes that describe how the address is calculated. As shown in the examples above, some instructions can read a value from an address provided with the instruction, or it can read the value provided with the instruction itself (which is just reading it from the memory that contains the program code).

    Addressing modes are a powerful concept, and understanding them is critical for performing certain tasks effectively. The MEGA65 45GS02 CPU has many addressing modes. I recommend learning a few common ones to get started, then read about the rest once you’ve tried writing a few short programs.

    The MEGA65 manuals describe the 45GS02 instruction set and addressing modes in detail. The 45GS02 supports all of the instructions of the 6502, so descriptions of the 6502 instruction set (another good one) that you can find online and in books also apply to the MEGA65.

    The MEGA65 machine language monitor

    The chapter on machine language in The Commodore 64 Programmer’s Guide makes a brief mention of a software tool called “64MON,” and uses it to introduce machine language concepts. I know they did not intend this to be cruel, but it was an insurmountable hurdle for me as a kid that Commodore did not include 64MON or anything like it with the computer.

    64MON was a machine language monitor, a tool for examining and interacting directly with the CPU and memory of a microcomputer. An ML monitor is a gateway to accessing the raw power of a machine, so useful that many microcomputers had one built in. The earliest models of the Apple II even booted directly into an ML monitor, instead of BASIC. Commodore added a built-in monitor to their computers starting with the C16. The MEGA65 includes an all-new monitor, written by Bit Shifter.

    To start the MEGA65 ML monitor from the READY. prompt, type the MONITOR command:

    MONITOR

    The monitor accepts commands similar to the BASIC environment. For example, to exit back to BASIC, type X then press Return. The monitor uses the BASIC screen editor, so you can cursor up to previous lines to repeat or modify commands.

    The first thing the monitor displays is the contents of the CPU’s working memory: the program counter, the status register, the accumulator, and so on. These values aren’t useful when the monitor first starts with the MONITOR command, but you can examine them at any time with the R command.

    I won’t describe all of the monitor’s uses and features here, but I do want to mention two of its primary functions: examining and changing memory values, and assembling and disassembling machine language instructions.

    Try this command:

    M1800

    The M command takes an address in hexadecimal (with or without the $), then displays a block of memory values in hexadecimal. If you POKE’d that short program into memory earlier, you’ll see the byte values at the beginning of this list, along with a bunch of junk values:

    >1800 EE 20 D0 60 8D 41 6A A9 01 8D 40 6A 20 32 52 20 ................>1810 ...

    The command to change values in memory is the > that appears at the beginning of one of these lines. This is not a coincidence: you can move the cursor up to any line printed by the M command, change a value, then press Return to modify the memory.

    The monitor knows how to assemble instructions directly into memory, using their assembly language mnemonics. To start the assembly process, use the A command followed by a starting address and the first instruction, then press Return. It converts the assembly instruction to machine code, stores it in memory, then prompts for the next instruction. Press Return without an instruction to end assembly.

    Try typing A 1800 INC $D020, followed by Return. Then enter RTS on the next line, and finally enter a blank line. Notice that the assembler displays the machine code byte values that it came up with as you type: EE 20 D0 are the bytes for INC $D020, and the 60 byte means RTS.

    To see the assembly instructions stored at an address, use the D command (for “disassembly”) followed by the address. Try this now: D 1800

    . 1800 EE 20 D0 INC $D020. 1803 60 RTS. 1804 8D 41 6A STA $6A41. 1807 A9 01 LDA #$01...

    The instructions you entered appear at the top. Notice that the disassembly continues into the junk data region. The disassembler doesn’t know that those values are meaningless, so it just displays what those bytes would be as assembly instructions, even though it’s nonsense.

    To execute a subroutine from the monitor, use the J command (for “jump”) followed by an address. When the CPU encounters the RTS instruction, it returns control back to the monitor, just as it does with SYS in BASIC. Note that if you write a subroutine that never reaches the RTS instruction, control will never return to the monitor. In most cases, you can hold Run/Stop and press Restore to return to the READY. prompt without losing your program in memory.

    Here’s a variation of the border color subroutine without an RTS instruction. Use the monitor to assemble it at address $1800, then run it:

    INC $D020JMP $1800

    For more information on the ML monitor’s features, see the manual. I also wrote a tutorial on the MEGA65 Monitor as part of a series on introductory assembly language.

    Mega Assembler

    The machine language monitor is super useful for understanding how machine language programs work, and for troubleshooting programs and examining memory. Even so, you would not write large programs this way. A full-fledged assembler application gives you essential tools for managing large amounts of code.

    Mega Assembler by grubi is an assembler for the MEGA65. It includes a source code editor with built-in help features, and can assemble and run your programs, and save them to disk. Check out the example programs included on the disk image to get a feel for how it works.

    One of the most useful features of an assembler is its ability to assign labels to the many numbers that appear in a machine language program. Here’s a version of the border color program for Mega Assembler that is easier to read than the raw instructions you entered into the monitor. (Mega Assembler needs the lines indented as shown.)

    BORDER=$D020 *=$1800START INC BORDER JMP START

    Next steps

    The MEGA65 manuals are the best and most complete reference for the MEGA65, but they do not yet contain introductory material for machine language programming. Many books about machine language programming for the 6502/6510 CPU and the Commodore 64 apply to the MEGA65. The memory locations are different, and the MEGA65’s 45GS02 has more advanced features, but C64 programming books are still a valuable resource.

    Check Archive.org for scans of popular assembly language books, such as:

    * Machine Language for Beginners by Richard Mansfield

    * Machine Language for the Commodore 64 and Other Commodore Computers by Jim Butterfield

    * Compute!’s Machine Language Routines for the Commodore 64

    Despite my struggles with it as a small child without the benefit of the Internet, the chapter of the Commodore 64 Programmer’s Guide on machine language is a good introduction to the topic.

    With a built-in machine language monitor, a freely available assembler, and access to hundreds of websites and PDFs, it’s so much easier to learn how to write machine language programs for the MEGA65 today than it was for the Commodore 64 in 1986. I hope you give it a try, if only to get a sense of how the computer works, on its own terms.

    See you next month!



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • I think many of us were first attracted to the MEGA65 project for its hardware: the Cherry MX keyswitches in an authentic Commodore layout, the precision recreation of the Commodore 65 injection molded case, the 3-1/2" floppy drive—not to mention modern conveniences like HDMI video out and an SD card slot. It has taken nine years of hard work and persistence of vision to bring this project to the point of being something everyone can purchase and enjoy.

    In this Digest, we’ll look at the recent history of the MEGA65 hardware, including the Nexys FPGA development board on which most of the firmware was written. We’ll take a tour of peripherals that work with the MEGA65, both vintage and new. And we’ll look at hardware experiments in progress that may provide a glimpse of the MEGA65’s future.

    But first!

    Resources for new owners

    The latest batch of MEGA65s is being delivered, and it’s been super exciting to see all of the messages and photos from proud new owners in the Discord. If you’re a new owner, welcome to the world of personal computing!

    We have many more resources for getting started with your MEGA65 than we did a year ago. There’s a new documentation landing page, which has links to the latest version of the User’s Guide.

    Last year I wrote a MEGA65 Welcome Guide intended to help new owners get up and running. I’ve been keeping it up to date to be useful whether you received your MEGA65 last May or this January.

    You’ve already found this Digest. You might also enjoy the back issues, available on the website.

    That documentation landing page is part of the MEGA65 Wiki, a relatively new resource that we’re still building. If you’d like to contribute to the wiki, reach out to Gurce on the Discord chat server. You can also read and post articles on Filehost, another great resource.

    Featured Files

    It’s the Digest’s first recurring segment! Here at Featured Files, we look at cool stuff that has been posted to the MEGA65 Filehost. Download and try these on your MEGA65 today!

    Mega Sisters, by Endurion. A version of the 1987 Commodore 64 classic The Great Giana Sisters, this multi-stage adventure pays homage to familiar side-scrolling platformers while adding a few twists of its own. Endurion, aka Georg Rottensteiner, is the author of C64 Studio, a Commodore cross-development IDE for Windows. You can download the source code for this MEGA65 game. Use a joystick in port 2; move up to jump.

    Battle Sparrow, by gurce. A vertical scrolling space shooter in the vein of Warhawk for the C64 (1986), this action game was written entirely in MEGA65 BASIC with PETSCII graphics, vibrant colors, and a rockin’ soundtrack. Use a joystick in port 2.

    Barnsley Fern Fractal, by heath8041. This elegant BASIC program renders the Barnsley fern at a resolution of 640x400. The disk image includes several programs to render the fractal in different ways. Run it yourself, or watch Heath-man’s video.

    The MEGA65 hardware

    When you pre-order a MEGA65 from Trenz Electronic, you can expect to receive a faithful recreation of the unreleased Commodore 65 personal computer, with a few modern improvements. The first step of this experience is opening the rainbow-colored “retail” cardboard packing box. Inside the box is the MEGA65 computer, with its authentic injection-molded plastic case, keyboard with authentic layout and keycap designs using modern mechanical keyboard switches, and a vintage new-old-stock 3-1/2" floppy drive.

    The ports on the back and side of the computer are a mix of modern and familiar: a barrel-jack power connector, a C64-style cartridge port, an IEC serial port, VGA and HDMI video output, an ethernet jack, a microSD card slot, stereo audio output, and two DE-9 ports for joysticks, paddles, and mice.

    Inside the MEGA65 is a circuit board populated with chips and connectors. Compared to its vintage ancestors, the MEGA65’s board is surprisingly spare, with less than a handful of devices that you might call chips and lots of empty green space. Also surprising are what appear to be extra unused connectors for diagnostic devices, additional stereo audio outputs, and unspecified peripherals. The keyboard is a separate device connected to the main board with a ribbon cable, as is the floppy drive. The main board also sports a removable full-size SD card pre-populated at the factory with software, and a CR1220 battery holder for the Real-Time Clock.

    At the center of the MEGA65 is the Xilinx Artix-7 FPGA chip, a modern device that can be programmed to behave like other digital logic devices. Importantly, the FPGA replicates these behaviors electronically, as if these digital designs were etched in silicon. The MEGA65 firmware (or core) describes a complete chipset that in 1991 would have been a dozen permanently-etched chips arrayed across the board.

    The MEGA65 has two smaller FPGA devices on the board, an Altera MAX10 for various electronic functions, and a Lattice device for the keyboard. There are three FPGA devices in total in the MEGA65.

    This is the MEGA65 in its official form. It’s what you buy from Trenz Electronic, and it’s what the MEGA65 team does its best to support with regular testing and improvement of the firmware and system software. The MEGA65 has taken other forms in the past, and the expandability of the machine and open licenses of the designs are meant to encourage experimentation. Naturally, you install such expansions at your own risk.

    From Nexys to MEGA

    The MEGA65 as we know it went through multiple stages of hardware development over the years. Most of the MEGA65 core was built on the Digilent Nexys A7-100T FPGA trainer board, a bare circuit board that electronics designers use to evaluate the Artix-7’s capabilities and learn how to use it. The circuit board is “bare” in the sense that it doesn’t come with its own plastic case, but it is actually quite crowded with features, with connectors and hardware interfaces of various kinds, push-buttons, and a set of seven-segment LED numeric displays. Important to the MEGA65 project, the trainer board includes VGA video output, monaural audio output, a USB port for a PC keyboard, and a microSD card connector.

    While the Nexys board is not an officially supported configuration, the MEGA65 team still provides downloads of the MEGA65 core for the Nexys A7. You can buy a Nexys board for $350 on Amazon, install the MEGA65 core, set up the microSD card, and put together a capable MEGA65 rig. This configuration lacks the eight megabyte RAM expansion of the MEGA65, but this is a documented variation, and many software titles can run without it.

    Note that the Nexus A7 board is also known as the “Nexys4DDR,” which is the name you will see in some documentation. This is not the same as the older board known as the “Nexys 4,” which was also used for MEGA65 development at one point.

    You can program the Artix-7 FPGA using the m65 command-line tool provided by the MEGA65 project, or with Vivado ML: Standard Edition, the free version of the official professional FPGA development suite from Xilinx. Connect your PC to the “PROG UART” microUSB port on the board.

    Support for the USB host port is limited and doesn’t work with USB hubs. You can connect a standard USB PC keyboard to this port, though be warned that fancier keyboards tend to act like USB hubs, so be sure to look for something cheap. A PC keyboard does not have the MEGA65 key layout, but all of the MEGA65 keys are mapped to PC equivalents.

    For serious tinkerers, you can enhance your Nexys board with the DM65PIC MEGA65 widget board, designed by Dieter Penner. The widget board connects to the Nexys’s PMOD ports and provides connectors for an authentic Commodore 64 keyboard, a Commodore 65 keyboard (if you’re lucky enough to have one), and two DE-9 ports for joysticks, paddles, or mice. You’ll have to get a board fabrication shop to make it from the Eagle design files, and depending on which shop you use you may need to solder some or all of the surface mount components. You’ll also have to program the microcontroller using the software in the repo. It’s a significant project, but can make for a satisfying build. See sy2002’s demo video to see the widget board in action.

    While you’re at it, whip up a 3D-printed case for the Nexys using community-provided design files. I don’t have my own 3D printer, so I use 3D printing services like ShapeWays. It’s pretty amazing how we can send homemade design files for things like plastic shapes and circuit boards to fabrication services, and have them in our hands weeks later, for not much money.

    Because the Nexys board was the only way to develop for the MEGA65 project for so long, there are excellent set-up instructions in the Developer Guide. Also check out the article and video by RetroCombs: Install the MEGA65 on a Nexys4 or A7 FPGA (2021).

    Board revisions

    Between the Nexys trainer board and the MEGA65, there were two revisions of the main board. It is occasionally useful to understand the board revision identifiers, especially when locating the firmware release for your computer.

    There were early main board designs known as “R1” and “R2.” These were not distributed, so you won’t see these in the wild.

    In the year 2020, the MEGA65 project produced and sold 100 “DevKit” units, with cases made from laser cut acrylic. The DevKit main board is revision “R3.” It has four slots for firmware cores, and includes eight megabytes of additional RAM (known as “attic RAM” or “HyperRAM”). DevKits came bundled with USB JTAG hardware for testing new cores and doing cross-development of software. You can only flash a new core to slot 0 of a DevKit using the Vivado software.

    The latest main board in today’s MEGA65 is known as revision “R3A.” The differences from the R3 board are minor: there are eight core slots instead of four, and there are some minor electrical changes. The R3A board can only be flashed by the m65 tool and not the Vivado software suite, but you can flash a new core to slot 0 without Vivado.

    From an architecture standpoint, the Nexys, R2, R3, and R3A boards only differ with regards to the Attic RAM: whether it’s present or absent, how much there is, and how fast it performs. The core and system software intend to continue supporting these differences, and software that uses Attic RAM can test for its presence to run cleanly on all boards.

    You’ll see these board revision identifiers in the names of the different versions of the MEGA65 Core Release Package on Filehost:

    * nexys4ddr-widget is the latest firmware for Nexys boards, with widget board support.

    * mega65r2 is for the unreleased R2 board.

    * mega65r3 is for the DevKit (R3) and retail (R3A) MEGA65. You probably want this one.

    Peripherals

    The MEGA65 tries to be compatible with some vintage Commodore peripherals and their modern counterparts. Here’s a quick rundown of a few that I’ve tried. If you have your own experiences or recommendations, be sure to post them to the #peripherals channel in the Discord.

    Joysticks, gamepads, and paddles

    Vintage joysticks meant for Commodore and Atari computers work well with the MEGA65. They connect to the DE-9 ports on the left side of the computer.

    If you’d like to use a Sega Genesis gamepad controller, be sure to use a C64 Genesis adapter. Sega Genesis controllers use DE-9 connectors, but use different wiring that can damage a Commodore. It’s not obvious how much damage it might do to a MEGA65, but it’s mis-wired regardless and I’m not willing to try it to find out.

    I prefer a modern gamepad controller wired for the C64. They look and feel like Nintendo controllers, and they wire the second button to “up,” which is used to jump in platform games.

    For a modern joystick, I like the ArcadeR. It puts an arcade-quality stick and buttons in a featureful, mod-able case, and has options like auto-fire and two-button support. Another option is the Hyperkin Trooper, a good choice if you’re looking for the vintage shape without roughing up vintage equipment.

    The Hyperkin Ranger has a gamepad form factor, and also includes a single wheel for paddle games. Specifically for paddles, I recommend looking for vintage Atari paddles on eBay. They appear to be plentiful, inexpensive, and in good condition, at least for now.

    Mice

    The MEGA65 supports the Commodore 1351 mouse, the Amiga mouse, and anything that can act like either of these. The 1351 tends to be more reliable.

    The MEGA65 must be configured to recognize either the 1351 or the Amiga mouse. Hold the Alt key while turning on your MEGA65 to start the Configuration tool, then set each port to the desired mouse type under the “Input” tab. Connecting an Amiga mouse while in 1351 mode may interfere with the behavior of the keyboard, so if you’re having difficulty, just unplug the mouse and check your settings.

    The mouSTer is a clever modern device that lets you connect a USB mouse to a DE-9 Commodore port. It’s quite versatile, and you can set a variety of options by connecting a USB drive containing a config file. The mouSTer can be configured to emulate either a 1351 or an Amiga mouse, so make sure it matches your MEGA65’s settings. I use my mouSTer with an inexpensive Logitech M185 wireless mouse. If I’m not desperate for the Commodore tank mouse look and feel, I prefer my Logitech.

    I’m looking forward to trying modern retro mice recreations like the Tank Mouse when I get one.

    Other peripherals

    The MEGA65 has an IEC serial port, most often used on Commodores with external disk drives. You can use a vintage external 1581 drive with the MEGA65 in C65 mode. Other IEC devices don’t work so well with C65 mode at the moment due to known timing issues inherited from the Commodore 65 ROM. C64 mode (type GO64) does better in some cases. I was able to get my Blue Chip D12 daisy wheel serial printer to work in C64 mode. Improving IEC device support in C65 mode is on the to-do list for the ROM.

    The FTDI JTAG adapter is a peripheral that mounts to the primary JTAG port on the main board. With your PC connected to it with a mini-USB cable, you can install bitstreams, send programs, transfer files, and debug issues. If you don’t need to install bitstreams, you can use a cheaper and easier-to-find USB serial device connected to the UART pins of the JTAG connector. USB serial communication is great for cross-development and debugging.

    Work is in progress to make it possible to transfer files and programs, and perform other cross-development tasks like debugging, using the MEGA65’s ethernet port, with no need for a separate adapter. If you’re interested in helping test this feature, inquire on the Discord. There’s a test core and new versions of the command-line tools that demonstrate this capability.

    To round out this discussion of peripherals, we might as well mention the Real-Time Clock replacement. This is a peripheral that uses the Grove connector on the main board. The replacement RTC was our workaround solution for the small percentage MEGA65s that shipped with faulty real-time clock chips. The latest firmware detects when the replacement RTC is connected and communicates with it over the Grove connector.

    Paul’s prototypes

    One of the biggest hardware challenges for the MEGA65 project is the limited availability of FPGA chips. Trenz Electronic can only acquire so many of the FPGAs at time, which limits their ability to build and deliver computers. Even the price of a Nexys trainer board has gone up $80 in the last year. We all hope this shortage is temporary, but it may be a few years before we see supply return to previous levels.

    MEGA65 founder and hardware designer Paul Gardner-Stephen is experimenting with a prototype for a lower cost keyboard that doesn’t need its own FPGA. The “DIY keyboard” project intends to be a drop-in replacement for the current MEGA65 keyboard, using the same Cherry MX switches and keycaps, and fitting perfectly in its case with no noticeable difference to the user. It can also be a standalone C65 keyboard for the Nexys board, connected to a PMOD port. You can use the open hardware design files to send away for a bare board, and install your own switches and keycaps. As pictured above, MEGA65 owner mpryon completed his Nexys rig with a DIY keyboard based on Paul’s prototype design.

    It’s too early to say whether the DIY keyboard will become a more polished product for sale. It’s easy to imagine it being sold as a kit with a set of official MEGA65 keycaps, or adapted via microcontroller to be a USB keyboard with a C65 layout for use with the Xemu emulator. You can follow Paul’s progress on the DIY keyboard on his developer blog: October 2022, November 2022, December 2022

    Paul is also working on a prototype for a port expansion board that adds component video output, a Commodore user port, a tape port, and a port for the unreleased C1565 external floppy disk drive. The board would mount inside the MEGA65, and place the new ports through the punch-outs already prepared in the back of the plastic case.

    Why add a port for an unreleased Commodore peripheral? So you can recreate the peripheral, of course! It’s just an idea for now, but the 8-pin mini-DIN connector for the C1565 external floppy drive could support an actual vintage prototype drive, or an all-new project to recreate the drive with a case that matches the MEGA65. At the very least, the port would make the MEGA65 more authentic, matching the similar port on the Commodore 65.

    As with the DIY keyboard, there are not yet plans to produce the expansion board in quantity. You may be able to make your own from open designs at some point. Paul is also dev-blogging progress on the expansion board: October 2022, January 1, 2023, January 6, 2023.

    For several years, the MEGA65 website advertised not only an upcoming reproduction of the Commodore 65, but also a mobile phone based on the same technology. Today, the website focuses on the first project, which, obviously, is now in full swing and in the hands of hundreds of happy owners. Is the mobile phone project still a thing?

    Let this be a lesson: never bet against a project with strong principles. The MEGAphone is still in active development, and making good progress. With a grant from the NLNet Foundation, the MEGAphone seeks to reclaim one of the most important technological spaces in the daily lives of billions of people.

    The idea is this: The sheer complexity of modern computers alienates us from the technology upon which our digital lives depend. It’s not enough for a smartphone operating system to be open source in theory, as Android claims to be. To achieve the benefits of this transparency—security, privacy, control in the hands of the user—the technology has to be strictly modular, and simple enough for a computer hobbyist to understand. The Commodore 65 is one of the last practical computers to fit this description. What if there were a smartphone based on the Commodore 65?

    The MEGAphone is a proof-of-concept portable device with mobile telephony, Internet, and a touch screen interface. It uses the MEGA65 core and ROM, and can run MEGA65 software, including software written by the phone’s owner. Everything is open source, and any owner can replace any component on their phone as easily as they can on the MEGA65.

    To learn more about the project’s goals, watch video of Paul’s 2019 talk, Creating Resilient and Sustainable Mobile Phones. For a glimpse of recent progress, see his recent dev-blog entries about the MEGAphone: September 7, 2022, September 14, 2022, September 20, 2022.

    The MEGA65 hardware released in 2022 is a huge milestone for the project and for vintage computer preservation in general, the culmination of nine years of work to realize the vision of Commodore’s designers and engineers with modern components and techniques. The result is a multi-layered hobbyist platform that will continue to see revisions, adaptations, and expansions into the future.

    If you’d like more information on any of these projects, or if you discover something interesting or build something cool, be sure to let the community know in the Discord.

    Until next time!

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • One of the most satisfying things you can do with a vintage computer is to turn it on and start writing a program. With nothing but your curiosity, a little persistence, and maybe a book and a pad of scratch paper, you can craft a program that solves a problem, performs a task, produces a work of art, tells a story, or generates an interactive experience.

    In this Digest, we’ll look at a few ways to get starting writing programs for the MEGA65 using the built-in BASIC 65 programming language. This won’t be a BASIC tutorial—there are hundreds of vintage books on that subject, and you already have the MEGA65 User’s Guide. There are additional chapters for beginners in the MEGA65 Complete Compendium. Instead, we’ll focus on several ways to create and run BASIC programs with your MEGA65, and with your PC.

    But first!

    Batch 2 shipments have begun!

    Trenz Electronic has announced that batch 2 shipping has begun, and some have already received their MEGAs! The next 400 recipients should receive shipping notices in the next few weeks, followed soon after by receipt of your very own MEGA65.

    Batch #3 is expected to deliver in the third quarter (July-September) of 2023. It’s too early to say how many units will ship in the next batch. Here’s hoping that FPGA supply will be flowing more freely next year.

    Has your shipping address changed?

    For those of us awaiting delivery of a pre-ordered MEGA65: If your shipping address has changed since you placed the pre-order, send an email to: [email protected]

    Changing the shipping address in your Trenz Electronic website account settings will not update shipping addresses on pending orders. You must send them email to update the address on a pre-order.

    I know many of us have been waiting a long time for our MEGA65s. If your address needs updating, take care of it soon to ensure smooth delivery.

    Digest feeds

    You’re probably reading this Digest delivered as email via Substack. If you clicked through to the audio version with the play icon at the top of the email, you’re probably listening to it using a web browser on your desktop computer, tablet, or smartphone. You can read past and current issues, as well as manage your email subscription, on the Substack website: m65digest.substack.com Substack has a phone app, and it includes a built-in audio player.

    Alternatively, you can follow the Digest using your favorite feed reader. The Substack website has an embedded RSS feed, and you can usually just copy the website address into your feed reader to subscribe. If your reader needs the exact feed URL, it’s just this: m65digest.substack.com/feed

    I’m pleased to announce that the audio version of the Digest is now available in your podcast player! Search for “Dan’s MEGA65 Digest” in Apple Podcasts or the Pocket Casts directory. I’ve also found that some (but not all) podcast players can subscribe directly to the Substack RSS feed as if it’s a podcast.

    Finally, just to make sure we’re not too dependent on a single platform, I post a copy of the Digest to my personal website. dansanderson.com/mega65 has links to all of my MEGA65 projects, along with every issue of the Digest. You can follow the RSS feed on that page for just the Digest, or follow the one on my homepage for everything I post. I sometimes write about MEGA65 topics on my main blog.

    Regardless of how you follow the Digest, thanks for being here!

    Entering commands and programs

    Like the Commodores that precede it, the MEGA65 starts up with a blinking cursor at the READY. prompt. You can enter a command by typing the name of the command followed by arguments, and execute the command immediately by pressing the Return key. For example, here’s a command to turn the color of the screen border to black:

    BORDER 0

    You can use the same blinking cursor to write a program, a collection of commands on numbered lines. If you type the BORDER command after a line number then press Return, it does not change the border color, but instead stores the command to be run as part of the program.

    10 BORDER 0

    Here’s a short program that prompts for a temperature in degrees Fahrenheit, then displays the equivalent temperature in degrees Celsius. Try typing these lines into your MEGA65:

    100 PRINT "ENTER A TEMPERATURE IN DEGREES FAHRENHEIT:"110 INPUT F120 C=(F-32)*5/9130 PRINT140 PRINT F;" DEGREES FAHRENHEIT IS ";C;" DEGREES CELSIUS."

    If you’ve written a program on a Commodore before, this should feel familiar. The BASIC screen editor allows you to type whatever you want anywhere on the screen. When you press Return, it checks whether the line with the cursor on it begins with a line number, and if so, it stores the contents of that line in BASIC program memory. If there’s already a line in memory with that line number, BASIC replaces the old line with the new one.

    It’s important to remember that what’s on the screen does not necessarily represent the program stored in memory. You can think of the screen as a sort of scratch pad on which you can type whatever you like. Only when you press Return on a line will BASIC try to do something with what you typed.

    To see the lines of the actual program stored in memory, use the LIST command.

    LIST

    If you notice a mistake or something you’d like to change, you can move the cursor up to the line displayed on the screen, type new text over the old text, then press Return to replace the line in memory.

    BASIC keeps the program in line number order, but you can enter the lines in any order you like. This is handy for inserting a line between two other lines: pick a number between the numbers of the existing lines, and enter the new line with that number. This is why BASIC programmers tend to number their lines by tens (10, 20, 30
), to make it easy to insert a line in the middle of the program (15).

    To delete a line, enter the line number with no text after it. To delete a range of numbered lines, use the DELETE command followed by the range:

    DELETE 1000-1500

    To erase the entire program from memory, use the NEW command. If you do this accidentally and want to bring the deleted program back, don't panic, just type:

    NEW RESTORE

    Saving programs to disk

    Your program is in the computer’s memory, but it is not saved to permanent storage automatically. (Maybe that’s obvious in the context of vintage computers, but we get accustomed to modern conveniences sometimes.) If you turned off the MEGA65 now, the program would be forgotten.

    Hopefully by now you’ve had a chance to mount a D81 disk image and load a program from it. You can also use the Freeze menu to create an empty disk image on your SD card. Try this now: hold Restore for a second then release to open the Freeze menu. Press 0 to mount a disk to device 0 (unit 8). At the top of the list of disk images is the option to create a “NEW D81 DD IMAGE.” Select this, then give the disk a name. I like to call my work disks “WORK” to make it seem like I’m doing something important.

    The new disk image is now mounted. Press F3 to resume to BASIC. (Be careful not to press F5 to reset if you have a program in memory!)

    With a BASIC program in memory, save it to your disk with the DSAVE command. Put the filename in double-quotes:

    DSAVE "TEMPCONV"

    Confirm that your program is on the disk by listing the disk directory:

    DIR

    As written, the DSAVE command will fail if there is already a file with that name on the disk. It’s a common practice to save your work periodically with different filenames suffixed with increasing numbers, so you can revert back to an older version if necessary. (Commodores don’t have built-in revision control systems!) Over a few days, you might end up with "TEMPCONV2", "TEMPCONV3", "TEMPCONV17" on your disk, until you’ve decided which version is the final version.

    Alternatively, you can live dangerously and overwrite the same file each time you save. To do this, prepend the filename with an “at” symbol (@). (The symbol is not considered part of the filename.)

    DSAVE "@TEMPCONV"

    You can now turn off your MEGA65. The next time you turn it on, you can use the MOUNT command with your work disk name followed by .D81 to mount it, then the DLOAD command to load your program back into memory:

    MOUNT "WORK.D81"DLOAD "TEMPCONV"

    Listing long programs

    Eventually your program will be many lines long. The LIST command will try to list your entire program, and only the bottommost 25 rows will be on the screen at the end. How can we navigate a long program listing?

    (If you want to experiment with this without writing a long program, MOUNT "MEGA65.D81" then DLOAD "AUTOBOOT.C65" to load the demo disk’s menu program, which is written in BASIC. If you disabled opening the menu on start-up, this file has been renamed: use DLOAD "MENU" instead.)

    As with previous Commodore BASICs, the LIST command accepts a range of line numbers. This is a slightly cumbersome but precise way to look at a few lines at a time, if you know their numbers.

    LIST 100-300 : rem List lines 100 through 300LIST -300 : rem List all lines up to 300LIST 1000- : rem List all lines starting from 1000LIST 250 : rem List only line 250

    When listing many lines, you can tap the No Scroll key to pause the listing. You can press Run Stop to terminate a paused listing, or No Scroll again to resume. The MEGA65 is so fast in its default 40 MHz mode that this isn’t a practical way to peruse a listing. You could use the SPEED 1 command to set it to 1 MHz and slow it down, but be warned: there’s a bug where the MEGA65 crashes when you Run Stop in slow mode! I don’t recommend this method at all for this reason—but I mention it because it’s interesting.

    The MEGA65 LIST command has an option to display a program listing one screenful at a time:

    LIST PLIST P 100-300

    Press a key at each page to advance to the next one, or press Run Stop to abort at the current page.

    There’s a third method to browse long listings, and it’s my favorite: press F9 and F11 to scroll down and up by a line. (If you’ve redefined your function keys, you can use Ctrl-P and Ctrl-V instead.) I like this method because the screen editor remains active, so you can start typing inside the listing as soon as you see what you want to change. Notice that the screen does not have a modern-style scrollback buffer, even though it seems like it does: it’s actually reading lines from BASIC memory to fill in the scrolling display.

    With lots of text on the screen, remember that you can get new blank lines to type on by running the cursor off the bottom of the screen, or pressing Shift + Clr Home to clear the screen entirely. You can also clear just from the cursor’s line to the bottom of the screen by pressing the ESC key followed by the @ key.

    The Eleven programming environment

    The BASIC 65 screen editor is thoroughly retro and thoroughly Commodore, and it picked up some nice features along the way from the Commodore 128, Commodore 65, and a few added by the MEGA65 team. But perhaps you want a coding environment that’s a bit more modern—without leaving your MEGA65.

    The Eleven programming environment, by Stephen Kleinert (username ubik), reinvents the BASIC 65 editing experience. It provides a modern-style code editor and extensions to the BASIC 65 language to make it easier to use for large projects. It dispenses with line numbers, and instead uses labels for flow control (such as goto statements). Variable names can be longer than two characters, and preprocessor directives allow for efficient definition of constants without taking up variable space.

    The brilliant part is that Eleven compiles your program into plain BASIC 65 code. It generates line numbers, replaces labels, renames variables, strips comments, and minifies syntax. The result is a compact BASIC 65 program that you can save to disk and give to your friends, with no bulky runtime library or other baggage. BASIC 65 is a powerful enough language; Eleven just adds modern documentation and editing conveniences, making BASIC programs easier to write and maintain.

    A copy of Eleven was included on your SD card, and you can download the latest version from Filehost. Here’s how to give it a try:

    * MOUNT "ELEVEN.D81"

    * BOOT

    * Enjoy reading the documentation directly in the editor. Use cursor keys to scroll.

    * Press F1 to load a program.

    * Type dizzy.el and press Return. Scroll through the program listing to see how it works.

    * Press F5 to compile. The program compiles and starts running. Press any key to exit to the READY. prompt.

    * LIST to see the compiled BASIC 65 program.

    * BOOT to return to the Eleven editor, with the last-saved project loaded.

    Eleven will insist that you save your changes before compiling, so you won’t lose anything if your program crashes the machine.

    Stephen has released Eleven to the MEGA65 project with an open source license. There may be on-going improvements in the future.

    Writing BASIC 65 programs on your PC

    Coding directly on the MEGA65 with the printed User’s Guide at your side is a cozy, comfortable experience, free of Internet-y distractions. But sometimes—just sometimes—I want to use modern tools to develop retro software, even if I’m writing in BASIC.

    Full disclosure: I’m a developer tools nerd. I like storing text source files in a Git repository, running things through multiple levels of processing, and automating it all together with Makefiles. One of my favorite ways to write MEGA65 BASIC is on my PC.

    I use a command-line tool called petcat that converts a text file containing BASIC code into a PRG file that I can run on my MEGA65 or in the Xemu MEGA65 emulator. petcat comes with the VICE Commodore emulator suite, which I have installed for all of my non-MEGA65 Commodore projects. VICE doesn’t provide a MEGA65 emulator (that’s what Xemu is for), but petcat does know about BASIC 65 commands.

    That temperature conversion program looks like this in a petcat text file, literally the same text but in lowercase:

    100 print "enter a temperature in degrees fahrenheit:"110 input f120 c=(f-32)*5/9130 print140 print f;" degrees fahrenheit is ";c;" degrees celsius."

    To convert this to a MEGA65 PRG file, use this shell command:

    petcat -w65 -o tempconv.prg -- tempconv.bas

    You can test the PRG file in Xemu by dragging it into a running Xemu window, or by starting Xemu with appropriate command-line options. If you happen to have a JTAG USB adapter, you can beam this PRG file directly to your MEGA65 with the m65 command-line tool or with the M65Connect app (search for “M65Connect” on Filehost).

    petcat labels

    You might notice that a text file on a PC doesn’t seem to be capable of representing everything that might go in a BASIC program. For example, there are characters on the MEGA65 keyboard that are not present on a PC keyboard, like the Up Arrow symbol. How would a petcat program print the graphical glyphs on the front of the keys, like the heart shape on the S? What about the PETSCII control codes, like Ctrl-3 that changes the print color to red?

    petcat represents as many characters as it can with ASCII equivalents. All of the right-hand glyphs that you access by holding Shift and pressing a letter are simply the capital letters. The PETSCII symbols for pound, Up Arrow, Back Arrow, and pi are represented by ASCII characters with the same encoded value: \, ^, _, and ~, respectively.

    Nearly everything else appears in a petcat listing as a label inside curly brackets, such as {red} for Ctrl-3. For example:

    10 print "{clr}{red}SSS {wht}mega65 {red}SSS{wht}"

    The left-hand glyphs that you access by holding Ctrl and pressing a letter are labels like {CTRL-A}. A few codes that are typed with the Mega key look like {CBM-@}. Other PETSCII control sequences have named labels like {clr} or {stop}.

    I won’t clutter this Digest with a complete list. I’ll just say that petcat also knows how to convert a PRG file back into text. If you’re unsure of what label to use for a character or control code, you can create a small program with the character in it using the MEGA65 or Xemu, then run petcat in reverse to see what it looks like.

    petcat -65 -o myprog.bas -- myprog.prg

    CBM PRG Studio 4

    If your PC runs Windows, there’s a compelling new option for MEGA65 cross development. CBM PRG Studio is a much loved integrated development environment for writing programs for Commodore computers. Starting with version 4.0, it includes support for the MEGA65.

    I don’t normally use Windows, so I’m not deeply familiar with CBM PRG Studio’s features. But it took me no time at all to figure out how to use it to write a MEGA65 BASIC program and build the PRG file. It looks like a compelling IDE for Kick Assembler, as well. Give it a try!

    Managing D81 disk images on a PC

    Maybe you’ve written a program on your MEGA65 and saved it to a D81 disk image, and now you want to extract the PRG file on your PC. Or perhaps you’ve written a PRG on your PC, and want to put it in a D81 disk image for the MEGA65. We’ve got tools for that!

    Windows users should go straight to DirMaster, a powerful disk image management tool that supports many formats, including D81. You can create new images, open existing ones, copy files to and from images, and much more.

    Mac and Linux users will prefer droiD64, a desktop app similar to DirMaster. It has fewer features, but I like it because it’s fast and works on all operating systems. It requires a Java 11 runtime, such as OpenJDK or the Oracle Java runtime. I wrote a bit more detail about droiD64 in a recent blog post. Check that out for a technical recommendation on how to improve the start-up script that comes with droiD64.

    Of course, I did say I was a developer tools nerd, so naturally my build scripts use command-line tools to create D81 image files. VICE comes with a tool called c1541, and cbmconvert (download) is another option. Personally, I write my own D81 build logic in Python with the d64 Python library. Most people will get by just fine with DirMaster or droiD64.

    It’s the end of the year, and I hope everyone is able to take some time off, disconnect from the Internet a bit, and spend some quality time with your MEGA65, and maybe family and friends too if you get around to it. When you get back online at the end of your break, don’t forget to share your BASIC programs by uploading them to Filehost!

    I hope you’re all doing well this holiday season, and I hope to see you again in 2023.

    — Dan



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • [Did you know: All issues of the Digest have an audio version! Check out the player at the top of the email or Substack post. — Dan]

    The Commodore 64's Sound Interface Device (SID) chip was ahead of its time. While other personal computers were limited to simple beeps, the SID provided features comparable to professional sound synthesizers, with support for multiple kinds of sound waveforms, three-voice polyphony, and advanced filters and effects. Musician-programmers and game developers pushed the SID's capabilities to the extreme, finding clever ways to drive the chip to produce multi-instrumental arrangements. To this day, artists continue to contribute to a vast legacy of SID-based music.

    The MEGA65's audio subsystem includes four SID chips, alongside more modern sound capabilities. In this Digest, we will scratch the surface of how the SID works, and how to produce sound and music with the SIDs from BASIC. We'll also introduce a new music demo written for the MEGA65 that takes full advantage of all four SID chips. MEGA65 music is a big subject, and we'll cover more music topics in future issues of the Digest.

    But first, some news!

    New firmware release

    The new release bundle for the firmware and system software has completed testing and is now officially declared "stable." The new batch of MEGA65 computers being delivered by the end of the year 2022 will have this release installed at the factory. Anyone who received their MEGA65 computer earlier this year is encouraged to upgrade.

    Release bundles now have version numbers to make them easier to understand. The new release is known as release v0.95, and includes the MEGA65 core dated October 2022 (20221012.18,93d55f0) and MEGA65 ROM 920377. The previous release has been retroactively labeled v0.9.

    I have updated the MEGA65 Welcome Guide to describe the upgrade procedure, and to welcome the new batch of owners. You can download the release v0.95 bundle from Filehost. Sign in with your account, make sure you have redeemed your owner code, then download the release package:

    * MEGA65 Core Release Package (mega65r3) incl. ROM (only accessible if you’re signed in)

    If you have any questions about upgrading, ask for help in the Discord!

    Real-Time Clock replacement program

    The MEGA65 has a built-in Real-Time Clock (RTC) chip that keeps track of the date and time. If you haven't yet, you'll want to open your MEGA65 case and install a battery of type CR1220 on the main board. See the Welcome Guide for instructions with photos.

    It was discovered earlier this year that a minority of MEGA65 computers contained faulty RTC chips, estimated to affect about 20% of computers. Faulty RTCs count the seconds too slowly or not at all. Starting with release v0.95 of the system software, the Freeze menu includes a diagnostic utility that knows how to test for a faulty RTC. (Open the Freeze menu and press the Help key to start it.)

    If your MEGA65 has a slow or stopped clock, you can request a replacement part that connects to the main board. For instructions on how to run the diagnostic utility, and how to request a replacement unit, see this article on Filehost:

    * Request a Real-Time Clock replacement

    Thanks to the generosity of the MEGA65 community, we are able to offer this replacement part for the cost of shipping. Make sure your RTC fails the test with a fresh battery before requesting the part. We will send you email with the cost of shipping to your location after you submit a request, and you can cancel your request without remitting payment. Currently, shipping from the USA to Europe is $18 USD. We will try to find the cheapest shipping option to your location. We only accept PayPal at this time. [Update December 2022: Previously we covered shipping costs through donations. Donations have since been exhausted. Thanks to everyone who contributed!]

    I am personally assembling these replacement parts in my basement! Many thanks to the MEGA65 team and community donors for making this fix possible.

    C64 core release 4

    The MEGA65 is not just a MEGA65. Thanks to its FPGA-based architecture, it can be reconfigured to behave like other computers. By far the most thorough transformation available today is the Commodore 64 core by MJoergen and sy2002, based on the MiSTer core. This core provides a PAL-mode C64 experience with a high degree of compatibility, and has been tested thoroughly with even the most intense games and demos. The “C64 for MEGA65” earns its place in slot 2 of everyone’s computers.

    They’ve just announced a new release 4 of the C64 core, which adds RAM Expansion Unit emulation and writable D64 disk images. Many aspects of the core can be configured, especially display settings, and starting with this release you can save your settings to the SD card.

    Download the C64 core from Filehost and install it from the core selection menu, similar to how you upgraded the MEGA65 firmware.

    The sound of ones and zeroes

    The simplest way for a computer to make sound is to send ones and zeroes to a speaker. A "one" pushes the diaphragm of the speaker all the way out; a "zero" pulls it all the way in. If the computer sends alternating ones and zeroes fast enough, we perceive the pressure wave generated by the diaphragm as sound.

    The faster the computer alternates the ones and zeroes, the higher the pitch of the sound we perceive. The slower the alternations, the lower the pitch. We can describe the pitch of the sound in terms of the frequency of the repetitions, expressed as the number of repetitions per second, or Hertz (Hz). A frequency of 880 Hz is higher in pitch than a frequency of 660 Hz.

    The more forcefully the computer pushes the diaphragm of the speaker, the louder the sound. This is known as the amplitude of the wave, or the volume of the sound. The computers sending ones and zeros to a speaker are beeping as loud as they can: the difference between the "one" and the "zero" is as much as it can push the speaker. If you're lucky, such a computer has a volume knob connected that reduces the amplitude of the signal electronically before it reaches the speaker.

    With only ones and zeroes at its disposal, it might seem like this simple computer can only make one kind of sound at different pitches, or no sound at all. In fact, it can change the nature of the sound in one other way. When it sends a "one" for a small fraction of a second then sends a "zero" for that same amount of time, and repeats this pattern at a given frequency, the computer generates a special kind of pulse wave known as a "square wave." The computer can also differ how long it holds the "one" relative to the "zero," known as the pulse width. The pulse width affects the timbre of the sound, a musical term referring to the nature of the tone independent of its frequency or amplitude.

    It's worth pausing here to admire what creative coders have done with these simple pulse waveforms. By rapidly adjusting the frequency and width of these pulses in complex patterns, computers can generate music that sounds, at least to a generous observer, like a band of instruments playing a tune.

    Introducing the SID

    Pulses are a crude digital way to make noise. By the time of personal computers, musicians had already spent decades developing sophisticated analog sound synthesis techniques. To break free of pulse waves, computers needed analog devices that they could control digitally, entire chips dedicated to sound and music.

    Commodore's solution was the MOS 6581 Sound Interface Device, now known the world over as simply "the SID chip." The SID brought sound synthesis features previously found only in professional musical instruments to home computing, and became a defining characteristic of Commodore computers. For later models of the C128 and C64C, Commodore used an improved version with the part number 8580 with minor differences from the 6581. Audiophiles are divided as to which version sounds best. SID designer Bob Yannes went on to found the Ensoniq synthesizer company with an expanded version of the SID in its instruments.

    The SID can generate four distinct types of sound wave: pulse waves of multiple pulse widths, triangle waves, sawtooth waves, and a randomized "noise" waveform. A single SID chip has three independent signal generators, capable of three simultaneous "voices" with separate wave and volume controls that can be combined for effects or used as separate instruments. (The 8580 can even merge the waveform types, but this is seldom used.)

    The SID can trigger tones programmed with a volume pattern known as an "envelope” that can reproduce behaviors of musical instruments and other sound sources, such as a bowed violin or a plucked guitar. The signal generators can be synchronized and modulated with each other, and the combined output can be filtered by frequency.

    The SID made the Commodore 64 popular with musicians, and composers produced a long legacy of SID music for games and demos. Third-party hardware such as the SID Symphony cartridge gave the Commodore a second SID chip, and you can find many six-voice dual-SID compositions in the archives. Today, hobbyist-made devices to add a second SID chip to a C64 are widely available. The vintage SID chips themselves are getting increasingly difficult to find, though hobbyists have recreated them as FPGA-based devices that slot in to vintage and retro hardware.

    The MEGA65's audio subsystem includes four SIDs as part of its FPGA architecture, for a total of twelve independent voices. The MEGA65 produces stereo audio, and by default places SIDs 1 and 2 panned slightly to the right, and SIDs 3 and 4 slightly to the left. You can adjust the mix yourself from the Freeze menu: hold Restore for a second then release, then press the A key to select the audio mixer utility.

    The MEGA65 also has separate hardware for playing 16-bit digitized audio samples, and room to add a Yamaha OPL FM synthesizer in a future firmware update. Altogether, MEGA65 audio represents multiple generations of microcomputer sound technology.

    Sound and music with BASIC 65

    MEGA65 BASIC makes it easy to include sound and music in your programs with simple commands. BASIC reserves two SID chips (six voices) for sound effects and the other two SIDs (the other six voices) for music, so effects and music never compete for resources.

    All sound occurs simultaneously with the action of your program: the commands return control immediately, so your program can continue to drive animations and game logic while the music plays. This powerful feature is unlike any other BASIC, which, if they have sound commands at all, typically wait for the sound to finish playing before proceeding to the next command.

    While these commands do not provide access to all of the features of the SID chips, they're a quick and easy way to add sound and music to your BASIC programs.

    The SOUND command

    SOUND voice, frequency, duration, sweep-dir, sweep-lower-frequency, sweep-size, waveform, pulse-width

    The SOUND command plays a single sound effect. When you provide the voice number (1-6), a frequency (in Hz), and a duration, it plays a square wave:

    SOUND 1,3520,90

    The duration is in a unit called a "jiffy." The length of a jiffy depends on the MEGA65's video mode: in PAL mode, it's 1/50th of a second, and in NTSC mode it's 1/60th of a second. (We'll discuss this oddity a bit later.) So a duration of 90 in NTSC video mode would sound the tone for one and a half seconds.

    The SOUND command can apply fun frequency sweeping effects, good for sirens, whoops, and rumbles. The sweep is described by three parameters. The first parameter is the direction of the sweep: 0 for up, 1 for down, and 2 to wobble up and down. Next is a second frequency lower than the first, defining a range that the sound will sweep between. The last sweep parameter is a duration of each repeat of the sweep. Larger numbers produce faster sweeps and more repetitions over the duration of the sound effect.

    Experiment with these numbers to see what sounds you get.

    SOUND 1,3520,90,0,2640,50

    The command accepts additional parameters to select a different waveform or set the pulse width. If you want to use one or both of these parameters without a frequency sweep, provide empty values (just commas) for the sweep parameters.

    For the waveform parameter, select 0 for a triangle wave, 1 for a sawtooth wave, 2 for a pulse wave, and 3 for noise. If you select the pulse wave (the default), you can set a pulse width in the range 0-4095.

    Here's a non-sweeping triangle wave:

    SOUND 1,7040,90,,,,0

    This produces low noise:

    SOUND 1,880,90,,,,3

    A noise waveform with frequency sweeping might sound like an airplane engine sputtering:

    SOUND 1,4000,45,2,2000,900,3

    Try the pulse waveform with different pulse widths to see how it affects the sound of a pulse wave:

    SOUND 1,4000,45,2,2000,90,2,200SOUND 1,4000,45,2,2000,90,2,800SOUND 1,4000,45,2,2000,90,2,2500

    The PLAY command

    PLAY voice-1, voice-2, voice-3, voice-4, voice-5, voice-6

    While you could generate musical melodies using a series of SOUND commands, this isn't convenient. Instead, BASIC 65 has a featureful music system, and it's based entirely on strings—strings of text, that is.

    The PLAY command accepts up to six string parameters, one for each voice reserved for music. Each string describes a sequence of notes and directives to be performed by the voice. Sequences for separate voices are performed simultaneously, so you can generate harmonies and rhythms.

    This command plays a simple melody using a piano-like sound:

    PLAY "CEG"

    These are the notes C, E, and G, played in sequence with a single voice. To play them simultaneously as a chord, we give one note to each voice in separate strings:

    PLAY "C","E","G"

    The directives and notes in a PLAY string are evaluated in order from left to right. A directive affects all subsequent notes played by the voice, until another directive changes the effect. For example, the O directive sets the octave with a number in the range 0-6:

    PLAY "O3 CDEFGAB O4 CDEFGAB O5 C"

    PLAY will ignore spaces in the string, so you can organize the symbols for clarity.

    Each note is a letter in the diatonic C major scale: A, B, C, D, E, F, or G. The letter can be preceded by modifiers: the # symbol to make it sharp or the $ symbol to make it flat. For example, $B is B-flat. A note can also be the letter R to specify a rest.

    PLAY "O4 RGG $BRRRGG $BRRRG$B O5 $ERDRCR CR O4 $B"

    Duration and tempo

    A note is a quarter note by default. You can precede it with a letter to set its length: W for whole note, H for half note, Q for quarter note, I for eighth note, and S for sixteenth note. Any of these followed by a dot (.) extends the duration by half: a dotted quarter note is the same duration as three eighth notes. For example, S#F is an F-sharp sixteenth note.

    The note duration persists for the voice like a directive, so you only need to specify it once in a run of notes with similar durations.

    PLAY "O4 S#F#G#F#G#F"

    You can adjust the tempo for the entire song using the TEMPO command. Its sole parameter is a number in the range 1-255, where larger values are faster. You can think of this value in terms of beats per minute divided by ten: TEMPO 12 sets the tempo at 120 bpm. (The User’s Guide defines this value as the denominator in a fraction of seconds for a whole note, which breaks my brain.)

    TEMPO 12

    Instruments and envelopes

    So far we've been playing a piano-like instrument. This is defined by a combination of the SID waveform type and an "envelope" that describes the volume curve for each note. The envelope consists of four segments, during which the volume increases (the attack), abates (the decay), holds (the sustain), then fades out (the release). This is what differentiates instrumental notes from the solid tones we produced with the SOUND command.

    BASIC 65 starts with 10 default instrument envelopes, numbered from 0 to 9: piano, accordion, calliope, drum, flute, guitar, harpsichord, organ, trumpet, and xylophone. To change the instrument being used, issue the T directive followed by the number.

    PLAY "T6 O4CECGCO5C"PLAY "T8 O4CECGCO5C"PLAY "T9 O4CECGCO5C"

    Some of the instruments are more convincing than others, and may require some experimentation to fit your song.

    You can overwrite any of the ten instrument slots with your own definition. See the ENVELOPE command in the User's Guide for more information.

    Looping, waiting, and silencing

    The L directive tells the PLAY command to loop to the beginning of the string. This is great for background music that needs to play indefinitely. Remember to loop all voices for a piece of music in the same place—or loop them in different places for interesting effects! For instance, you can have a short loop for drums and a long loop for verses and choruses.

    Issuing a new PLAY command with a new sequence for a voice that's currently playing will stop the current sequence and start the new one. If you want a voice to continue playing while you issue a new sequence to a different voice, leave an empty parameter.

    PLAY "CEGBGEL" :rem a loop for voice 1PLAY ,"EDCDEGE" :rem a sequence for voice 2, does not interrupt voice 1

    If you want your program to wait until a PLAY sequence has completed, use the RPLAY(n) function to test whether a voice is currently sounding. It takes the voice number as a parameter, and returns 1 if that voice is making sound, or 0 otherwise.

    10 PLAY "O4CECGCO5C"20 BORDER 030 IF RPLAY(1) THEN 3040 BORDER 6

    To silence all voices, issue the PLAY command without parameters. You will probably use this often when debugging games with background music, as the music will keep playing after the program halts with an error.

    PLAY

    Learning more about PLAY

    When you first turned on your MEGA65, it loaded the demo disk menu with some jaunty background music. This menu is a BASIC program, and the music is produced by the PLAY command. Run the menu, exit to BASIC, then LIST the program to find the PLAY statements.

    The User's Guide describes a few more features of the PLAY command not covered here. The PLAY command can actuate the ring modulation feature of the SID, an effect that involves combining multiple voices in a complex way, so you'll want to read more about that. PLAY can also enable and disable the filter on the SID; filter parameters can be set with the FILTER command.

    Remember that PLAY sequences are BASIC strings. This means you can assemble and manipulate these strings as values before passing them as arguments to PLAY. This also means they are constrained by the BASIC limit of 255 characters per string. If you run out of string, you might consider breaking your composition into parts, and using RPLAY() to wait for each part to finish before PLAYing the next part.

    The best way to learn is to experiment! Remember that you can always reset the computer and try again.

    What's PAL got to do with it?

    Earlier, we said the SOUND command measures duration differently depending on which video mode your MEGA65 is in: PAL or NTSC. Why would the video mode have anything to do with playing sound?

    Programs that play music are sensitive to timing. They need to execute code with strict regularity to make sure the music keeps up with the beat. Commodore games and demos typically tie their playback loops to another part of the architecture that keeps strict time: the video chip. Using raster interrupts, they set up their code to trigger each time the video chip refreshes the screen. The screen refreshes an exact number of times per second, so this is a good way to advance to the next step in a music composition with strict regularity. It's like turning the cylinder of a music box at a steady pace.

    There's just one problem with tying playback to the video refresh rate: the PAL and NTSC video standards used different rates! Commodore made different versions of their computers for the analog video standards in the countries where they were sold, PAL in Europe and NTSC in the United States and Japan. (In countries that used a third standard called SECAM, Commodore sold PAL computers with video adapters.) PAL refreshed the screen at 50 Hz, and NTSC refreshed at 60 Hz. In many cases, games and demos written for one video standard played too slowly, too quickly, or not at all on a computer built for the other standard. It’s possible to write a program that works similarly for both, but this requires additional effort, and few people had both kinds of computers to test with.

    The MEGA65 outputs a modern digital video signal that supports multiple refresh rates. For compatibility with older software, the MEGA65 continues to honor PAL and NTSC as separate video modes, including their raster timings. Many modern digital displays will honor both modes, but some of us have older displays that get confused by one or the other. You may or may not remember setting your default video mode when you turned on your MEGA65 for the first time.

    You can check which mode you're in, and change it, in the Freeze menu: hold Restore for a second then release, then locate the Video setting (PAL50 or NTSC60). Press the V key to switch between them. If a game or demo isn't running correctly for you and your display supports both modes, try switching modes and running the program again.

    PAL vs. NTSC survey!

    Can the display you use with your MEGA65 support both PAL and NTSC video modes, or just one or the other? Developers want to know!

    MEGA65 musician and demo coder deathy has set up a one-question survey that asks which video modes your set-up supports. Please take a moment to answer it. It'll be a big help to MEGA65 game and demo developers!

    * PAL vs. NTSC survey for MEGA65 owners

    Xanadu

    Syntax 2022, the 16th annual demo party in Melbourne, Australia, took place this month, and the MEGA65 was there! deathy and MEGA65 contributor Gurce, both members of the BAS demo group, produced “Xanadu,” a two-part tribute to the late Olivia Newton-John.

    Part one is written in assembly language and features an arrangement of the Newton-John classic using all four SID chips. Part two offers another take, this time rendered entirely in BASIC with the PLAY command.

    Download the D81 disk image and run it on your MEGA65 today!

    * Xanadu for the MEGA65

    There's plenty more to say about music on the MEGA65, but it'll have to wait for future issues. Until next time, thanks for listening!



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • Personal computers in the early 1980s ignited the home video gaming industry with their ability to display animated color graphics. Even so, the games with the best images were the ones with no graphics at all. Text adventure games told tales of fantasy, mystery, and suspense with you as the protagonist, rendering entire worlds using only the written word and your imagination.

    The effectiveness of the medium and the limited hardware requirements have made text games the longest living and most widely supported form. Archivists, hobbyists, and game authors have reverse engineered and ported vintage text games to modern computers, and evolved the form into the modern day. Thanks to members of our community who have continued that work, you can play a vast legacy of interactive fiction—everything from classic games to new releases—on your MEGA65.

    Hibernated 1: Director’s Cut

    A Cold Dark PlaceYou wake up. A feeling of nausea grips you as youslowly regain control of your senses. You shouldopen your eyes.>open eyesBlurred shapes slowly morph into a clear picture.It takes a moment for you to find your way back toreality. Has the Polaris-7 reached its destination?Still a bit shaky on your legs you climb out ofthe hypersleep tube.Hibernation ChamberThe room is lit by a gentle blue light. A glancethrough the porthole reveals nothing but theendless vastness of the Centaurus constellation.Proxima Centauri must be very close now. But thereis no planetary orbit in sight. It seems an incidenthas interrupted your journey to Proxima C1. Theonly exit is starboard.The status monitor of the hypersleep tube flashesintrusively.>examine monitorIf this information is correct, then you have spentnearly 20 years in hypersleep. During this time adistance of about 4.1 light-years was covered.Proxima Centauri is 4.24 light-years away from Sol,which confirms the assumption that you haven'treached the target system yet. What's going on here?

    In Hibernated 1 by Stefan Vogt, you play Olivia Lund, a space-faring explorer whose long voyage to Alpha Centauri is interrupted by a mysterious alien vessel. With your artificial intelligence companion Io, you must board the vessel and learn its secrets to break free of its tractor beam.

    To play a text adventure game, you describe the actions of your character in abbreviated English commands. The story proceeds with each action, so you can take your time to read descriptions for clues and work out solutions to puzzles. In Hibernated 1, you navigate around spaceships (yours and theirs) with commands like starboard, port, fore, and aft. You can also examine objects to investigate your surroundings.

    >starboardLower CorridorFlashing red warning lights are reflected on thepalladium glass. From here, you're able to reachevery section of the ship. The hibernation chamberis port, while your private area is starboard.The docking bay lies aft.The passage fore, leading to the Polaris-7 commandunit, is barred by a massive security door. Itdivides the narrow corridor into two halves.>examine lightsLooks like we have a problem.

    Some objects can be taken, carried, and used at various points in the story. Others are fixed in place, and you must remember where they are and come back to them when needed. When playing text adventures, it is critical to take notes and draw maps in a paper notebook so you don’t lose your way.

    >aftDocking BayYou stand in a desolate hall. This is the sectionwhere raw materials and samples of foreign originmust be stored, according to the Terran Alliancedirective. Fore you get back to the corridor. Anairlock aft allows you to leave the Polaris-7.A laser rifle is leaning against the wall.You also notice your spacesuit.>take rifleTaken.>take spacesuitTaken.>wear spacesuitYou are now wearing the spacesuit.

    Stefan originally released Hibernated 1 for the Commodore 64 and several other systems in 2018. In 2021, he rewrote the game with a revised story and puzzles, and published the “Director’s Cut” for a whopping twenty-eight (28) microcomputer platforms. You can even play it on a modern computer. Hibernated 1: Director’s Cut is available for the MEGA65, with an 80-column text display and the ability to save your progress to disk.

    You can download Hibernated 1 from 8bitgames.itch.io. The download is free of charge; donations to the developer are welcome.

    For an authentic vintage software experience, you can purchase a physical boxed edition of Hibernated 1 for the MEGA65 from publisher poly.play. The physical edition comes on a 3-1/2" floppy disk that you can use with your MEGA65’s floppy drive, in a gorgeous display box designed to resemble the games we used to buy in computer stores. And just like Infocom games back in the day, the box is packed with extras.

    The physical edition of Hibernated 1: Director’s Cut qualifies as the first commercial title for the MEGA65. If boxed software appeals to you, you might also be interested in the second qualifying title, Showdown by Badger Punch Games, a two-player action game for the MEGA65 available in a display box from poly.play and as a download from badgerpunch.itch.io.

    What is the Z-machine?

    The most famous name in text adventures is Infocom, an American software company founded in 1979. Their most famous game was Zork, a treasure hunting adventure that begins in a boarded up cottage in the woods. Infocom published 36 original text adventures over ten years, including several Zork sequels and an adaptation of The Hitchhiker’s Guide to the Galaxy by Douglas Adams.

    Key to Infocom’s early success was the ability to publish versions of their games for multiple microcomputer platforms simultaneously. All games were written in a custom programming language that ran on a common engine known as the Z-machine (Z for Zork). Infocom made versions of the Z-machine for every major microcomputer from the Apple II to the Amiga. This effectively erased the difference between each type of computer as far as the game’s Z-machine code was concerned: the story could be written once, compiled to Z-code, then interpreted by each platform’s Z-machine to play the game. When a new kind of computer came to market, Infocom simply built a new Z-machine for it, then re-released their entire catalog.

    The longevity of this strategy continues to this day, over 40 years later. After Infocom ceased operations, hobbyists reverse engineered and documented the Z-machine standard. It’s a fun coding exercise to build your own Z-machine that can run Infocom story files, and implementations exist for nearly every modern computer. This is how Stefan released Hibernated 1: Director’s Cut for twenty-eight computers simultaneously: it’s a game written for Z-machines.

    The Z-machine is a popular target for modern authors thanks to its ubiquity. The annual Interactive Fiction Competition gets new entries in this format every year, and you can find plenty more via the Interactive Fiction Database. Be sure to look for game files with names with endings such as .z3, .z5 or .z8. (There are several other formats used for interactive fiction, including Glulx, TADS, Twine, and more.)

    Ozmoo

    Ozmoo is a Z-machine player by Johan Berntsson and Fredrik Ramsberg for the MEGA65, Commodore 64, Commodore 128, and Commodore Plus/4. It’s a modern take on the idea, capable of taking advantage of each machine’s capabilities to their fullest extent, especially when extra memory is available. Ozmoo can run pretty much any game written for the Z-machine, including nearly all Infocom games and most modern Z-machine games.

    Infocom experimented with sound effects and still graphics for a few of their games. Ozmoo supports the ones with sound effects, but not the ones with graphics (“v6” files).

    The best way to get Ozmoo games for your MEGA65 is with Ozmoo Online, a web-based utility that can convert any compatible Z-machine game file into a playable D81 disk image. Ozmoo is free and open source, and you can learn more about it from the Ozmoo Github repository.

    Fredrik, known as fredrikr on the Discord, has done a ton of great work to make interactive fiction available to the MEGA65 community. For starters, Ozmoo Online has every classic Infocom game available for download. Simply select one of the provided story files from the menu instead of uploading one.

    Be sure to select MEGA65 as the platform, and “81” as the build mode. I also recommend enabling the scrollback buffer, a handy feature of Ozmoo that works well with the MEGA65’s “AtticRAM” extended memory.

    Fredrik has packaged the two Infocom games with sound files as a separate MEGA65 download. You can find it on Filehost:

    * Infocom sound games

    If you’re playing Infocom games, you’ll also want the original game manuals. You can download PDF scans of these from infodoc.plover.net. Some of the manuals contain information required to finish the games.

    The interactive fiction community has been developing new Z-machine games for decades. Fredrik has bundled a selection of the best of these, using Ozmoo for the MEGA65. These are also on Filehost:

    * The MEGA65 Z-code Text Adventure Collection Pack #1

    * The MEGA65 Z-code Text Adventure Collection Pack #2

    * Game Book Collection

    Need more? Try these text adventures written by MEGA65 owners, including two by Fredrik himself:

    * The Job, by fredrikr

    * Vacation Gone Awry, by fredrikr

    * Arthur’s Day Out, by WauloK

    * Brotquest 2, by EgonOlson71

    Writing a Z-machine game

    Infocom used their own custom language called “ZIL” to write their games. Contemporary authors use a family of languages called Inform, specifically Inform 6 and Inform 7. A newer language called Dialog is also worth a look, especially when writing games for microcomputers.

    Inform 6

    Inform 6 is a programming language for writing Infocom-style adventure games for the Z-machine. Typically, you use it with the Inform 6 standard library, which implements a wide range of useful object properties (doors, keys, containers, food) and player verbs (open, unlock, put in, eat). The Inform 6 compiler is a command-line tool that takes an Inform 6 source file and produces a Z-machine game file.

    Here’s a tiny excerpt of how a bit of the Docking Bay in Hibernated 1 might be implemented. (This is not the actual code. Among many things, I’ve omitted code that replaces “north” and “south” with shipboard directions “fore” and “aft.”)

    Object docking_bay "Docking Bay"with description "You stand in a desolate hall. This is the section where raw materials and samples of foreign origin must be stored, according to the Terran Alliance directive. Fore you get back to the corridor. An airlock aft allows you to leave the Polaris-7."n_to lower_corridor,s_to airlock,has light;Object rifle "laser rifle" docking_baywith name 'rifle' 'laser' 'gun', initial "A laser rifle is leaning against the wall.", description "The rifle supports two modes: paralyze and disintegrate.";

    Even though Inform 6 is intended to build to the Z-machine format, its standard library was written with modern computers in mind, and tends to produce game files too large to run on vintage microcomputers. Ozmoo co-author Johan Berntsson produced PunyInform, a replacement for the Inform 6 standard library optimized for low memory computers like the Commodore 64. You use PunyInform with the Inform 6 compiler.

    macOS and Linux users can download the Inform 6 source bundle with everything you need, including the Inform 6 compiler, standard library, and PunyInform. The Interactive Fiction Archive also has pre-built versions of Inform 6 for many platforms, library add-ons, and plenty of example code. I recommend using Visual Studio Code to write Inform 6 games: there are extensions available that allow you to compile and play your game directly in the editor.

    The definitive book about the Inform 6 language is The Inform Designer’s Manual by Inform’s creator Graham Nelson. It’s exceptionally well written and includes general information about interactive fiction and game design, as well as a tour of the language and its library. I consider it a classic text, and recommend it to anyone with even a casual interest in the subject. Read it online, or buy it in hardcover or paperback.

    Inform 7

    Inform 7 is a newer language and authoring system for narrative game writing. It’s a radical departure from Inform 6, using a logical programming paradigm and a natural language syntax, so source code reads like English prose. Inform 7 also includes a friendly authoring application where you can write an Inform 7 game, test it, read high quality documentation, and even develop automated tests that put your game through its paces.

    Here’s how that Docking Bay example would be written in Inform 7 (again, not the actual code):

    Docking Bay is a room. "You stand in a desolate hall.This is the section where raw materials and samplesof foreign origin must be stored, according to theTerran Alliance directive. Fore you get back to thecorridor. An airlock aft allows you to leave thePolaris-7."The Docking Bay is south of the Lower Corridor. TheDocking Bay is north of the Airlock.A laser rifle is in the Docking Bay. Understand"rifle" and "laser" and "gun" as the laser rifle."A laser rifle is leaning against the wall." Thedescription of the laser rifle is "The rifle supportstwo modes: paralyze and disintegrate."

    Inform 7 is designed to be accessible to authors without a computer programming background, but it doesn’t skimp on computational power or expressiveness. Some programmers prefer Inform 6 because it looks more like a programming language. Most new language innovation is happening with Inform 7.

    The only reason I didn’t give Inform 7 top billing in this section is that games made with Inform 7 tend to run slowly on microcomputers. The MEGA65 version of Ozmoo can handle simple Inform 7 games with the “Inform 7 XL Stack” option enabled in Ozmoo Online, but they tend to be too slow to play.

    For making Z-machine games for the MEGA65, stick with Inform 6. If you also want your game to run on smaller machines like the Commodore 64, use PunyInform instead of the Inform standard library.

    Dialog

    Dialog is another modern take on writing interactive fiction by Linus Åkesson. It borrows ideas from Inform 7 and the Prolog programming language, with an emphasis on minimalism, clarity, and performance. Dialog brings some of the best language design ideas to games that can be played on vintage microcomputers with Z-machine players. Like Inform, Dialog includes a rich standard library that makes starting new stories easy.

    Here’s my novice attempt at describing the Docking Bay in Dialog:

    #docking-bay(room *)(name *) Docking Bay(look *) You stand in a desolate hall. This is the section where raw materials and samples of foreign origin must be stored, according to the Terran Alliance directive. Fore you get back to the corridor. An airlock aft allows you to leave the Polaris-7.(from * go #north to #lower-corridor)(from * go #south to #airlock)#rifle(item *)(name *) laser rifle(descr *) The rifle supports two modes: paralyze and disintegrate.(appearance *) A laser rifle is leaning against the wall.(dict *) rifle laser gun(* is #in #docking-bay)

    Dialog includes a command-line compiler and a handy interactive debugger. The software bundle includes pre-built tools for Windows and Linux, and it’s easy to build them from source on macOS. Linus also has his own alternative to the Z-machine, which he calls the Å-machine, optimized for converting Dialog games to playable web pages and Commodore 64 disk images.

    Adventures in BASIC

    I’ve always been interested in how computers can be used to tell stories. One of my favorite books as a kid was Creating Adventure Games on Your Computer by Tim Hartnell (1983, Ballantine Books). In fewer than 200 pages, Hartnell covers game design, BASIC coding techniques, and several fully playable adventure games that you can type in, play, and modify.

    I love the title of the kid’s book Creating a Database Adventure Game by Steve Rodgers and Marcus Milton (1985, Aladdin Books). It’s a genuine insight that adventure games are like explorable databases: tables of values that describe the state of the world, and long strings of text that become the game’s narrative based on the player’s actions.

    Write Your Own Adventure Programs by Jenny Tyler and Les Howarth (1983, Usborne Publishing) is another, with excellent visualizations of how BASIC programs are structured. Both of these books use a grid structure to represent the game world, with each cell a location with potential exits in the four cardinal directions (north, east, south, west).

    Compute!’s Guide to Adventure Games by Gary McGath (1984, Compute! Books) only dedicates a few chapters at the end to authorship, but it includes useful advice on structured programming and a short type-in. Most of the book is a catalog of the state of adventure games of the era, summarizing their stories and reviewing their features. Infocom gets its own chapter.

    Of all the books on BASIC that came out of the 1980s, the ones about adventure games were some of the most informative and inspirational. They described how to organize large programs, how to design and implement data structures beyond simple variables, and how to build a game engine as much as a game. And they showed how evocative text games can be, even with no graphics, simple command parsers, and short text descriptions. You can read these vintage BASIC books and others on Archive.org.

    I was going to write up a bunch of tips for coding adventure games in MEGA65 BASIC for this Digest, but we’re running a little long. Instead, here’s a brief example of a technique for representing a world map that’s common to most vintage BASIC books on the subject: the travel table.

    Let’s say our game takes place on the Polaris 7, Olivia’s ship from Hibernated 1. At the beginning of the game, Olivia can access five rooms: the Hibernation Chamber, the Lower Corridor, the Private Area, the Docking Bay, and the Airlock. Olivia can navigate these rooms by traveling fore, aft, starboard, or port, according to the entrances and exits to each room.

    For this example, we’ll go with the simplest possible command parser. We’ll use an INPUT statement to accept the command, and compare the value against the four directional commands. If a command is recognized, it is converted into a number from 0 to 3 in the C variable, and processing continues on line 380. Otherwise it is rejected with a message, and control loops back to the INPUT statement.

    100 DIM CM$(4):FOR I=0 TO 3:READ CM$(I):NEXT110 DATA FORE,AFT,STARBOARD,PORT300 INPUT C$310 PRINT320 C=-1:FOR I=0 TO 3330 IF C$=CM$(I) THEN C=I340 NEXT I350 IF C-1 THEN 380360 PRINT "I DON'T UNDERSTAND."370 GOTO 300

    The travel table is a two-dimensional array, with one row for each room, and one column for each movement direction. The value of a cell represents the exit for that room in that direction. If the value is a room number, that is the destination of the exit. If the value is 0, then there is no exit in that direction. We reserve room #0 for this purpose, so room numbering starts at #1. For example, the Docking Bay has an exit fore to the Lower Corridor (room #2). Fore is direction 0, so the Docking Bay’s zero-th column in the travel table is 2.

    We initialize the TT(room, direction) array by reading the map data from DATA statements. For convenience, we put the room names on the same lines in the DATA statements and read them into the RO$(room) array.

    120 DIM TT(6,4):DIM RO$(6)130 FOR I=1 TO 5140 FOR J=0 TO 3:READ TT(I,J):NEXT J150 READ RO$(I)160 NEXT I180 DATA 0,0,2,0,"HIBERNATION CHAMBER"190 DATA 0,4,3,1,"LOWER CORRIDOR"200 DATA 0,0,0,2,"PRIVATE AREA"210 DATA 2,5,0,0,"DOCKING BAY"220 DATA 4,0,0,0,"AIRLOCK"

    Olivia begins the game in the Hibernation Chamber, room 1. The PL variable stores her location. At the top of the game loop, we tell the player where they are, and which directions from the current room have exits—that is, are non-zero in the travel table.

    230 PL=1240 PRINT CHR$(13)+"YOU ARE IN THE "+RO$(PL)+"."250 PRINT "EXITS: ";260 FOR I=0 TO 3270 IF TT(PL,I)0 THEN PRINT CM$(I)+" ";280 NEXT I290 PRINT

    Now we can finish processing the command. With a valid direction command in the C variable, we can determine whether there is an exit from the player’s current location in that direction by consulting the travel table. If not, we inform the player. Otherwise, we move the player to that location, then return to the top of the game loop.

    380 IF TT(PL,C)0 THEN 410390 PRINT "YOU CAN'T GO THAT WAY."400 GOTO 240410 PL=TT(PL,C)420 GOTO 240

    That’s a complete albeit not very interesting game. It might be more interesting if there’s an object that the player can find to open the security door fore of the Lower Corridor. We might update the room description routine at the top of the game loop to announce whether the object is in the player’s current location. It might also describe the security door when the player is in the Lower Corridor, and whether it is open or closed. A new command could allow the player to pick up the object, when appropriate. When the player opens the security door, the game logic would update the travel table to allow passage between the Lower Corridor and what lies beyond.

    50 Years of Text Games, by Aaron Reed

    This isn’t MEGA65 specific but I can’t close this out without recommending 50 Years of Text Games by Aaron Reed, a historical deep dive on the genre and its many unusual twisty passages. Well researched and compellingly written, Reed originally published this as a serial newsletter, then crowdfunded a book version. The project raised over $640,000.

    The Kickstarter has ended, but there is a limited number of extra print copies available for pre-order. If you’re still reading this Digest, you’ll love Aaron’s book.

    The MEGA65 might be my favorite text adventure gaming platform. With the distraction-free 80-column display and quality mechanical keyboard, I can shut off the Internet and immerse myself in an interactive story. And the large amount of memory, fast disk access, and ability to store a giant library on an SD card mean I can play modern text games without the limitations of other microcomptuers.

    I hope you give at least a few of these games a try, and maybe write one of your own. Happy adventuring!



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • First off, thank you all so much for the outpouring of support for this Digest idea. I didn't expect to see so many of you subscribe to a newsletter sight unseen. I really hope it'll be an enjoyable use of your attention.

    And boy did we time this right, because we get to discuss big news in the first issue!

    Batch #2 is shipping soon

    MEGA's assembly and distribution partner Trenz Electronic has parts in hand for the next batch of 400 computers, and is scheduled to assemble and deliver them by the end of the 2022 calendar year. Soon there will be 800 MEGA65s in the hands of new owners, not counting the 100 Dev Kits.

    All batch #2 machines will ship with updated factory-installed firmware and system software, including fixes and improvements made since batch #1 shipped back in May. Batch #2 will include the printed User’s Guide from the first print run. If you receive a batch #2 machine, you'll want to download the most recent PDF as a supplement. I'll try to keep the Welcome Guide up to date as well.

    Trenz is planning these fulfillment batches based on the availability of parts, especially the Xilinx FPGA chips. The MEGA65 team has done a great job mitigating risk in the supply chain, with unusual pieces like the injection molded cases and floppy disk drives well stocked. (We were all surprised when the first batch was delayed due to a shortage of cardboard, of all things.) We can all look forward to continued fulfillment of pre-orders through next year.

    Help with testing for batch #2

    The MEGA65 community made a huge push to test the factory-installed firmware and system software for batch #1. We're doing it again for the batch #2 release candidate—and you can help!

    The closer you can get your MEGA65 to the final configuration, the better for testing. If you own a MEGA65, a Dev Kit, or a Nexys FPGA board, jump in the release-test forum on the Discord. Check out the release candidate verification home page with links to downloads and instructions for testing and reporting bugs. You can install the latest core in slot 1 of the core management utility, and prepare a new internal SD card with the latest system software and bundled disk images.

    If you're one of the lucky ones to have both a batch #1 MEGA65 and a JTAG programming interface, you can install the candidate core in the special "slot 0," which is how batch #2 machines will be configured. Overwriting slot 0 requires opening your case to flip a tiny switch, as well as running some fancy commands. We need slot 0 testers, so if this sounds like you, please give it a try. See the wiki page for instructions.

    If you don’t yet have a MEGA65, you can still help test the ROM using the Xemu emulator. You’ll need to use the C65 ROM diff files along with a copy of the original Commodore 65 ROM version 910828 (which you can find online or on the C64 Forever CD-ROM) to produce the mega65.rom file.

    Thanks to everyone who can help out!

    What's the latest firmware, anyway?

    The core team and contributors have been improving the MEGA65 firmware and system software (including the MEGA65 version of the Commodore 65 ROM code) continuously since batch #1 shipped. So what's considered the "latest" version, and should you upgrade?

    There are two major release packages for the system software: the stable release package, and the experimental release package.

    The stable release package contains the most recent set of software that has been through a testing phase, which today is the factory-installed set from batch #1. It includes MEGA65 core version 20220109.11,1586ad4 and the MEGA65 ROM version 920287. When we've completed verification of the batch #2 software set, that set will become the new stable release. You can download this from the MEGA65 R3 Release Package page on Filehost. (You'll need a Filehost account registered with your owner code to access it, because it contains the licensed ROM.) Stable releases have their own version number to represent the entire set of software, with the current release known as version 0.9.

    The experimental release package is the bleeding edge, built regularly from the latest changes committed to the source repo. As of this writing, the experimental package download contains core version 20220717.12-develo-3253c5d. Contributors do their best to keep everything in working order when they submit changes. For additional assurance that changes maintain backwards compatibility, they are held in this "experimental" state while we test them and put them through their paces. You can download the experimental release core and system software from the Experimental Release MEGA65 R3 page on Filehost.

    Unlike the stable package, the experimental release package does not contain the ROM. As of now, the latest ROM is 920377, and is available from the C65/MEGA65 Kernal ROM page on Filehost.

    The batch #2 verification build has its own download page and may be slightly newer than the experimental release during the test phase.

    Which release should I use?

    Which release you choose to install on your own MEGA65 is a matter of taste. Everyone is encouraged to install the latest stable release. For batch #1 owners, this just means that we'll throw an upgrade party when batch #2 is finalized. If you don't want to hassle with frequent upgrades of experimental releases, and the occasional downgrade when issues are discovered, stick with the stable release and watch for announcements. If you'd like to preview new features, get the latest bug fixes, and help test new contributions, consider installing the latest experimental release. I've had a good time keeping the latest experimental release on my MEGA65 all year, though I've also been paying close attention to bug reports.

    One of the coolest things about the MEGA65 is that it's easy to switch between multiple versions of these components. You can have multiple cores in flash memory, you can have multiple ROMs on the SD card, and you can easily switch between them when you boot the machine. This is not quite true for the auxiliary system software in those .m65 files on the SD card. If you find yourself switching between stable releases, you might want more than one SD card prepared with the appropriate files. The differences in the files between experimental releases tend to be minor enough to just use one SD card.

    As of right now, my personal recommendation is for batch #1 owners to proceed with upgrading to the experimental or batch #2 verification release set. Since batch #1 shipped, newer releases have fixed noticeable bugs and improved the overall quality of life for MEGA65 owners. You'll also be helping with the verification effort by upgrading now. When the batch #2 testing phase completes, that'll be a good time to install the new stable release as your default core (in slot 1) and default ROM (with filename mega65.rom).

    As anyone who has done software release management professionally can tell you, release verification is an expensive process. We’re gradually building out automated testing solutions to reduce the time between stable releases, though this is challenging when custom hardware is involved. I'm grateful to everyone who tests experimental releases. You make continuous improvement possible!

    For instructions on how to upgrade your MEGA65's firmware and system software, see the User's Guide included with the machine, as well as the Welcome Guide.

    Upcoming type-in zine, call for submissions

    ZeHa of Dr. Wuro Industries (known as ZeHa on the forums, drwuro on Discord) is producing Megazine, a printed zine of type-in BASIC programs for the MEGA65, and is calling for submissions. If you've always wanted to see one of your programs featured in magazines like Compute!'s Gazette, now is your big chance!

    Megazine is looking for BASIC programs with a focus on fun, such as games, animations, or demos. Keep it short, and keep it readable enough for beginner programmers to understand. (I remember doing a type-in as a kid and encountering the word FORK in the program and wondering what it did. It took me a moment to realize it was just a FOR statement and a variable named K, with the space removed.) Also please only submit unreleased programs.

    When the zine was originally announced, the submission deadline was set at September 30. This will probably be extended, though a new date has not yet been determined as of this writing. Check out the original forum announcement for submission details and updates.

    Character graphics made easy

    One of the easiest ways to get started with programming games on the MEGA65 is with character graphics. Your BASIC program plots colored letters and symbols on the screen, checks whether the joystick or fire button is pushed, and decides on new positions for player, enemy, and environment objects. Do that in a loop and you've got a game.

    Just like with the Commodore 64, you can replace the glyphs used for each letter or symbol with your own custom designs. And starting with ROM version 920347, MEGA65 BASIC makes this super easy!

    The CHARDEF command takes the character screen code whose glyph you want to replace, and eight numbers that describe the new 8x8 pixel image, one number for each row. Try this at the READY. prompt:

    CHARDEF 0,$0C,$1C,$18,$FF,$18,$3C,$66,$C3

    If you get a SYNTAX ERROR, double-check that you're using the latest version of the ROM. (ROM 920347 came after the batch #1 v0.9 release.)

    Now type the "at" symbol (@) a few times.

    The first 0 is the screen code for the "at" symbol. Screen codes 1 through 26 are the letters A through Z. See this table for all the screen codes. CHARDEF supports the first 256 screen codes in the uppercase PETSCII mode. (This will be updated to support all 512 codes, uppercase and lowercase PETSCII, in an upcoming release of the ROM.)

    Each of the numbers following the screen code describes a row of the character glyph.

    MEGA65 BASIC's built-in support for hexadecimal notation comes in really handy here, because each hexadecimal digit describes exactly four pixels.

    Many of the games I wrote as a kid featured this classic "brick wall" glyph. Look at the diagram below. What hexadecimal numbers describe this pattern? What CHARDEF command would change the letter A to appear as a brick wall?

    CHARDEF __, $__, $__, $__, $__, $__, $__, $__, $__

    To restore the glyphs back to the MEGA65 PETSCII font, use the FONT command, with the letter C as an argument:

    FONT C

    There's also a FONT A, which replaces some lowercase glyphs with ASCII punctuation not available in PETSCII, and FONT B which resembles a DOS-like font. Try them! (Remember you can toggle between uppercase and lowercase modes with Mega+Shift.)

    With CHARDEF in your BASIC programs, you're well on your way to making some fun games. Be sure to submit yours to Megazine!

    That'll do it for this month. Best of luck to all the testers, and congrats to everyone about to receive a new MEGA65!



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe
  • The party was already in full swing when I got my MEGA65 back in March of 2022. I got mine as part of the first shipment of production units, the ones with the sweet injection molded cases, but 100 others already had the acrylic-encased Dev Kit beta units from the previous year. Many more were eagerly running the MEGA65 core on Nexys FPGA boards or testing the waters with the Xemu emulator. By the time batch #1 shipped, it included multiple disk images packed with demonstrations and games from an already thriving community.

    A flurry of essential firmware and ROM updates followed the March delivery, and it was important to keep up with developments. I was lucky to have just started a sabbatical from my software job and had the time to read through daily discussions on the MEGA65 Discord. I knew other newly minted MEGA65 owners that didn't have that kind of time and were struggling to dig into their new machines. For them and others, I wrote the MEGA65 Welcome Guide, a supplement to the already excellent documentation that tried to synthesize information about recent changes and practical advice, stuff too temporary for the official manual but still useful to the first 400 owners.

    And the new stuff keeps coming. I've been keeping track of all of the amazing things this growing community has been doing with the MEGA65 all year, from boxed retail games to music demos to tools and libraries to YouTube videos and tutorials. There was so much being posted, I built the @MEGA65Files Twitter bot as a way for people to be notified of new software and articles posted to the Filehost repository. As of this writing, the Filehost has nearly 200 downloadable files and over 60 articles.

    By the end of 2022, there will be 800 MEGA65s in the wild—not counting the 100 Dev Kits—and the pace of development is likely to increase. With more people and more activity, it won’t be sufficient to assume that everyone is reading the Discord chat. I think it's time for a newsletter.

    Whether you already have a MEGA65, have preordered one from a future batch, are jumping in with a Nexys board or the emulator, or are just curious about the MEGA65 project and its community, this Digest will keep you up to date. Firmware updates, shipping status, new software releases, game jams, tips and tricks, and maybe the occasional interview. Things you can do with your MEGA65 right now. It’ll be short, interactive, and free.

    There are two things you can do to help:

    * Subscribe. You can get the Digest by email, RSS reader, or the Substack app.

    * Tell people about it. We want everyone who is interested in the project to know there's a newsletter, so they don't miss out.

    Look for the first post in mid-September.

    Thanks all! GO 65!

    Thanks for reading Dan’s MEGA65 Digest! Subscribe for free to receive new posts.



    Get full access to Dan’s MEGA65 Digest at m65digest.substack.com/subscribe