Atari 800 Winter Solstice Celebration Demo 2022

Every December, I try to do a little winter demo to practice one of the 8bitworkshop platforms. This year I chose the Atari 800 to test the new native TypeScript emulator in 8bitworkshop. You can see the emulated demo here.

I revisited my "Happy 2020" demo from Bally Astrocade, which simulates snowfall. It uses pixel-level collision to simulate each falling particle, which creates nice little piles of snow and rippling particles on the sides of obstacles.

Background

Atari ANTIC Mode $F uses the GTIA chip to add additional modes beyond what the original CTIA chip provides. I used GTIA Mode 10, which is 80 x 192 pixels with nine different colors.

I changed the snowfall algorithm so that snow only accumulates when it collides with existing snow. This diagram reserves one of the palette inputs for snow, so we can detect snow against the background.

I first used DiffusionBee, a stable broadcast art application, to create cute little villages. This one turned out the best:

I painted a white streak on the roofs of the buildings and the ground, making sure the snow hits it. I then ran it through Dithertron to convert it to Atari 10 mode.

Particle simulation

In the original demo, the falling particles follow these rules every frame:

Move the particle down one pixel. If there's an empty pixel, we're done for now.

Alternatively, if there is an empty pixel to the left or right, move it left or right.

If not, set the background pixel to the color of snow and recycle the particle to the top of the screen where it will fall somewhere else.

In the new demo, we're changing them like this:

Instead of "empty pixel", we will only collide when we find a "snow pixel". This means that the particles will pass over the background image until they hit the snow. Using XOR ensures that we won't damage the background.

When a particle needs to move left or right, there will be a small probability that it will stop instead. Over time, this will create piles on top of sloped roofs, whereas the old algorithm would never pile snow on a slope greater than 45 degrees.

The music

I adapted the Atari vector game music routine from Making 8-Bit Arcade Games in C. This sets the POKEY to 16-bit mode for higher frequency accuracy, so you can hit notes without the weird tuning problems like the Atari 2600.

Arcade games have two POKEYs, and a stock Atari 800 only has one, so we only get two voices with this scheme.

To play at a steady beat, we need to call the music_update routine at a steady beat. The CC65 library sets up a VBI (virgin vertical interrupt) that runs at 60Hz, so we can use that.

The problem with CC65 and interrupts is that CC65 code uses registers and a stack in RAM, which can get cluttered if the interrupt fires at the wrong time. CC65 provides a special set_irq() function that links C routines to the interrupt chain, but preserves global registers and uses a second stack for the interrupt.

// set the interrupt routine with the stack to $7000 - 70 FF set_irq(music_update, (void*)0x7000, 0x100); CC65 config file

For this demo, we will produce a 32KB ROM cartridge, which occupies addresses $8000-$BFFF. This requires us to hook a custom .cfg file, like this (inside the main .c file):

//#resource "atari-tgi.cfg" #define CFGFILE atari-tgi.cfg

Creating a 32 KB cartridge is easy, there is only one variable to change:

__CARTSIZE__: type=low, value=$4000; TG...

Atari 800 Winter Solstice Celebration Demo 2022

Every December, I try to do a little winter demo to practice one of the 8bitworkshop platforms. This year I chose the Atari 800 to test the new native TypeScript emulator in 8bitworkshop. You can see the emulated demo here.

I revisited my "Happy 2020" demo from Bally Astrocade, which simulates snowfall. It uses pixel-level collision to simulate each falling particle, which creates nice little piles of snow and rippling particles on the sides of obstacles.

Background

Atari ANTIC Mode $F uses the GTIA chip to add additional modes beyond what the original CTIA chip provides. I used GTIA Mode 10, which is 80 x 192 pixels with nine different colors.

I changed the snowfall algorithm so that snow only accumulates when it collides with existing snow. This diagram reserves one of the palette inputs for snow, so we can detect snow against the background.

I first used DiffusionBee, a stable broadcast art application, to create cute little villages. This one turned out the best:

I painted a white streak on the roofs of the buildings and the ground, making sure the snow hits it. I then ran it through Dithertron to convert it to Atari 10 mode.

Particle simulation

In the original demo, the falling particles follow these rules every frame:

Move the particle down one pixel. If there's an empty pixel, we're done for now.

Alternatively, if there is an empty pixel to the left or right, move it left or right.

If not, set the background pixel to the color of snow and recycle the particle to the top of the screen where it will fall somewhere else.

In the new demo, we're changing them like this:

Instead of "empty pixel", we will only collide when we find a "snow pixel". This means that the particles will pass over the background image until they hit the snow. Using XOR ensures that we won't damage the background.

When a particle needs to move left or right, there will be a small probability that it will stop instead. Over time, this will create piles on top of sloped roofs, whereas the old algorithm would never pile snow on a slope greater than 45 degrees.

The music

I adapted the Atari vector game music routine from Making 8-Bit Arcade Games in C. This sets the POKEY to 16-bit mode for higher frequency accuracy, so you can hit notes without the weird tuning problems like the Atari 2600.

Arcade games have two POKEYs, and a stock Atari 800 only has one, so we only get two voices with this scheme.

To play at a steady beat, we need to call the music_update routine at a steady beat. The CC65 library sets up a VBI (virgin vertical interrupt) that runs at 60Hz, so we can use that.

The problem with CC65 and interrupts is that CC65 code uses registers and a stack in RAM, which can get cluttered if the interrupt fires at the wrong time. CC65 provides a special set_irq() function that links C routines to the interrupt chain, but preserves global registers and uses a second stack for the interrupt.

// set the interrupt routine with the stack to $7000 - 70 FF set_irq(music_update, (void*)0x7000, 0x100); CC65 config file

For this demo, we will produce a 32KB ROM cartridge, which occupies addresses $8000-$BFFF. This requires us to hook a custom .cfg file, like this (inside the main .c file):

//#resource "atari-tgi.cfg" #define CFGFILE atari-tgi.cfg

Creating a 32 KB cartridge is easy, there is only one variable to change:

__CARTSIZE__: type=low, value=$4000; TG...

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow