• Skip to main content
  • Skip to header right navigation
  • Skip to site footer
Retro Game Coders

Retro Game Coders

Retro computer/console game + dev community

  • About
    • Retro Computer Collection
    • Contact
  • Blog
  • Retro Resources
    • Retro Gaming Timeline
    • Online Retro IDE
    • Retro Pixel Art Editor
    • Dungeon Loom Map Editor
    • 6502 Programmer’s Reference
    • Emulators
      • Acorn Electron
      • Amstrad CPC Emulator
      • Online BBC Micro Emulator
      • Commodore PET Emulator
      • Browser C64 Emulator
      • DOSBox/DOS PC emulator
      • Tandy CoCo/Dragon
    • Best Retro YouTube Channels
    • New Retro Books
    • Raspberry Pi Amiga Emulation
    • MiSTer FPGA Tutorial
    • BMC64 C64 Pi
  • Community

Home » Retro Game Coders Blog » Programming

C64 Ultimate – 16 Colours on Every Hires Pixel (and Atari ST Pictures)

Atari ST pictures on C64U (1)

It turns out, the Commodore 64 Ultimate has some surprising graphical abilities, you just need to know the tricks!

In my C64 Ultimate review my big gripe was that ZX Spectrum Next games get to use all of the Next’s enhanced abilities, while the C64U has no comparable graphics modes for developers to use.

Unlike the Next, and ironically the official C64 successor, the C65, the C64U can’t do 256 colours. However, it turns out that it is possible using coding tricks to give every hires pixel any of the 16 palette colours.

Not only that, with the forthcoming Ultimate firmware, we will be able to do even more!

This week I went down a rabbit hole, got a full 320×200 high resolution 16-colour picture with none of the usual vic chip limitations running on my real C64U, then emerged with a video showing a slideshow of Atari ST pictures in their own original ST palettes.

video showing a slideshow of Atari ST pictures in their own original ST palettes

Join Retro Game Coders Community
Join the Retro Game Coders Community

What is this witchcraft?

Credit where it is due. None of these tricks are my invention. Martin Piper worked out the “Mega Multicolour Mode” and Brandon Staggs built it into his Mosaicus paint program. My efforts were around re-implementing it to work in my slideshow code, plus getting the full hires version with text on top to line up correctly.

The Mosaicus $D020 viewer showing my own 320x200 picture on the C64 Ultimate
The Mosaicus $D020 viewer showing my own 320×200 picture on the C64 Ultimate

On a stock C64 the VIC-II constrains colours to the limitations of a display made up of 8×8 character cells. Hires bitmap mode allows just 2 colours per cell, and multicolour offers 4 per cell but at the cost of half the horizontal resolution, and only one of the colours can be individually selected from the palette as the others are shared.

What makes an enhanced display possible on the C64U is its ability to run at much higher clock speeds.

The C64U provides a Turbo register located at $D031. Writing $8F to this register sets the computer to a blistering 64 MHz. Turbo Control must be turned on in the settings, of course.

    lda #$8f
    sta $d031       ; 64 MHz, badline timing off
    ...
    lda #$00
    sta $d031       ; back to 1 MHz before handing back to BASIC

You can now follow the tutorials and edit the code right in your web browser with the Online Retro IDE

– No downloads, configuration, etc necessary, and it is free!

Racing the Beam

Using this higher clock speed we can write to a colour register at the exact moment the computer is about to change the next pixel, aka “racing the beam”. The two techniques differ on if we set the background colour ($D021) or border colour ($D020).

Racing the beam

In the former, Martin’s technique, we can overlay text on top of the bitmap, but the latter is more simple to implement (eg. doesn’t have to deal with “badlines” where the CPU pauses to read data) and can “overscan” making the screen somewhat bigger.

A full screen 320×200 picture needs 32000 bytes. Brandon’s version (384×272) is around 51K. That’s why we need to use the REU for anything more than displaying a single picture, for example in a game for swapping screens in for title, instructions and game over.

The pixel pair loop

The VIC ignores the top 4 bits of $D020 and $D021, so one byte can contain the data for two pixels.

