Converting Images to Sprites for PicoSystem

I’m currently working on a small game for the PicoSystem and want to use custom sprites. I didn’t find any docs/tooling for doing this, so I put together a small python script to handle the conversion (based on comments in the SDK about pixel format and the data associated with the default sprite sheet). So far, this is working for me and figured I’d share in case others are facing the same challenge:

(disclaimer: Using the SDK values as a reference, the python script does get slightly different RGB values when converting the default sprite sheet from the 32Blit source image. The end result has looked visually OK to me; however, I’m still trying to account for the slight difference)

1 Like

I’m using this web-based converter:

but I can’t seem to get the transparent color to work. That could be one of the sprite() flags but I don’t see the flags documented.

when exporting from GIMP - under Compatibility Options you need to check Do not write color space information.

Then in Image Transcoder - check Byte Swap and make sure to fill in Frame Width and Frame Height.

Looks like transparency IS working if black (color 0 in default palette) is used in background of spritesheet.

1 Like

Oh cool, I hadn’t heard of that converter. I wasn’t able to get RGB565 format to work when I originally tried it with the sprite drawing. I ended up writing the converter code based on comments in the source about GBAR format and 16bits of data:

Do you know if the Picosystem has a set palette? I’m having trouble getting colors to show up as expected.

To be honest, I don’t know if it supports palettes (early on, I was assuming it did; but, I never found a way to make that work).

With the disclaimer that the following is just my observations (but it does seem to work OK in practice), below is my current mental model on how sprites/bitmaps work:

I think the PicoSystem is using a color model similar to “True Color” but with only 12 bits of color data (4 bits each for red, green, and blue) plus 4 bits of transparency data to total out at 16 bits. I’m basing the bit count on the format of the _default_sprite_sheet:

My thinking here is that it’s 8 entries across with each entry having 16 bits of data and that seems to line up reasonably well with the 8x8 sprites in the source image from the 32blit project

The ordering is a bit different than I would have expected, I was assuming it would be RGBA; but, it appears to be GBAR based on the comments in blend.cpp.

Walking across the first line of data to the first non-zero pixel, 0xd5f7, when I open the source image in GIMP, I get the values:

  • Red: 38.8
  • Green: 78.0
  • Blue: 30.2

When I multiply those against 15 and convert to integer, I end up with:

  • Red: 6
  • Green: 12
  • Blue: 5

Which feels very close to the values in the library source:

  • Red: 7
  • Green: 13 (0xD)
  • Blue: 5

(I don’t have a good working theory on the variance on red and green; but, the difference there doesn’t stand out to me on screen, so I haven’t worried about it so far).

Additionally, the 0x0 versus 0xF in the third nibble line up nicely with where the source image is intended to be fully transparent versus fully opaque.

Thanks Dan, that helps a lot, I’ll try adjusting my colors using that information and let you know how it works.


1 Like

I found a workaround, kind of lame but it works.

If you compiled the examples there is and example called colour, you can upload it to the Pico system and use the d-pad to choose a color that you like and write down the hex value, then I did a search and replace in my data to get the exact color, not elegant but I’m only using 3 colors and black for transparent for now.

Hey Brian, you’re welcome, no worries! Sounds like a good workaround - I think a lot of times the key thing is getting to a point where one can keep moving forward with the overall project :)


Yeah, there are 4 bits per colour channel, so everything gets squashed down into that space.

( this is also why pen() takes r/g/b/a values between 0 and 15; treating them as 0-255 channels has some … confusing side effects! )

1 Like