The Commander x16 is a FPGA enhanced
recreation of the C64, adding high resolution graphics, Tilemap
support and hardware sprites it gives the 6502 programmer the
opportunity to develop for a more modern system with the familiarity
of the C64. The commander X16 is still under construction - the developers have a facebook group here |
![]() |
![]() |
![]() |
|
![]() |
Links
New Ports
The 'Vera' Graphics
Address | Name | Bits | Details |
$9F20 | VERA_ADDR_HI | IIIIHHHH | 20 Bit address I=Increment |
$9F21 | VERA_ADDR_MID | MMMMMMMM | 20 Bit address |
$9F22 | VERA_ADDR_LO | LLLLLLLL | 20 Bit address |
$9F23 | VERA_DATA1 | DDDDDDDD | Data Port 1 |
$9F24 | VERA_DATA2 | DDDDDDDD | Data Port 2 |
$9F25 | VERA_CTRL | R------A | R=Reset A=Address (port 1 / 2) |
$9F26 | VERA_IEN | -----SLV | Interrupt enable - S=Sprite L=Line V=Vsync |
$9F27 | VERA_ISR | -----SLV | Interrupt Occurred - S=Sprite L=Line V=Vsync |
VRAM
To access this data - write an address to $9F20-$9F22, then read or write
with port $9F23
Group | Address | range | Description | |
Screen Ram | $00000 | $1FFFF | Video RAM | |
$20000 | $207FF | PETSCII character ROM (upper-case) | ||
$20800 | $20FFF | PETSCII character ROM (lower-case) | ||
L1 | $40000 | L1_CTRL0 | MMM----E | M=Mode 7=8bpp bmp / E=Enable |
L1 | $40001 | L1_CTRL1 | --HWhhww | H=tile Height / W=tile Width / m=map height / w=map width |
L1 | $40002 | L1_MAP_BASE_L | LLLLLLLL | Map Base (9:2) |
L1 | $40003 | L1_MAP_BASE_H | HHHHHHHH | Map Base (17:10) |
L1 | $40004 | L1_TILE_BASE_L | LLLLLLLL | Tile Base (9:2) |
L1 | $40005 | L1_TILE_BASE_H | HHHHHHHH | Tile Base (17:10) |
L1 | $40006 | L1_HSCROLL_L | LLLLLLLL | Hscroll (7:0) |
L1 | $40007 | L1_HSCROLL_H | ----HHHH | Vscroll (11:8) |
Alternate | L1_BM_PAL_OFFS | ----BBBB | In mode 567 Bmp palette offset | |
L1 | $40008 | L1_VSCROLL_L | LLLLLLLL | Hscroll (7:0) |
L1 | $40009 | L1_VSCROLL_H | ----HHHH | Vscroll (11:8) |
L1 | $4000A | $4000F | Layer 1 registers | |
L2 | $40010 | L2_CTRL0 | MMM----E | (M=Mode E=Enable) |
L2 | $40011 | L2_CTRL1 | --HWhhww | H=tile Height / W=tile Width / m=map height / w=map width |
L2 | $40012 | L2_MAP_BASE_L | LLLLLLLL | Map Base (9:2) |
L2 | $40013 | L2_MAP_BASE_H | HHHHHHHH | Map Base (17:10) |
L2 | $40014 | L2_TILE_BASE_L | LLLLLLLL | Tile Base (9:2) |
L2 | $40015 | L2_TILE_BASE_H | HHHHHHHH | Tile Base (17:10) |
L2 | $40016 | L2_HSCROLL_L | LLLLLLLL | Hscroll (7:0) |
L2 | $40017 | L2_HSCROLL_H | ----HHHH | Vscroll (11:8) |
Alternate | L2_BM_PAL_OFFS | ----BBBB | In mode 567 Bmp palette offset | |
L2 | $40018 | L2_VSCROLL_L | LLLLLLLL | Hscroll (7:0) |
L2 | $40019 | L2_VSCROLL_H | ----HHHH | Vscroll (11:8) |
L2 | $4001A | $4001F | Layer 2 registers | |
SprCom | $40020 | SPR_CTRL | -------E | E=Enable |
SprCom | $40021 | SPR_COLLISION | ----CCCC | C=Collision Mask |
SprCom | $40022 | $4002F | Sprite control registers | |
DspCom | $40040 | DC_VIDEO | F----COO | F=current field (RO) C=Chroma disable O=Out mode (1=vga) |
DspCom | $40041 | DC_HSCALE | HHHHHHHH | 128=Normal 64=2x |
DspCom | $40042 | DC_VSCALE | VVVVVVVV | 128=Normal 64=2x |
DspCom | $40043 | DC_BORDER_COLOR | CCCCCCCC | |
DspCom | $40044 | DC_HSTART_L | HHHHHHHH | hstart bit 0-7 (0) |
DspCom | $40045 | DC_HSTOP_L | LLLLLLLL | hstop bit 0-7 (640) |
DspCom | $40046 | DC_VSTART_L | HHHHHHHH | vstart bit 0-7 (0) |
DspCom | $40047 | DC_VSTOP_L | LLLLLLLL | hstop bit 0-7 (480) |
DspCom | $40048 | DC_STARTSTOP_H | --VvHHhh | V=vstop Bit 8 / v=vstart bit 8 / H= hstop bit 8 / h=hstart bit 8 |
DspCom | $40049 | DC_IRQ_LINE_L | LLLLLLLL | |
DspCom | $4004A | DC_IRQ_LINE_H | -------H | |
DspCom | $4004B | $4005F | Display composer registers | |
Palette | $40200 | Color 0 Green/Blue | GGGGBBBB | G=Green / B=Blue |
Palette | $40201 | Color 0 Red | ----RRRR | R=Red |
Palette | $40202 | $403FF | ... | Palette 1-256 |
SprData | $40800 | Sprite 0: Address L | LLLLLLLL | L = Vram Address L |
SprData | $40801 | Sprite 0: Address H | M---HHHH | H=Vram Address H / M= Mode (0=4bpp 1=8bpp) |
SprData | $40802 | Sprite 0: Xpos L | XXXXXXXX | Xpos bits 0-7 |
SprData | $40803 | Sprite 0: Xpos H | ------XX | Xpos bits 8-9 |
SprData | $40804 | Sprite 0: Ypos L | YYYYYYYY | Ypos bits 0-7 |
SprData | $40805 | Sprite 0: Ypos H | ------YY | Ypos bits 8-9 |
SprData | $40806 | Sprite 0: Settings 1 | CCCCZZVH | C=Collision mask Z=Z depth V=Vflip H=Hflip |
SprData | $40807 | Sprite 0: Settings 2 | HHWWPPPP | H=Height , W=Width (0/1/2/3 = 8/16/32/64 px) / P=Palette offset |
SprData | $40808 | $40FFF | ... | Sprite data 1-127 |
![]() |
256
color Hello World on the Commander x16 with the x16emu Lets create a Hello World example, using a bitmap font in 256 color mode. |
![]() |
![]() x16_HelloWorld.asm |
![]() |
When it comes to compiling a x16 program, we just need to build a
regular C64 PRG file... we can compile a valid file with VASM... vasm6502_oldstyle_win32.exe %1 -c02 -cbm-prg -chklabels -nocase -Dvasm=1 -L \BldC64\Listing.txt -DBuildC64=1 -Fbin -o "\BldC64\Program.prg" The only addition to my regular C64 script is the -c02 switch... this enables the extra 65C02 commands (rather than 6502) |
To start our program we can just specify our PRG on the command
line to x16emu... the script below will load a compiled program
'Program.prg' in the folder \BldC64\ x16emu.exe -run \BldC64\Program.prg |
Using 256 color BMP screens...
Printing characters to the screen...
4bpp Bitmap font
2x 4bpp Layers
Due
to the size of the screens, there isn't enough memory for two
320x240 bitmap screens with 256 colors, but 16 color layers are
likely to be enough for any realistic needs! Most systems from the 90's only had 16 colors or less anyway, so it's what a classic system had to work with. |
![]() |
Putting a bitmap on the screen
Changing the layer
![]() |
The
'Hscroll' option works as a Palette offset for bitmap modes...
unfortunately it seems there's no hardware scroll option for the
bitmap modes... If we want to do scrolling, we're probably going to be best to use tilemap modes (we'll look at them soon)... otherwise we'd have to use software scroll. |
Setting Hardware sprites
Each of the 128 sprites are controlled by settings held in VRAM between
$40800-$40FFF... each has 8 bytes...
The actual bitmap data of the sprites is held in normal VRAM - so we want
to store it outside the visible screen...
Before we can actually use sprites, however, we need to turn them on, we do this with Bit 0 of $40020
Group | Address | range | Description | |
Screen Ram | $00000-$1FFFF | Video RAM (also sprite bitmap data) | ||
SprCom | $40020 | SPR_CTRL | -------E | E=Enable Sprites |
SprCom | $40021 | SPR_COLLISION | ----CCCC | C=Collision Mask |
SprCom | $40022-$4002F | Sprite control registers | ||
SprData | $40800 | Sprite 0: Address L | LLLLLLLL | L = Vram Address L |
SprData | $40801 | Sprite 0: Address H | M---HHHH | H=Vram Address H / M= Mode (0=4bpp 1=8bpp) |
SprData | $40802 | Sprite 0: Xpos L | XXXXXXXX | Xpos bits 0-7 |
SprData | $40803 | Sprite 0: Xpos H | ------XX | Xpos bits 8-9 |
SprData | $40804 | Sprite 0: Ypos L | YYYYYYYY | Ypos bits 0-7 |
SprData | $40805 | Sprite 0: Ypos H | ------YY | Ypos bits 8-9 |
SprData | $40806 | Sprite 0: Settings 1 | CCCCZZVH | C=Collision mask Z=Z depth V=Vflip H=Hflip |
SprData | $40807 | Sprite 0: Settings 2 | HHWWPPPP | H=Height , W=Width (0/1/2/3 = 8/16/32/64 px) / P=Palette offset |
SprData | $40808-$40FFF | ... | Sprite data 1-127 (8 bytes per sprite) |
Bitmap Data format
Some useful new functions for VRAM
Coding Sprites
Here we've
shown a single sprite frame, but if we have multiple versions of
the sprite at different addresses, we just need to alter the
address to update the animation of the sprite... Take a look at the example in the sources file to see more! |
![]() |
Using our Sprite routine
![]() |
The example in this episode works fine for
hardware sprites 0-15, but not 16+... it's not clear why! Unfortunately, with the documentation limited, and the emulator in an early state, When something doesn't work it's not clear if it's an Emulator but, Unclear documentation, or a mistake by the author of these tutorials... If a solution becomes clear later, the code sample will be updated. |