Commodore 64 Programming #7: Creating and rendering bitmaps

image

Update: All needed files for this tutorial can be found in the GitHub repo linked in the bottom of this page.

In this tutorial we are going to cover two things. First we will look at one way of creating bitmaps/images for our C-64 programs by using a tool for Windows. Next we will load the image we created into our own program and render it.

Creating bitmaps

Before you can draw your bitmap, you will need a tool. The tool I like to use is named Timanthes v3, and can be downloaded below.

imageDownload Timanthes 3.0 beta by Mirage of Focus:  http://noname.c64.org/csdb/release/?id=75871

Load Timanthes and you will see an environment much similar to other painting programs in front of you. When painting for the Commodore 64 you must be aware of a few limitations. The Commodore 64 supports a few different graphic modes. The one introduced here is a pretty common one and will work as a basis to understand the rest of them.

The format we are implementing is named MultiColor and got a resolution of 160×200 pixels, with the support of 16 colors. As you can see, the resolution of the images is smaller than the screen. One pixel in the image represents 2×1 pixels when rendered on the screen. Another important attribute with this mode is that the screen is divided into 40×25 attribute cells, where each attribute cell is 4×8 pixels in size. Each is also limited to contain the maximum of 4 colors.

Confused? Let me break it down for you:

The image is 160×200 in size…
image

..where one pixel in the image represents 2×1 pixels in screen size:
image In this picture, I drew ONE line across 8 pixels, and another line down 8 pixels. Notice that the width of one pixel spans across two pixels when rendered.

I also mentioned that this image mode splits the image into 40×25 attribute cells:

image

where each of the cells contains 4×8 pixels (8×8 in real):
image This is one cell. It contains 4 pixels you can draw in the x-axis and then 8 pixels you can draw in the y-axis. One pixel in the x-axis represents 2 pixels in screen size.

Also, one cell can only contain the maximum of 4 colors, including the background. If you try to draw more than 4 colors in Timanthes, a red pixel will show on the colors that exceed the limit, and must be corrected.

Now, the first thing you will see when loading Timanthes is that you got a drawing area and some floating windows. Move these into a position you like. Now, in the layers window, notice that you got two layers. This is how it should be when exporting your image to a prg file. You NEED to have two layers. I usually draw on the 2nd layer.

Also, on the right side of the layer preview image, you can see what type of layer your dealing with:

image

This is where you select what kind of graphic mode you want the image in. Select Layer 2 (it’s probably already selected) and click the properties button:

image

You will see a popup window:

image

In Mode, select “Bitmap multicolor” and click OK.

Now, select a color from the Colors window. This is the palette. This mode support 16 different colors. You can modify each color from this window. But remember, 16 in total is the limit. Smilefjes

image

Now, draw any image. My result was this, the logo of my group in the demoscene. You can download the file below.

image

image Click the file below to download dcc.PRG

DOWNLOAD

Now it’s time to export your image from Timanthes. Click File and Export As, the type must be .PRG and you can name it whatever you want. I named mine dcc.prg. Press OK and a new popup will show:

image

You can leave it like this for this example, but these values are the values we are going to use when loading the image into memory and displaying it!

A list of other graphic modes can be found here: http://www.studiostyle.sk/dmagic/gallery/gfxmodes.htm

Loading and displaying the image in your program

Keep in mind that one image takes about 2000 bytes in memory, so it has to be loaded into $2000, $4000, $6000 and so on, and not in $2456.

Let’s write our code. A complete listing can be seen below.

First of all, we set the background color to the one that the image is using. When you exported the image, you noticed that the background is stored in $4710. Load the value from here into the d020 and d021 memory.

processor 6502
org $1000

     lda $4710
sta $d020
sta $d021

Now we will create a loop that copies the data to screen RAM that starts at $0400. The data (in one way, we use characters (the cells), but more on this later) for our image is located at $3f40 (as we noticed when we exported the image). We use the same method for copying as in the earlier example where we cleared the screen.

First, set the x-register to zero, and start the copying:

     ldx #$00
loaddccimage:
lda $3f40,x
sta $0400,x
lda $4040,x
sta $0500,x
lda $4140,x
sta $0600,x
lda $4240,x
sta $0700,x

Also, we must copy the color RAM for our image located at $4328 (specified when exporting the image) to $d800. We add this to the loop:

     lda $4328,x
sta $d800,x
lda $4428,x
sta $d900,x
lda $4528,x
sta $da00,x
lda $4628,x
sta $db00,x

One last thing has to be done in the loop, and that is to increase x. If x does not equal zero, branch to the loaddccimage label.

     inx
bne loaddccimage

