Building a Better ZX81 Digital Rain using Z80 Assembler
A remake of my original Digital Rain, but with a few new twists. The biggest being color.
My original plan was to create an z80 assembler version of Moon Lander. But with the trailer release for the next Matrix movie, I found myself revisiting another program. Built entirely in machine language, Z80 Digital Rain expands on my previous version with a splash of color. Let’s dive deeper.
Revisiting and revising.
This updated version of digital rain—you can learn more about the 2018 version here—has two things going for it. First off, it is much faster which improves the overall look of the rain. Second, I added some color!
Because it is faster, I found adding inverted characters made the rain look more interesting. The improved speed also removed the loop you could see it making over the rain drops. In fact, it was so fast that I had to add a delay routine to slow things down a bit.
Given the opportunity to enhance things a bit, Imexpanded the display to use 24 rows. I use a different display routine that doesn’t rely on the ROM print. As such, I wasn’t limited to using the default 22 display lines. Instead, I could reach into the two input lines. This filled the display better and I think it is nice to see the full display used and not just a small part of it.
Although not original part of my program, I saw another version of Digital Rain that varied the drop speed. I wondered how hard that would be. After tweaking the program a bit, I found it was’t that hard to add in. It also allowed me to speed things up a bit. As such, I lowered the default delay and let the drops decide how fast, or slow, they will display.
The biggest change was to update Digital Rain to use color using the Chroma hardware expansion. Previously, I had figured out how to use it working on Gem Quest. This let me create a version much closer to what you see in the Matrix. To add to the effect, the screen is turned black, the letters are green, and the lead drop is white. I dropped the inverted character when in color, using Cyan instead.
Z80 Digital Rain - Screen Shot 2021-09-17 at 11.58.59 PM by Steven Reid, on Flickr
Overall, I love the new look. It is fast, colorful, and works.
Digging into the code.
For the z80 version of digital rain, I started with my original BASIC program. This time, though, I really used it as a guide. It became the pseudocode on which I built this new version. Although it has a different flow from the first, Z80 Digital Rain use much the same logic. The base routines didn’t take much time to create. I had most of the code done in a couple of hours. I even borrowed some routines from Gem Quest to speed up development. Yet, something wasn’t right.
The first time I ran the program, the screen was blank. Seemed my compares were off. I started to comment out the code, creating simplified version of each stage to ensure it was working. I could get the rain to work, drawing a screen of random symbols. I even got the code to change characters working. But removing the drops was a bit of a problem.
With things not quite working, what followed were a few days of varying emotions. From frustration to panic. I was struggling to understand what I did wrong and why the display wasn't working. The code compiled, but just didn’t work.
My mind was tricking me.
Part of the problem was I was using the same one array trick I had used before. That is, the rain drops were positive when adding characters. The same column was negative if I was removing them. I kept thinking the problem was the way I was handling negative numbers. To that end, I keep trying different compares such as JP M
or JP P
to verify the sign.
Although everything seemed to behave right, it still wasn’t working. I ended up giving up in frustration and headed to bed. The next day, I took a different approach. I wrote a little test program to make sure I was doing the math right. That program worked flawlessly. Yet, for some reason, digital rain was still failing to function.
Pushing my frustration aside, I started to walk through the code in pieces. And then it hit me. I was testing for a carry at the end of my code. The problem, though, is that negative numbers would be below the row compare I was doing. I dawned on me that I was bypassing the very thing I was trying to test. Realizing my mistake, I swapped the compare to use the zero flag instead. Suddenly everything started to work again.
Fun with color.
With the program now working, I could focus on something fun: adding in color. I really wanted my original code to be green on black. At the time, I didn’t have many alternatives. Seeing the use of Chroma hardware in other videos, I had dabbled into the code for it with Gem Quest. That worked very well and give me a base to use it with digital rain.
Around this time, I also started to refactor the code. Sticking to the BASIC code, I had used the ZX81’s ROM printing routines to display things. Although those work, they are a bit slow and tend to use registers I wanted to manage. Thus, I converted to using direct screen manipulations. This made it easier to manage the position. As an added benefit, it was very easy to adjust color in Chroma.
To be honest, I think there is now more code in the program to deal with all the color changes than there is in the original digital rain. I had to do a few things to set the appropriate color as the drop fell. There is even a special section to deal with the white drop at the bottom of the screen.
I ended up building a little demo video for it. This lets anyone enjoy the program, even if they don't have an emulator. I did jazz it up with some ambient music and such.
Packaging things up.
With that done, it was time to package it up and share. The final program is actually quite fun. I did end up optimizing the code into modules. Because it is so much faster, I added a delay routine to make sure it wasn’t too fast. The effects were almost a blur. I shared a video of z80 Digital Rain with a ZX81 group I’m part of and received great feedback. It was there that I got the idea to add the variable speed rain drops. It was something I’d mentioned before, but had forgotten about. I had dropped it from my BASIC / MCODER II version because it was too slow.
I did have some other ideas I thought about trying. One was to add in a dark green drop as well as a bright green one. This would have better matched the original matrix, but I ended up scrapping the idea. I also received a suggestion to rotate the letters instead of leaving them static where they first land. This would be a bigger challenge, although I don’t think impossible.
The other thought, which I mentioned in my original version, was to have the digital rain end at different levels. Again, that wouldn’t be too difficult. I'd need to use another array to capture the end drop. But I think the program looks pretty good in its current state. Anything else is just fluff at this point.
So there you have it. I now have my pure assembler version of digital rain. It is fast, and green. Just as I always wanted it to look.