How to save and draw sprites to and from FX modchip?

I’ve seen it mentioned a couple times on here that the FX mod chip and the production ArduboyFX should enable us to save and read bitmaps to and from the external flash, allowing for more assets to be called forth in a sketch (more sprites and longer audio in particular). But I’m rather unclear on how one would actually go about incorporating this into a sketch. So my question is this:

How do I save a sprite/bitmap to the FX modchip? How would I draw said sprite in a sketch?

To convert a image into suitable format you use the image-converter.py Python script. From the Arduboy-Python-Utilities

Make sure to rename the script image-converter.py to image-converter-fx.py (add -fx to the filename). You can now drag and drop images onto thw script and it will produce a .bin file (It will also produce a .h header for normal use). you can also use the script from the command line.

The converter turns colors with a dark green element ( <64) into black and with a brighter green element into white. If the image contains a transparency layer it will automatically add mask data as well.

The image can contain multiple frames/tiles (with spacings). You append [width]x[height][spacing] to the filename. for example if you have a image with 10 8x8 pixel images with a spacing of 1 pixel. The filename would be something like:

numbers_8x8_1.png

to save the .bin file to the FX flash chip (during development of your project) you can use the uploader-gui.py script.

After uploading the data. the log will give you information about the PROGRAM_DATA_PAGE You should copy and paste the line with the define in your project source file.

At the top of your source file you wil also include the line :

#include <ArduboyFX.h>

In your setup() function you add the line:

FX::begin(FX_DATA_PAGE);

To draw thw image you use:

FX::drawBitmap(x, y, address, frame, mode);

address is the offset in the .bin file. for a single resource image it is 0.
frame is the frame number if the image has multiple frames otherwise it is 0
mode is the drawing mode:

  • dbfWhiteBlack = 0; // bitmap is used as mask
  • dbfInvert = 1; // bitmap is exclusive or-ed with display
  • dbfBlack = 2; // bitmap will be blackened
  • dbfReverseBlack = 3; // reverses bitmap data
  • dbfMasked = 4; // bitmap contains mask data

I recommend to have a look and go at the [draw balls example](https://github.com/MrBlinky/Arduboy-homemade-package/tree/master/board-package-source/libraries/ArduboyFX/examples/drawballs)

Currently the FX library is part of the Homemade package But you can download it,extract abd copy the ArduboyFX library folder into your Arduino’s Sketchbook folder if you want to.


When you successfully uploaded the FX data and example sketch. It will look like this on your Arduboy FX. All sprites drawn from the FX chip at 60 fps :)
2 Likes

Thank you so much! This makes a lot of sense, I’ll try my hand at the process as soon as I get a chance today :slight_smile:

If you’ve got a lot of time to watch my tutorial video I go through everything of making and editing sprites:

2 Likes

Does the emulator provide any support for FX?

I get most of it, but now I’m asking myself how it would be possible to take an already defined bitmap in an existing header file, and convert that to the necessary binary for the uploader gui.

For example, if I had the following file named “room1.h”:

#pragma once

#define ROOM_WIDTH 16
#define ROOM_HEIGHT 8

const uint8_t room1[ROOM_HEIGHT][ROOM_WIDTH] = {
{1,1,1,1,1,0,1,0,0,1,0,1,1,1,1,1},
{1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1},
{1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1},
{1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1},
{1,0,0,0,0,1,1,2,2,1,1,0,0,0,0,1},
{1,0,0,0,0,1,1,2,2,1,1,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1}
};

what would I do to it to convert to the .bin wanted by the uploader GUI?

Which log would that be? Having trouble finding it.

You do not need to worry about the individual .h files as these are all compiled into the single .bin file for distribution.

Assuming you don’t want to store it in the FX chip.

Yes, checkout this thread:

If I understand it correctly by bitmap you mean something else then an image in this case.

You can only upload a single .bin file and that .bin file should contain all your fx data. Currently you need a bit of manual work to put all your data in there. With only images you could combine them together using COPY /B command line command. or use an Hexeditor. inserting your byte array example would also require the hexeditor.

I hope to have a script ready soon to make it all easier.

You can save it in an .XBM file format and open it with GIMP

XBM File (What It Is & How to Open One).

1 Like

In this case the bitmap would be a tile map of “solid” blocks, representing a room’s default layout in a game. Each tile is 8x8 pixels to keep things neat & rounded.

I didn’t realize all the data had to be in the bin, that makes sense though. I haven’t used a hexeditor before, so I’m not sure it would be very useful in my case. I’ll be looking forward to the script being ready!

the drawBitmap function of the FX library is capable of drawing sprites using a width and height from 1 to 65335 pixels (as long as the binary data fits the FX chip)

1 Like

I can’t seem to get it working quite right. the background tiles are displayed,fine but the balls are just gibberish polluting the space the ball should be.

Why only odd numbers? That seems… odd.

Ok will look into this.

I guess poor choice of word there.

any number of pixels from 1 to 65535


Edited the post, hope it's more clear now.
1 Like

Tried again this morning, and was met with success :slight_smile: I think I was using an outdated version of the example before, everything’s working fine now!

2 Likes

While developing my own games, after I convert sprite data to a .bin format, say

spritedata_128x64_0.png

and I’ve got the data page output by

flaschart-writer.py -d spritedata.bin

How do I find the address of each image in the spritesheet? Do I have to use a hex editor to look at the newly created .bin or is there a more user-friendly/easy way to go about it?

Good news. I’ve worked all day on a script to make fx-data creation easy and added it to my GitHub :smiley:

The tools is called fx-data.py

Basically you supply (drag and drop) a text file onto the script and it creates a C header file. and the .bin file.

There’s an example text file that creates a header file and data file for the Balls demo.

The format is very C-ish for convenience.

for your example you would the following line to the fx-data text file (asuming the image is is nthe same folder as the text file):

image_t spriteData = "spritedata_128x64_0.png"

The tool then creates a header file with something like this:

constexpr uint24_t spriteData = 0x000000; //(address is 0 cause it's the first resource)

It also creates the a FX_DATA_PAGE define so you don’t have to worrry about that anymore. You can just use a fixed line of code in your setup and never worry about it again.

FX::begin(FX_DATA_PAGE);

You don’t. lets say you have a sprite sheet of 256 8x8 tiles without spacing.
You would append _8x8 to the filename. for example spriteSheet_8x8.png and the tool will slice the image up depending on it’s dimensions.

To decide which tile you want to draw you just pass it on to the drawBitmap function as the frame parameter

FX::drawBitmap(x, y, spriteSheet, frame, mode);
1 Like

That’s fantastic! Definitely going to speed things up.

^This makes so much sense! it’s always the most obvious thing :crazy_face:

1 Like

Alright, I’ve used the script now & it’s perfect :clap::pray:
Currently working on an Atari 2600 adventure port (probably just the first level, but we’ll see), it’s a lot of screens and I was using a couple for () loops and byte arrays to draw and determine whether a block was solid. I’ll have to come at it from a different angle of I’m going to use the FX::drawBitmap() function I think, but for now I’m just making sure it can draw each room by setting the frame to currentRoom, and incrementing or decrementing with left and right. What’s neat about this is that you can see the rest of the data on the FX if you go past the number of frames the spritesheet has.

One thing I noticed out of place: there’s a one pixel column of what should be the 128th, but it’s being wrapped around back to the 1st. Not sure why. But setting the x value in FX::drawBitmap to -1 fixes it.

2 Likes