Page 1 of 1

Help loading c64 multicolour bitmaps?

Posted: Wed Dec 10, 2025 1:45 pm
by retrogamecoders
I'm new to UG and recently added it as a compiler option to my online IDE, but I am failing at adding tutorial examples for users :?

Hires monochrome is working (although I haven't yet been successful using it for movement/redrawing) but the second part of my example after the keypress is going weird

Image

Assuming multi colour mode on the

Code: Select all

C64 is ENABLE BITMAP (16)
how do I get a white background and my

Code: Select all

PUT IMAGE
to use the colours I want?

Re: Help loading c64 multicolour bitmaps?

Posted: Fri Dec 12, 2025 1:53 pm
by spotlessmind1975
Hi retrogamecoders, and welcome to the forum! :D
retrogamecoders wrote: Wed Dec 10, 2025 1:45 pm I'm new to UG and recently added it as a compiler option to my online IDE, but I am failing at adding tutorial examples for users
First of all, I'm flattered that you've added ugBASIC to your IDE, and I hope I can help you with the tutorial!
retrogamecoders wrote: Wed Dec 10, 2025 1:45 pm Assuming multi colour mode on the
C64 is ENABLE BITMAP (16)
how do I get a white background and my
PUT IMAGE
to use the colours I want?
Below is an example that attempts to overcome some intrinsic limitations of the VIC-II chipset when working with multicolor images.

Before moving on to the code, there's a theoretical premise to introduce. The PUT IMAGE primitive manages the entire lifecycle of drawing an image, from bit representation to setting the color registers. Therefore, if the image you draw has a black "background," it will be represented on the entire screen: this is because the VIC-II video chipset has only one color register for the entire background. Since ugBASIC is an isomorphic language that provides no unnecessary abstractions, there are several ways to overcome the problem, from the most portable to the most specific to the Commodore 64 (and other targets with a VIC-II video chipset).

The first solution, and the least portable, is to ensure that drawing the image does not modify the color registers. This solution involves using the PUT BITMAP primitive instead of the PUT IMAGE primitive. See this example:

Code: Select all

	' enable multicolor
	BITMAP ENABLE (16)
	' clear the screen with a white background
	CLS WHITE
	' Load image...
	spriteImageColor := LOAD IMAGE("4tiles.png")
	' ... draw the image
	PUT BITMAP spriteImageColor AT 0, 0
Image 4 tiles.png is this:
Image

A second, much more portable, solution is to ensure that the image sets a white background. This is achieved by specifying the image background to be white, so that it will be used as the background color when the PUT IMAGE statement is used.

Code: Select all

	' enable multicolor
	BITMAP ENABLE (16)
	' clear the screen
	CLS WHITE
	' Load image with white background...
	spriteImageColor := LOAD IMAGE("4tilesw.png")
	' ... draw the image
	PUT IMAGE spriteImageColor AT 0, 0
Image 4tiles4w.png is this:
Image
retrogamecoders wrote: Wed Dec 10, 2025 1:45 pm Hires monochrome is working (although I haven't yet been successful using it for movement/redrawing) but the second part of my example after the keypress is going weird
If you could be so kind as to share the source so I can copy and paste it into the IDE, I could check what's wrong.

Thank you again, and happy retrocoding!

Re: Help loading c64 multicolour bitmaps?

Posted: Fri Dec 12, 2025 7:10 pm
by retrogamecoders
Thank you, I updated the code in the IDE so this is the latest

https://ide.retrogamecoders.com/?file=s ... atform=c64

Re: Help loading c64 multicolour bitmaps?

Posted: Sat Dec 13, 2025 6:40 pm
by spotlessmind1975
retrogamecoders wrote: Fri Dec 12, 2025 7:10 pm Thank you, I updated the code in the IDE so this is the latest
First of all, thank you for the example, which allowed me to highlight a bug in the multicolor image conversion routine. So, first of all, I ask you to update the compiler on your online IDE (I don't know if you're using the binary version or the source code, but I've updated both).

The first thing to note is that the transparency mechanism in multicolor mode works exclusively on the bitmap component, not the color one. In other words, this mode requires transparency masking operations to occur only on the index "plane," ignoring the color map. This means, in practice, that the drawn image won't be visible unless the underlying color has already been set. So, it's necessary to remove WITH TRANSPARENCY, at least for this specific example. I also changed the image, making sure it has a white background:

Code: Select all

	PUT BITMAP sprites FRAME 1 AT elfx,elfy
A theoretical description can be found here.

Running the source code, you'll notice the "strip," because the background isn't restored. At this point, it's best to switch to multiplexed sprites. To use these sprites, however, you must abandon the ability to switch between resolutions and use a single one. In short, you have to choose between 320x200 or 160x200 pixels. To get a working source, I switched to the 320x200 version, which allows transparency using PUT IMAGE.

The code is this:

Code: Select all

	BITMAP ENABLE(2)
	DEFINE MSPRITE ASYNC
	COLOR BORDER WHITE
	CLS WHITE
	
	xmas := LOAD IMAGE("xmas.png") 
	snowpic := LOAD IMAGE("snow.png") 
	elfpic := LOAD IMAGE("elf.png") EXACT

	CONST limitx = SCREEN WIDTH - SPRITE WIDTH
	
	RANDOMIZE

	FOR idx = 1 TO 25
	  x=RND(320-IMAGE WIDTH(snowpic))
	  y=RND(75)+75
	  PUT IMAGE snowpic AT x,y WITH TRANSPARENCY
	NEXT
	
	PUT IMAGE elfpic AT 200, 50 WITH TRANSPARENCY
	PUT IMAGE xmas AT 80, 0 WITH TRANSPARENCY

	sprites := LOAD ATLAS("xmas_sprites2.png") FRAME SIZE (24 , 24) EXACT

	sprite1 = MSPRITE( IMAGE( sprites FRAME 1 ) )
	sprite2 = MSPRITE( IMAGE( sprites FRAME 2 ) )
	sprite3 = MSPRITE( IMAGE( sprites FRAME 4 ) )

	DO

		SPRITE sprite1 ENABLE AT elfx+SCREEN BORDER X, 21+elfy+SCREEN BORDER Y    
		SPRITE sprite2 ENABLE AT SCREEN BORDER X+limitx-elfx, 60+elfy+SCREEN BORDER Y    
		SPRITE sprite3 ENABLE AT SCREEN BORDER X+elfx, 90+elfy+SCREEN BORDER Y    
    	elfx=elfx+1
    	IF elfx > limitx THEN	
    		elfx = 0
    	ENDIF
        
        MSPRITE UPDATE
	LOOP
For performance reasons, I used asynchronously multiplexed sprites, which require an explicit call to MSPRITE UPDATE. In principle, this could have been done without, except for the initial DEFINE: in that case, the sprites are updated when the relevant command is executed.
This is the result (I colorized the elfpic.png image, to make evident the VIC-II limitations):
Image

More info on sprites can be found here.

Hope this helps!