The loop will now loop until x is zero, copying all data into the correct memory. Once this is done, the image is loaded and ready to display! Smilefjes

The next thing we need to do is to tell “the system” that we want to enter bitmap mode, and that the mode is a multicolor mode.

$d011 must be set to what mode we want to go into. To got into bitmap mode, we set $d011 to 3b:

     lda #$3b
sta $d011

Now we are in bitmap mode.

Next, we must turn on multicolor-mode. This is done by putting the value in $d016 to 18.

     lda #$18
sta $d016

Now, we are in bitmap multicolor-mode! Smilefjes

The last thing we need to do is to tell the VIC that the screen RAM is at 0400 and that the bitmap is at $2000. If we put in the value 18, the first numer (1) is where we want the screen RAM, and the last numer is where the bitmap is. How does this work? First, we know that out screen RAM is located at 0400 and is 0400 bytes long. We count how many times we need to “add” 400 bytes to reach to the desired screen RAM from 0000. So, 0000+0400 = 0400. Thats one time. Next, we must count how many times until we reach 2000. Thats 8 times. To set that the screen RAM is at 0400 and the bitmap is at 2000, we $d018 to #$18:

     lda #$18
sta $d018

This might sound confusing. The screen memory is 400 bytes long, so it has to start on a memory address that is a multiple of 400. If you don’t change where the screen memory is, it’s located at $0400 by default like in this example.

Now, let’s add an infinite loop so that our program won’t just exit once the image is rendered:

loop:
jmp loop

That’s it for loading the image. One final thing remains, and that is to include our image file and put it into the memory. When we exported, we specified that we wanted to have the image at the memory location $2000. Now, a PRG file got a header that is 2 bytes long. That means that we want to include the file in location $2000-2 bytes = $1FFE:

org    $1FFE
INCBIN “dcc.PRG”

If you compile and run this, the emulator will display the image as seen below. Smilefjes

image

A complete listing of our code can be found in listing 7-1.

Listing 7.1 – Complete listing for rendering your multicolor image

    processor   6502
org    $1000

            lda $4710
sta $d020
sta $d021
ldx #$00
loaddccimage:
lda $3f40,x
sta $0400,x
lda $4040,x
sta $0500,x
lda $4140,x
sta $0600,x
lda $4240,x
sta $0700,x
lda $4328,x
sta $d800,x
lda $4428,x
sta $d900,x
lda $4528,x
sta $da00,x
lda $4628,x
sta $db00,x
inx
bne loaddccimage

           lda #$3b
sta $d011
lda #$18
sta $d016
lda #$18
sta $d018

loop:
jmp loop

    org    $1FFE
INCBIN “dcc.PRG”

Downloads
Download the source from GitHub:
https://github.com/petriw/Commodore64Programming/tree/master/7-Bitmaps

This entry was posted in Commodore 64. Bookmark the permalink.