A 256-byte table (mx_hi) stores each byte shifted down by 4 bits, so the right-hand pixel is one indexed load away.

    ldx picture,y       ; 4  two pixels in one byte
    stx $d021           ; 4  left pixel (top nybble ignored)
    lda mx_hi,x         ; 4  same byte >> 4
    sta $d021           ; 4  right pixel

That needs 16 cycles, so every fourth pair loads from zero page instead, saving one cycle (ldx $b0 takes 3 cycles instead of 4), so each character comes out at exactly 63 cycles.

The bytes for the next zero page pairs are copied in before each line starts, 40 per line.

Even with the code unrolled and running at 64 MHz, the CPU is busy the whole time that the picture is being drawn and only frees up in the borders.

💬 Questions or comments? Head over to the community to discuss!

Badlines Bug

With the screen on, every 8th line is a “badline” where the VIC fetches the next row of characters and stalls the CPU. Even with “badline timing” off at 64 MHz in turbo, it steals 40 cycles.

The outcome was my picture sheared to the right, about 5 pixels each badline.

Notches every 8 lines on the tower edges, the badline rows pushed right
Notches every 8 lines on the tower edges, the badline rows pushed right

Shortening the delay before each badline instead moved the error to the left-hand end.

Same rows now pushed left at their start
Same rows now pushed left at their start

The fix was to treat badline rows differently, grabbing their data from zero page which saves a cycle:

    ldx picture,y       ; 4  pair 0
    stx $d021
    lda mx_hi,x
    sta $d021
    ldx $b0             ; 3  pair 1, from zero page
    stx $d021
    lda mx_hi,x
    sta $d021
    ldx picture+256,y   ; 4  pair 2
    stx $d021
    lda mx_hi,x
    sta $d021
    ldx $b1             ; 3  pair 3, from zero page
    stx $d021
    lda mx_hi,x
    sta $d021           ; 62 cycles, +1 stolen = 63

This was inspired by Martin Piper’s RenderMegaLineBad which does the same thing for his 160-wide version.

Rendering text over the picture

For my games I use text for things like help text, high scores, heads up display, etc, so I lean toward Martin’s technique. Normal characters draw the usual way, in their colour RAM specified colour over the top of the bitmap. Reverse characters are the fun one, the letter shapes become holes and the picture shows through them. This could be a nice effect for a demo.

Full hires, 16 colours on any pixel, text on top
Full hires, 16 colours on any pixel, text on top

Changing the C64 Ultimate palette

So far we have only addressed avoiding the character block colour constraints, how did I switch the C64U to use the original Atari ST colour palettes in the slideshow?

It turns out, the C64U has the ability to select a user-defined palette. I imagine this was originally required due to PAL/NTSC etc and VIC II version differences.

In Ultimate 64 firmware 3.15, Gideon added UCI commands to set the palette from code (target $04, command $52, then 48 bytes of RGB).

Unfortunately, the latest (official) C64U firmware 1.1.0 answers with 21,UNKNOWN COMMAND, so the code-side palette commands haven’t reached the C64U … yet.

What does work today is the Palette Definition setting. It accepts a VICE palette file and applies it, no reset needed.

The 16 colour bars after setting a grey ramp palette
The 16 colour bars after setting a grey ramp palette

A .vpl file is plain text, one colour per line, red green blue in hex then a dither value:

# grey ramp
00 00 00 0
11 11 11 0
22 22 22 0
...
FF FF FF 0

For my slideshow I send the palette for each picture and set it through the REST API:

curl -X PUT -H "X-Password: $C64U_PASSWORD" \
  "http://192.168.0.64/v1/configs/U64%20Specific%20Settings/Palette%20Definition?value=/Temp/grey.vpl"

Therefore at least for now my full PRG release needs to wait for the updated firmware with the 3.15 commands.

Commodore 64 Ultimate > Atari ST

I love the Atari ST. It was “our” (my brother’s) third computer, and my first with a disk drive. We got it because that is what people locally owned, due to it being a lot less expensive than the Amiga. Being less expensive meant features were sacrificed, and that was a lot of fancy stuff like the Amiga’s blitter chip and better graphics.

