A Rorschach Test on Fire
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 $04
POKE $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 than those farther away.
(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,0
20 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 79
120 FOR R=0 TO 49
130 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.06
150 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)^2
x^2 + ixy + ixy + (iy)^2
x^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+X
180 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<=2 AND N<80 THEN 170
After iteration is complete, we determine the color of the screen location based on the number of iterations. If we hit the maximum, we conclude that the point is in the Mandelbrot set, so the square should be black. Otherwise it is some other color based on the number of iterations. With a maximum iteration count of 80, one way to convert this to a color value between 0 and 15 is to divide it by 5.
220 C=0:IF N=80 THEN 240
230 C=N/5+1
240 C@&(K,R)=C
250 NEXT R
260 NEXT K
That’s it! RUN
this program and watch it draw a pattern that roughly resembles the Mandelbrot Set image. 80x50 is a low resolution, but it’s close to the first picture of the Mandelbrot Set, published by Robert W. Brooks and Peter Matelski in 1978.
Mandelbrot Set, you’re a Rorschach Test on fire
You’re a day-glo pterodactyl
You’re a heart-shaped box of springs and wire
You’re one badass fucking fractal
And you’re just in time to save the day
Sweeping all our fears away
You can change the world in a tiny way
— “Mandelbrot Set,” by Jonathan Coulton
Peace and love,
— Dan