21 Responses to Commodore 64 Programming #7: Creating and rendering bitmaps

  1. Pingback: Windows Client Developer Roundup 067 for 5/1/2011 - Pete Brown's 10rem.net

  2. n00b says:

    Hello,
    excuse me for my silly question, but I don’t understand the need for the characters.

    the bitmap data at $2000, the colormem data at $4328 and the background color at $4710 not enough?

    Thanks!

    • gascioglu says:

      In Multicolor Bitmap mod VIC-II looks up to the screenram ($0400-07FF) for 1st and 2nd colors and colormem for 3rd color. That is what you copy as the charmem data is actually color data.

  3. Mike says:

    I don’t understand; when I assemble and run your program in VICE, SYS4096 just displays garbage. I have dcc.prg in the same directory as the source file and dasm assembled it without error.

  4. Javier says:

    i have the same question as noob ask:
    When you export the image you have the following data:
    Bitmap Data: $2000
    Charmem Data: $3F40
    Colormem Data: $4328
    Background Data:$4710

    Then you tell VIC-II to use the Video RAM in $0400, OK. But you tell it, moreover, that the Bitmap data is in $2000 too. Isn’t it? Then, why you need to copy all bitmap/colour data to $0400/$d800 if VIC-II already knows where those data is?
    Yes, i tried to render the bitmap without copy it to $0400/$d800 and it shows corrupted but what i want to know is why

    Fantastic lessons, thank you for do it!!

    • $0400 is the area that the computer fetch the bitmap from, you need to copy it there or change that pointer to another memory area, 0000-3C00 are available start addresses in steps of $0400. So you could set D018 to display $2000 directly and not copy.
      http://sta.c64.org/cbm64mem.html
      Color Ram can not be pointed to elsewhere (as far as I can tell), so you need to load it there right away or copy it there.

  5. Dan Roganti says:

    When I try this example using your ‘dcc.prg’ file, it works perfectly. But when I use a screen which I created using the Timanthes tool, then I get garbage. I noticed that the file size for my *.prg is ‘zero’ bytes.

    Because when I try to export the design to a *.prg, I get a popup error message
    “Unhandled Exception has occurred in your application. If you click to continue, the application will ignore this error and attempt to continue. I f you click Quit, the application will close immediately”

    And there’s a very long list of details from the error message in that dialog box. I can send it to you if you need to see this. I’m using Win7 here. The Timanthes tool works great otherwise except for that problem. I like using it very much, It reminds me of the early version of Paint Shop Pro, with the same menu and controls. I’m getting very acquainted with making C64 screens with this.

    I hope there is a remedy to the export problem
    thanks !

  6. Dan Roganti says:

    UPDATE:
    I managed to get my screen design I created in Timanthes to work with this example code. I’m not sure yet what I did wrong in the previous design. But I just started fresh with a new design, something very simple, also a Multi-color bitmap, and it worked perfectly. I was able to export the screen design to a *.prg . Then build the example code and run it in VICE and it works great.

    What I suppose is happening in this tool is there isn’t any warning messages to tell you there is something wrong with your screen design when you make a mistake somewhere. I do see the one type of error/warning you get when one of the pixels turns bright red – to alert you that there is a violation in the multi-color combination for that cell. I would fix those before I attempt to export the screen design. But I didn’t see any other error or warning when I tried to export the previous screen I made into a *.prg. Other than that it crashing with the exception error message.

  7. MANU says:

    Worked like a charm. I did my own drawing to be sure I’ll not have any problem later, I know there are many people who couln’t save the bitmap…

    I loved playing with the code, especially to see how it work with no bitmap mode and/or multicolor mode. Just put a jmp loop (I think you can use bne and few code to make a test stuff like IF a { your code } (so if a = 0 does nothing, else: does read the code)

    jmp loop
    lda #$18
    sta $d016
    lda #$18
    sta $d018

    It was cool with a simple letters drawings, it became blocky with some strange chars, very ascii art 🙂
    I can’t wait the next lesson, tommorow is another day, but I admit I tried to paste the sid music snippet, and it worked nice. (require image loading first, if you don’t wan’t to modify anything)
    The first step is almost here, just a scroller 🙂 I hope I can soon move stuff with sinuses, i’m a trig stufs wh0re 😛
    Thanks.a lot Digitalerr0r

  8. MANU says:

    huh, in fact in worked, but I did a mess by removing some stuff to play the sid and the logo. Ask if you want it. Remember i’m learning since not a even week.
    Btw I should have help other noob with acme syntax, c64studio ide (the simplest you’ll found)
    *= $1FFE == org $1FFE
    . INCBIN = “moi.PRG” == !binary “moi.PRG”

  9. Ralfie says:

    Hi!
    Im a real noob here and trying to figure out why nothing happens when i type run.
    It compiles with no error but still nothing happens…. wierd 🙂

  10. flag26838 says:

    And the link to dcc.PRG is broken too… 😦

  11. Aalea Ally says:

    When I try compiling it, the prompt says “error: Unknown Mnemonic ‘loaddccimage’. It’s probably something stupid that only an extreme beginner like me would miss, but can someone please help me?

    • e5frog says:

      Usually code has indentation, spaces or a tab (whitespace) – so “lda #$1e” is typed in the editor as ” lda #$1e”. The “loadccimage:” is a label that is there instead of an address, these are usually typed with no whitespace before – so they aren’t interpreted as a mnemonic.

  12. Pingback: C64 Programmierung – FabrikantenStadl

  13. Urias Nooteboom says:

    It just works. Thanx!!!
    But changing the colourmem in simanthes to $4000 and $4400 doesn’t work.
    It just handles the old adresses fixed.
    Nevertheless nice.
    In my old days it was hard to find a nice picture on the C64,
    without internet, just floppy disks :o)

  14. WebFritzi says:

    Thanks. It works perfectly. But when I want to display a sprite at the same time and display it just before I display the bitmap, the sprite gets corrupted. I would like to know why. Can anybody help? Here is my routine for the sprite that I call with jsr:

    paintsprite
    ldx #$00
    lda #$ff
    setspritedata
    sta $0340,x
    inx
    cpx #$40
    bne setspritedata
    lda #$0d
    sta $07f8
    lda #$01
    sta $d015
    lda #$80
    sta $d000
    sta $d001
    rts

    When I first diplay the sprite and then the bitmap, it’s fine.

    • markus says:

      because the 07f8 spritepicturepointers will overwritten by the bitmap copy routine.
      so first show bitmap and then run your sprite code…

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.