Beauty of Code

When I first sat down in front of a Commodore 64 again — decades after the 8-bit wars had ended — it felt a bit like uncovering an ancient map.
Not just any map, but one drawn with memory addresses, sprites, and sound waves.

A blueprint for magic.

This time, though, I wasn’t just a kid mashing keys to load LOAD"*",8,1.
I was an adventurer. A creator.
And the code you’re about to see?
It’s not just a list of instructions — it’s the story of a game being born.


Chapter 1: The Memory Map

Every epic needs a world.
On the Commodore 64, that world is the memory.

The game begins with the Zero Page — the bustling harbor where the CPU keeps its most precious cargo for fast access.
Above it, the Screen Memory at $0400 is like the marketplace, where characters chatter and colors flash.

Then, towering high at $C000, we find the Upper RAM Area, a sort of castle stronghold where scores and secret variables are tucked safely away.

And overlooking it all, like a mighty sorcerer, stands the VIC-II chip at $D000 — controlling the sprites, the colors, and the dance of pixels across the screen.

Memory wasn’t just storage.
It was territory.
And every address we defined — from SPRITE0_X to SIDV1_FRQL — was another landmark on our growing map.


Chapter 2: Sprites Awake

With the world prepared, it was time to breathe life into our heroes: the sprites.

Imagine the screen as a blank theater stage.
The paddles (our players), the ball, and the scoreboard sprites were summoned by setting up their pointers:

lda #$80
sta SPRITE0_PTR
lda #$20
sta SPRITE0_X
...

The paddles lined up like eager actors, rehearsing their moves.
The ball, small but full of mischief, waited center stage.
And somewhere above, the scoreboard began blinking into existence, ready to tally the victories.

Each sprite wasn’t just a graphic.
It was a character, with a position, a color, and even a personality.
The paddles moved swiftly and surely.
The ball darted unpredictably.

This was more than data.
It was the heartbeat of the game.


Chapter 3: The Battle of Joysticks

The players entered through the gates of CIA_PORTA and CIA_PORTB — the joysticks.
They spoke in simple signals:

  • Pressed down? AND #$02
  • Pressed up? AND #$01

Each command translated directly into motion, the players pushing their paddles up and down the battlefield.

But in true gladiatorial style, there was a limit.
Move too high, and the sprite would be clamped at $32.
Too low, and $CF would stop you.

Balance was enforced by code and gravity alike.


Chapter 4: Game Loop, the Pulse of Life

At the heart of it all, a simple but relentless drumbeat:

GAME_LOOP:  
    jsr PLAYER_MOV  
    jsr BALL_MOV  
    jsr SLOWDOWN  
    jsr GOAL_CHECK  
    jsr SCORE_REND  
    jsr WIN_CHECK  
    jsr COLL_CHECK  
    jmp GAME_LOOP

The main loop.
A tireless conductor, orchestrating the dance of the paddles, the furious chase of the ball, the cries of victory or defeat.

Every jump back to GAME_LOOP was another heartbeat.
Another second of gameplay, woven from thousands of tiny electrical impulses across the 6510 CPU.

And if something went wrong — a goal scored, a collision detected — the code responded like a living creature.


Chapter 5: Sound, Light, and Glory

Of course, no battle is complete without music.

Whenever a collision happened or a point was scored, a triumphant sound erupted from the legendary SID chip:

SOUND:  
    sty SIDV1_FRQH      
    lda #$20             
    sta SIDV1_FRQL       
    lda #$11            
    sta SIDV1_CTRL

The SID didn’t just beep.
It roared.
It cried.
It sang the song of battle.

Meanwhile, the border colors blinked furiously during resets, a visual fireworks display controlled by careful writes to BORDER_COL and BGND_COL.

The game wasn’t just seen.
It was felt.


Chapter 6: Victory (and Reset)

Every goal pushed the players toward their destiny.
Score 10 points, and — like a cycle of life and death — the game didn’t just end.

It restarted.

The paddles lined up again.
The ball floated gently to its center position.
A new battle was born.

Because in the world of the Commodore 64, the story never truly ended.
It simply looped forever.


💬 Epilogue: Why This Matters

You might look at this mass of labels, .byte declarations, and bitwise operations and think:
“This is too low-level. Too hard.”

But when you see it with the eyes of a storyteller, something else appears:
A world built from nothing.
A symphony played by electrons.
A game where every line of code is another verse in a timeless epic.

On a machine from 1982, we built a living universe — one memory address at a time.

And the beauty is, you can too.

Eager to play now?

Try it on the emulator or on a real C64, here is the assembled code.

And here is the full source code, 500 lines of Assembler Code.


<
Previous Post
👾 RBXE - A Pixel Game Engine with Voxel Power
>
Next Post
👾 Chess on the Vectrex: Multiplatform C Development with Raspberry Pi Pico, and Raspberry Pi