Making sprites with mksprite
Mksprite is a tool by the Libdragon team that allows you to convert PNG image files into libdragon-usable .sprite files.
Note: this page is about the stable mksprite. For information on how the mksprite on the unstable branch works, visit the wiki page.
Downloading mksprite for Windows (trunk version)
Building it from scratch is a pain in the butt, let me tell you. It’s much easier just to download it. You can get it from the download page by using the password howdoicompilethis
. This executable is for 64-bit Windows machines.
Building the executable in Windows
This took me a loooooong time to figure out, so this is as much of a guide for you as it is for me for future reference. It’s not too late to turn back and just download it.
In order to get this working, we’ll need to perform a few steps:
- Install libpng
- Install zlib
- Make the executable
To do this, you’ll need some kind of GCC installed, I’m using MinGW 64-bit.
Installing libpng
I’ll break this up into two sub-steps: Building the library and installing it into GCC.
Getting the library files
Start by getting the latest source code from the website and extract it using your favourite zipping tools. You should have a folder with a lot of source files in it.
Next, since we’re using GCC, we want to use the GCC makefile. so go to the scripts
folder and find a file called makefile.gcc
. Copy it up a level into the main libpng source folder and rename it to just makefile
(remove the ‘.gcc’ extension.
Do the same with another file in the scripts folder, pnglibconf.h.prebuilt
. Move it into the main folder and remove the ‘.prebuilt’ extension.
Once that’s done, you can run the make
command in the main folder and it should compile. You’ll get a pngtest.exe
file which isn’t useful to us, a bunch of .o
files which we’ll ignore and a file called libpng.a
which is our library file that we were looking for. Eureka!
Installing into GCC
Now that we have our libpng.a
file, we can start copying things over.
Go to your GCC installation directory. For me it’s C:\mingw64
. In there, we’re looking for two folders called include
and lib
. However, these are not necessarily the folders located in your GCC directory. I think that when you’re using a 64-bit GCC, the folders you’re looking for are in the 32-bit subdirectory. That’s a bit confusing, so let me show you some examples of where you might find the folders.
32-bit
C:\MinGW\lib
C:\MinGW\include
64-bit
C:\mingw64\x86_64-w64-mingw32\lib
C:\mingw64\x86_64-w64-mingw32\include
This will vary depending on what version of MinGW you are using, but that’s the gist of it. If in doubt, go to your folder and search for a file in stdlib like stdio.h
. This will be found in the correct includes folder.
Now it’s time to copy over the files. Go to your libpng folder that you were working on earlier and copy libpng.a
into the lib
folder.
Then copy all the header files (ending in .h
) into the includes
folder. These are the ones I copied over:
- png.h
- pngconf.h
- pngdebug.h
- pnginfo.h
- pnglibconf.h
- pngpriv.h
- pngstruct.h
And that aught to do it! You can now call in libpng using this includes statement: #include <png.h>
Installing zlib
Zlib is a dependency of libpng, so we’ll have to install that as well. Older versions of libpng have it included, but let’s use the latest ones in our project.
The process is similar to the above, so I’ll break it down into similar sections.
Getting the Library files
Grab the latest version of the source code from the zlib website and extract the folder.
Open the extracted folder and ignore the Makefile. This one isn’t going to work for our purposes. Instead do what we did with the other library and open up the win32
folder and copy Makefile.gcc
into the main libz folder.
Next open up the terminal and navigate to the folder using the cd
command. Then run the following command to make using the correct makefile:
make -f makefile.gcc
This should compile the source files. You should end up with a file called libz.a
.
Installing into GCC
I won’t go into too much detail since this was covered in the previous section, but you should copy this file into the same /lib/ folder:
- libz.a
And this file into the /include:
- zlib.h
These files might be included already, but this will update them to the latest version.
Making mksprite.exe
Now that we have the libraries in place, it’s time to build mksprite.exe.
First, go to the mksprite folder which should be located inside your project if you initialised Libdragon correctly at:
{project_home}/libdragon/tools/mksprite
Next we need to make some changes to the Makefile:
- Add
-lz
toLDFLAGS
. - Replace
$(CC)
withgcc
. Or addCC=gcc
to your environment variables.
Now we’re ready to make mksprtie.exe. Use this command in the terminal:
make mksprite
You should end up with a mksprite.exe file in the directory. It won’t run on its own, since it requires a .dll file. You can find zlib1.dll
in your zlib folder, it should have compiled at the same time as libz.a
.
Bonus: I like to move mksprite.exe
and zlib1.dll
to the same folder as libdragon.exe
from the first tutorial so that it’s a bit cleaner and so that it all lies in the PATH, making it more accessible.
Building mksprite in your project (better in Linux)
A much easier way to do all of this without having to mess with PATH variables is to include compilation of the tools as part of your makefile.
# Declare the tools location
TOOLS_DIR=libdragon/tools
TOOLS_MKSPRITE=$(TOOLS_DIR)/mksprite/mksprite
# Compile the required tools
$(TOOLS_MKSPRITE):
cd $(TOOLS_DIR)/mksprite && make
# Sample sprite processor, remember to include $(TOOLS_MKSPRITE) as a dependency
$(SPRITE_FILES): $(IMAGE_FILES) $(TOOLS_MKSPRITE)
@echo " [MKSPRITE] Processing image" $(notdir $(subst sprite,png,$@))
$(TOOLS_MKSPRITE) 16 128 1 $(IMAGES_DIR)/$(notdir $(subst sprite,png,$@)) $@
Using mksprite
The basic usage of mksprite from the command line is like this:
mksprite <bit depth> [<horizontal slices> <vertical slices>] <input png> <output file>
Here are the parameters:
<bit depth>
(required) is either16
or32
, depending on how many bits per pixel you want the sprite to be.<horizontal slices>
and<vertical slices>
(optional) how many slices are in the image. Useful for sprite sheets with many different images.<input png>
(required) input file name relative to the current directory<output file>
(required) name for the output file
Here is an example:
mksprite 16 player.png player.sprite
Automating mksprite
That’s just the basic usage of mksprite. To really up our game, let’s automate the process so that we don’t have to run the command every time we update our images. To do this, we’ll be putting some extra folders and add some clauses to our Makefile.
Start by adding in some folders in your /src/ directory: images and filesystem. These will be used for our source images (.png files) and our output images (.sprite files) respectively. It should look like this:
Put all your .png files into the images folder, like this:
Now that the files are in place, let’s amend the makefile. We’re going to need to run the mksprite command in a loop to convert all of the sprite images, so let’s make it looks like this:
V=1
SOURCE_DIR=src
BUILD_DIR=build
IMAGES_DIR=$(SOURCE_DIR)/images
IMAGE_FILES:=$(wildcard $(IMAGES_DIR)/*.png)
SPRITES_DIR=$(SOURCE_DIR)/filesystem
SPRITE_FILES=$(subst images,filesystem,$(IMAGE_FILES:.png=.sprite))
include $(N64_INST)/include/n64.mk
all: hello.z64
.PHONY: all
OBJS = $(BUILD_DIR)/main.o
$(SPRITE_FILES): $(IMAGE_FILES)
@echo "Processing file" $(notdir $(subst sprite,png,$@))
mksprite 32 $(IMAGES_DIR)/$(notdir $(subst sprite,png,$@)) $@
hello.z64: N64_ROM_TITLE="Hello World"
hello.z64: $(SPRITE_FILES)
$(BUILD_DIR)/hello.elf: $(OBJS)
clean:
rm -f $(BUILD_DIR)/* *.z64
.PHONY: clean
-include $(wildcard $(BUILD_DIR)/*.d)
Lines 4-7 have some new variables. Line 5 in particular searches for png files in the src/images
folder, and then line 7 does some substitutions to convert them to the /filesystem/
directory with a .sprite
extension.
Line 16-17 create a new target for the sprites. We run mksprite
on every file found, and place them in the src/sprites
folder. Line 20 then add them as a requirement for building our ROM file.
This is a fairly simple addition with some limitations (all sprites are 16-bit, there is no horizontal/vertical slices, etc) but this can be fixed by making a more complex makefile command that treats additional subdirectories differently.
Adding sprites to your ROM
Note that if you want to add the sprites you made to your ROM, you have to use the Dragon File System (DFS).