Atari ST games usually ran at 320×200 resolution, displaying 16 colours from a palette of 512 (bumped up to 4096 on the STE). You can see why my next thought was back to my ST days, with the new technique and colour palette control, ST pictures translate to the C64U pixel for pixel.

FormatHeaderPalettePixels
Degas .PI12 bytes resolution16 words at offset 232000 bytes at offset 34
NEOchrome .NEO128 bytes16 words at offset 432000 bytes at offset 128

ST colours are 3 bits per channel, $0RGB in a 16-bit word. The pixels are 4 interleaved bitplanes: each group of 16 pixels is 4 words, one per plane, and a pixel’s colour is one bit from each.

for y in range(200):
    for group in range(20):
        at = y * 160 + group * 8
        planes = [word(pix, at + 2 * p) for p in range(4)]
        for bit in range(15, -1, -1):
            colour = sum(((planes[p] >> bit) & 1) << p for p in range(4))

In many ways the C64U is better specced as a games machine than the Atari ST, at least comparing it to the popular 520STFM model that we had rather than, say, the Falcon:

  • Using turbo mode it is ~8x faster, though we lose some of the benefit by still being 8-bit versus the ST 16-bit 68000
  • Much as I loved the YM2149 music on the ST, the SID is considered overall a better sound chip, and the C64U can run multiple simultaneously. The C64U can also play mod-style music.
  • While the C64U can only address 64KB at a time, having up to 16MB of REU data storage beats loading from disk.
  • It amazes me that the C64 had hardware sprites but the ST had none. The C64U has access to 16.7 million colours to choose from, versus the original ST limit of 512.
  • Finally, the C64U has built-in networking allowing it to connect to the internet over WiFi.

My first test was a made-up sunset in ST colours, none of which are in the C64 palette.

A synthetic Degas picture in its own ST palette on the C64U
A synthetic Degas picture in its own ST palette on the C64U

Then a classic, the Tutankhamun picture from the TEX slideshow, “a little bit improved by ES”, straight from the original NEOchrome file and famously the “face” of DPaint!

Tutankhamun from the Atari ST TEX slideshow, in its own palette on a C64 Ultimate
Tutankhamun from the Atari ST TEX slideshow, in its own palette on a C64 Ultimate

What next?

What I would really like is for Commodore to implement a real enhanced mode on the C64U core as the Next team have done. There shouldn’t be need for these kinds of tricks, in fact you should be able to have 256 colour sprites from within BASIC.

That said, this is better than the stock C64, so our C64 games can be enhanced for, or developed specifically for the Commodore 64 Ultimate utilizing the remaining cycles of running at 64 MHz, the REU, the stereo SID sound, and more.

I already have a software sprite running under this new technique so I am thinking the obvious move is an enhanced version of my Cross-Platform C Dungeon with better graphics for the platforms that are capable, after all it seems confirmed that I can use the same graphics in the Atari ST and C64U versions at the very least!

Credits

Martin Piper for Mega Multicolour Mode: source and video.

Brandon Staggs for Mosaicus and the viewer code (MIT licence), and for answering my questions on Facebook.

xahmol’s ultimate-uci-oscar64 library, which is where I found the palette command bytes.

The 1541 Ultimate documentation for the UCI control target.

Avril Harrison, who drew the original Tutankhamun for Deluxe Paint on the Amiga, and TEX and ES for the Atari ST version.

Category: ProgrammingTag: 6502 assembler, Atari ST, Commodore 64 (C64), Retro C/C++ Programming
Previous Post:Progress and Levels in the C64 BASIC Dungeon CrawlerC64 BASIC Dungeon Crawler: Stairs, Levels and Levelling Up (Part 11)

Retro Game Coders

Retro computer/console game + dev programming community by Chris Garrett

  • Bluesky
  • Threads
  • Facebook
  • Instagram
  • YouTube
  • Mastodon

Maker Hacks ・ D6Combat・chrisg.com

© Copyright 2026 Chris Garrett

Privacy ﹒ Terms of Service

Return to top