The tool we want to use is PIXI, the latest sprite tool.
The advantages over romi's Sprite Tool are following:
Quick insertion time.
Local (i.e. level dependant) sprites, saving a couple sprite slots
Shared subroutines, saving a couple of ROM space
Support for extended and cluster sprites
Native SA-1 support
If these aren't reasons to not use PIXI over Sprite Tool, what else?
The first thing is to extract all files (okay, there are optional files but still, if you don't know how PIXI works, just do it). I also recommend to put PIXI in its own folder to avoid conflicts with tools which use files with the same name as PIXI's ones. To use PIXI in a seperate folder, simply use batch file, presumably a drag and drop one. It would look something like this:
Create a new empty text document, paste the above code into it and save it as "pixi.bat" (if you use notepad, you have to change the extension to "All Files").
Aside from that, at the end of each chapter there are some questions to test if you have understood the tutorial.
Mario want to use PIXI. There is one problem, though: It complains that some files aren't found.
After he managed to work PIXI correctly, other tools start complaining.
Sprite Insertion (Global)
Now, we have set up PIXI. The next step we want to do is to actually use it. We first get some sprites and for this tutorial, we use the default sprites. For more sprites, take a look at the Sprites section. Be careful that not all sprites are yet compatible with PIXI, due to being made for an older assembler. Look for the error section on how to fix it.
Anyway, after you got your sprite, there are three important types of files:
ASM files which contain the sprite code and
CFG files which contain some sprite properties
JSON files which are just CFG but with a more readable format and allows for custom sprite display.
These files must exist in the same folder which is for now "sprites". The amount of CFG and JSON files can be higher than these of ASM file and may not even match up with the file name but that's because these files already have the ASM file specified inside. You can even use it to create multiple sprites of different behvaiour (see the CFG Editor).
We then open list.txt or create it if it doesn't exist. It should be an empty text file that we then fill with our information in this format:
"<Number>" is simply any number between 00-AF.
"<Sprite>" is the CFG/JSON file of the sprite you want to insert. You don't need to specifly the main folder (by default "sprits"). However, if the sprite is in any subfolder besides the primary ones, you have to enter the subfolder's name, followed by a slash and then the sprite's name (i.e. something like "subfolder/sprite.cfg").
Confused? As an example, we try to insert the included Sidway Piranha Plant and the Hammer Brother. The list should look like this:
Now try to insert these sprites into your level. Insert the ExGFX, set the GFX in the level correctly, switch to sprite mode and now press "Insert" on the keyboard. You then see a dialogue window:
Only the "Command" and "Extra Bit" fields are important.
The former is the sprite number. I guess, you can figure out, what you have to enter into this.
The latter is set to be either 2 or 3. This has got too functions: The first function is to determine that this sprite is custom (hence why you have to enter 2 or 3 into that field) and the second function controls the behaviour on some sprites with 2 being the first, default behaviour and 3 being the secondary behaviour (that feature is often refered as the "extra bit").
In fact, there even exists a vanilla sprite with that feature: The goal tape. Both, the normal and the secret goal are the same sprite but the extra bit controls the exit it activates (of course, instead to enter 2 or 3 to that field, you have to put 0 or 1 for the goal tape).
The rest is irrelevant and can be leaved alone.
If you have done it correctly, a sprite on the top left corner (or whatever you have put for the coordinates). It will look like an X in Lunar Magic but since Lunar Magic doesn't reflect on how the sprites look actually in-game, this shouldn't be a problem. If it bothers you, you can try to create a Sprite Display File even though it can be quite complicated.
After you set up the graphics, try to place a Hammer Bro and two sidways Piranhas (each facing in different directions) into your level. If you have successfully done this, it should look like this:
Some sprites also requires another sprite to be inserted because they spawn a different sprite. The Boomerang Brother is one of them. In order to use them properly you also must insert the boomerang. A look into the ASM file reveals which number you have to chose for the projectile (that's because different sprites uses different methods to determine the new sprite's number). The answer lies below.
Finally, the "global" refers that these sprites can be used in all levels in contrast to the "local" sprites whose code and data is level dependant.
Bowser want to place a couple minions in the level. Except it turns out that the minions in question are Koopas even though they were supposed to be the Brother enemies.
In a cave, he wants to use sideways Piranha Plants but he has no idea to have them coming out of right pipes.
He also want to place a Boomerang Bro but it turns out that they won't throw boomerangs but other enemies.
Sprite Insertion (Local)
PIXI also allows the use of "local" sprites, sprites whose code and data is dependant of the level. Global sprites are such sprites which you can access from all levels. That way, you can have more sprites then you had with Romi's spritetool without relying on weird tricks.
Anyway, the insertion of local follows in a similar style as global sprites with one exeption: You have to enter the level number. The format is following:
"<Level>" is the level you want to have the sprite inserted.
"<Number>" is any number between B0-BF.
"<Sprite>" is simply the CFG/JSON file.
In addition, local sprites needs to be activated at first too. Open pixi.bat and add between "pixi" and "%1" a "-pl" (without quotes as it should be). pixi.bat should look like this:
Once again, there is an example on how to use local sprites with inserting the Boomerang Brother for level 105 and the roto disk for level 106:
If you place sprite B0 into level 105, you see that it's a Boomerang Brother but if you go to level 106, it's a roto disk instead despite both sprites using the name number.
Whether you put sprites as local or global doesn't really matter. It only gets important when the sprite in question spawns another sprite and its number isn't dependant of the mother sprite's number.
Here is another image for reference:
Luigi wants to use a roto disk which only should exist in level 105. However, PIXI complains that the sprite number is invalid.
As mentioned above, PIXI supports shared subroutines. The idea is that some routines are found in almost every sprite. Which is especially problematic for a couple routines like the large GetDrawInfo or SubOffScreen. Before PIXI, you had to use an external patch. PIXI doesn't require that since it has integrated that feature and can be use in sprites.
Now, I won't write about how to create them (that's a tutorial for the programming part) but on how to insert them. The idea is simple: There often is a readme which explains what file belongs where and routines simply belong to the folder "routines". That's it. Alternatively, you can insert this sprite without the shared routines and look what error appear. If a macro is missing and apperantelly has got the same name as an ASM file, it's this one you have to put in "routines".
Sprite Insertion (Shooters and Generators)
The next two kind of sprites are from different types: Shooter and generators. They belong to an own kind of sprite and such works differently, including the insertion. Here is a short list:
They don't feature any tweaker bits (see below) or property bytes but they still have got the extra bit.
Shooters use numbers C0-CF, generators D0-DF.
All of them are global.
They belong in their own folder (shooters in "shooters", generators in "generators".
You can only have eight active shooters (obviously, they disappear if they're too far off-screen) and one generator at time.
Other then that, the procedure is the same as with regular sprites.
Have fun with them:
Bowser Jr. want to use a vertical Bullet Bill shooter. However, it doesn't nothing or worse yet, crashes the game. Here is the list:
After he entered the correct sprite number, PIXI complains that it couldn't be opened even if it is located in the folder "sprites".
Final note: Generators are a depreciated feature and gets slowily replaced by UberASM. Finding them, especially on SMWC can be difficult. They still have got their uses, though, namely in controlling an effect for a certain area like an enemy generator.
Sometimes, you want to edit some sprite properties but don't know where to look at the ASM file. Thankfully, most of them aren't really hardcoded in the ASM file. Instead, these properties (also known as tweaker bits) are controlled in the CFG/JSON file which is easier to edit and also saves bytes.
You can open CFG files with a notepad but it is more of mess of data. Instead, you use a second tool which PIXI has included, the CFG editor. It is specifically made to edit the CFG files (JSON files, despite being readable, also work). Here are a couple setting which interest non-programmers and some sidenotes:
Can be jumped on: If checked then you can jump on this sprite without getting hurt (think of non-spiked enemies). This only applies if "Don't use default interaction" is unchecked.
Disappear in a puff of smoke: Some sprites like Piranha Plants does this when they're killed.
Use second graphics page and Palette: Most sprites' tile colours and page number can be edited on the CFG. That being said, some sprites still hardcode them in the ASM file.
Disable fireball killing: Mario's fireballs disappear in a smoke when they hit this sprites.
Disable cape killing: No interaction with cape at all.
Invincible to star/cape/fire/bouncing blk.: Regarding the fireball immunity, the sprite simply stops interacting with them. And Bomb-Ombs and Yoshi's stomp (due to being technically a bounce block) can't hurt these sprites too. Otherwise, it's selfexplaining.
Process when offscreen: But remember to use these sprite sparingly as they fill up the sprite slots and cause slow downs quickly.
Inedible: Yoshi simply can't eat it. That's it.
Stay in Yoshi's mouth: But remember to only use it for carryable sprite. The sprites Yoshi will spit out are in the stunned or kicked state which can cause glitches on these without a stunned routine.
Don't turn into a coin when goal passed: Keep in mind that sprites will still disappear if they haven't checked "Don't erase when goal passed" too ‒ they simply won't give you any coins.
Don't erase when goal passed: This only gets applied if you have checked "Don't turn into a coin when goal passed" too. Otherwise, this does nothing.
Can't be killed by sliding: But only if "Don't use default interaction" is unchecked.
Don't turn into a coin with silver POW (read: silver P-switch)
Extra Property Bytes: In order to save ASM space, some sprites will change their behaviour depending on these two bytes. For example, some custom Koopas will change their behaviour independantly from their palette and use these bytes instead. The second byte has got an extra function but that's only interesting for programmers.
Keep in mind that many extra property bytes also work bitwise. There will be a chapter later explaining what it means.
For the rest, only use them if you know what you're doing (e.g. if a readme tells you so).
One example which shows a tweaked custom sprite is e.g. hammer bro whose palette is changed to palette F and is unstompable:
(Of course, nothing stops you from copying these files and have two different versions of sprites. In fact, having multiple CFG/JSON files of a sprite is why tweaker bits exists in the first place.)
Peach wants to change a sprite's colour but for some reason, it just don't work.
She also has another one but don't want it to get removed when Mario hits the goal. For some reason, the sprite still turns into a coin.
Finally, she wants to use a couple custom shelless Koopas in the level. She knows that the behaviour is independant from the palette but in the end, she has no idea, how to change it.
One of the more powerful features PIXI has got are extra byts. Before that, only Tessera ever made great use of it. To explain what this one does: When you place a sprite in Lunar Magic, it inserts three bytes of data into the ROM containing position, sprite number and extra bits. Lunar Magic allows you to increase the sprite size, though, which is what we call "extra bytes". That way, you can insert sprites with different behaviour without different ASM files (or CFG files for that matter).
The usage get's a bit more complicated then usual. Let's take a look at the insertion window again:
The extra bytes are set in the extension field.
However, there are a couple stuff to keep in mind:
Extra bytes makes the sprite load data larger. That causes one notible issue: The game and Lunar Magic have to read more data from the sprite but doesn't know when the data already belongs to the sprite. Which means, if you change the amount of extra bytes the sprite can have or replace the sprite with another one of a different size, it can easily mess up your level data. Here is it what I mean: A1 A2 A3 A4 B1 B2 B3, where Ax is the first sprite and Bx the second one. Sprite A has got one extra byte, sprite B none. If you shrink down A's number of extra bytes to none, the game reads the data like this instead: A1 A2 A3 B1 B2 B3 C1" which means it reads A's former extra bit as B's first byte in the sprite loading data. This isn't an issue with local sprites, though, which permanently use four extra bytes.
It is a bit difficult to enter the number. More specificially, the values you have to enter are often bitwise. See the next chapter to understand what it means.
Now, we go into something more technical. This is where we explain, how to write the correct value for the extra bytes, extra property bytes. In case you didn't know, most kinds of computer (at least in the classical definition which also included consoles) calculates in dual or binary (there were attemts with trinary computers but these were inferiour to binary computers). Each digit in binary is called "bit". Eight bits equal one byte.
The problem is to get the correct value. To get some help, we use some kind of calculator, preferable these made for programmers. The Windows calculator has this mode so I'll use that. Keep in mind that you have to switch to programmer mode (scientific in older versions) so that you can use binary numbers. Programmer calculators also have got the property to set the value bitwise.
Anyway, here is a look at the calculator:
The sprite we want to explain the bitwise stuff are Shellless Koopas. Opening their ASM file and you find out that their behaviour is controlled by the extra property bytes. Specifically, it allows you for eight options. You take a look at line 5:
In binary, its format is [dgrh jfls]
What this means, you can assign each bit a flag. We take a look at the two most rightward groups of bits at the most bottom row. Here is the image of the calculator, marked in blue:
Thise are the bits you have to enter. Setting a bit to one means, the property is activated, if reset to zero, it's disabled.
You then have to make sure the value you got is in hexadecimal et voilà, you got the value you can to enter in the CFG editor for the Shellless Koopas' properties.
However, the usage isn't always as easy as the Shellless Koopa are.
We first have to explain, how bits are handled: The most right bit is called "bit 0", the bit to the left is "bit 1", then "bit 2", and so on.
The reason why we start with zero and not one is because of the bits' values: It's 2 to the power of n which where "n" is the bits position (for anyone who don't know what a power is: It's a simply repeated multiplication unless it's 0 in which the value usually becomes 1). As such, bit 0 has got the value 1, bit 1 the value 2, bit 2 the value 4, etc.
It also explains, why the numbers below the bits, are multiple of fours and the value hasn't been added with one.
Our next example are Para-Beetle. This is where our definition comes handy as instead to talk with flags, it uses a discription. It also uses groups of bits. But don't worry, the procedure is similar. You have to mark these (in your head). I have got some help with a graphical image of the calculator:
The problem is how to set the direction for the Para-Beetle as the values are written in decimal and in binary, only 0 and 1 as digits exits. But don't worry, you know how binary numbers work: Bit 0 controls the ones and bit 1 the twos. You such have got the amount of four possible states:
If you don't want to convert between decimal and binary (e.g. because you don't know how to or the numbers become unhandy), you can use the calculator instead. The only problem is that not all groups of bits start with bit 0. Some are in the middle of the bytes. But don't worry, your job is to adjust the value with the help of bit shifting. Bit shifting is nothing more but a multiplication or division by 2. The buttons for bit shifting are often called Lsh and Rsh or X<<Y and X>>Y (the former is bit shifting to the left, the latter to right) which is what you have to use them. After clicking on it, you have to enter the value for the smallest bit in the group (e.g. if a group consists of bits 3-6, you shift the amount of bits by 3 bits).
If you already have a value on the calculator, there is an easy way to go around with it: You add the values or "OR" them together (a bitwise OR is simply merging to bytes together where the final byte has all bits set which were set in either byte 1 or byte 2). Bit shifting comes before bitwise operators so there is no need to use paranthesis (brackets) but you can add them for safity.
Music porters knows this from the hexadecimal opcodes which work similar to that (e.g. ADSR uses two bytes of which the first one controls attack and delay and the second one sustain and release).
If you find this chapter confusing, then I'm sorry for that!
If you have a better way to discribe this chapter then feel free to do so!
Sprite Insertion (Cluster and Extended)
PIXI not only allows you to to insert sprites, shooters and generators but also cluster and extended sprites. To explain what these sprites types are, these are sprites which you cannot place in the level directly but are rather generated by other sprites. Cluster sprites use a special sprite type called "cluster generator" (not to be confused with regular generators) whereas extended sprites by regular sprite (the Mario's fireball by, well, Mario). Now, here are the applications of these two sprite types:
Cluster sprites are extrememly simplistic. That's because they're supposed to run without slowing down the game too much (thus explaining the sprite type). A list of cluster sprites can be found here.
Extended sprites are mostly projectiles and sometimes effects in case minor extended sprites don't work. A list of extended sprites can be found here
Anyway, the insertion is following:
The extended and cluster sprite list is shared with the regular sprite list but the insertion is even more different as you have to switch between their modes (the reason you don't have switch between shooter and generator mode is because it was such in Romi's sprite tool and also because you can place them directly inside the level). In order to use cluster mode, just stick "somewhere" (by which I mean not in the middle of the sprite list) a "CLUSTER:" and the sprites you insert below are all cluster sprites, for extended mode, "EXTENDED:" and to switch back to the regular list, use "SPRITE:" instead (all without quotes).
Neither cluster nor extended sprites use CFG files. They're purely ASM files. (Generators and shooters still use them but that's simply a leftover from mikeyk's Sprite Tool.)
With this knowledge, let's try to insert the fish cluster effect included with PIXI. The caller files are found in "cluster spawner" in the regular sprites whereas the cluster sprites in "cluster". Open fishspawn.asm to see which number the fish cluster sprite has to be. After you have found the correct number, here is how the list can look like:
The procedure is similar to extended sprites. The only issue is that no included sprite uses a custom extended sprite but you can download any other sprite (and this includes one of the Bro enemies).
Anyway, want an image for this effect? Here you are:
That's it. Inserting cluster and extended sprites isn't that much different than inserting regular sprites, shooters and generators.
Peach finds the level lacks some effects. She uses the cluster flower effect. After successfully inserting the sprite, the game crashes or the flowers won't appear. Nothing is wrong with both codes, btw.
She had put flower.asm but uh oh, PIXI complains! Here is how the list looks like:
00 cluster spawner/flowerspawn.cfg
It still complains! Why couldn't the insertion of cluster sprites be easier!
There is one type of custom sprite which isn't inserted as any of PIXI's sprites. It's the poison mushroom.
The poison mushroom is actually a hijack on an unused sprite in the original game (by default $85). You can open "Poison.asm" in the folder "asm" and edit some properties but other then that, you can't do any major edits on it.
And because it hijacks a the vanilla sprite table, the extra bit must be set 0 and not 2 as you would have done on regular custom sprites.
Finally, you have to patch poison.asm manually as PIXI doesn't insert it to your ROM it.
Be careful that once you have applied the poison mushroom into the ROM, it stays there, even when changing the number and repatch poison.asm.
If done successfully, you get something like this:
Now you can do all nonsense with that thing like placing it in ?-blocks or placing it inside the level.
Bowser is evil and wants to add a Poison Mushroom. Except when he tries to place a poison mushroom, a weird... thing appears. He even checked that the sprite number is really 85 and it is.
Now the weird thing won't appear. Instead, the game crashes.
Error and Crash Handling
Not everything is fine. Here are a couple problems:
TRASM sprites: Before PIXI was a thing, Sprite Tool was the local sprite inserter. That being said, it supported two assemblers: Xkas (and the latest version Asar) and TRASM. That being said, the latter had a very different syntax from the former two (ASM itself is mostly unchanged, just the assembler commands). As such, sprites using that tool are incompatible which unfortunatelly includes a list of sprites on SMWC and (older) sprites on other sites likely won't be Asar-compatible too. Luckily, you can convert TRASM sprites to Xkas with Trashkas (included with PIXI) which uses a similar syntax to Asar.
JSR (Label,x): There is a bug in Asar where it can't compile this command, no matter the label. There is a simple fix, though: Just replace the "JSR" with a "JSR.w" and sprite should compile. This has to do that Asar tries to compile it with a long address ("JSR.l ($xxxxxx,x)") even though this command doesn't actually exist, only absolute ones ("JSR.w ($xxxx,x)") do.
incsrc/ incbin: A problem mostly common on dynamic sprites. This one isn't bug but a different way on how both assmeblers determine the mother directory when using these commands. Simply remove "sprites/" from the incbin/ incsrc inside the sprite (just search for "incsrc"/ "incbin" to get to the erronous line). This has to do with the reason that Xkas (and TRASM for that matter) uses its directory as the mother directory whereas Asar the directory of the file which has got the incsrc/ incbin instead. That means, xkas searches in the directory it's located for the folder "sprites" (which usually exists) first and then for the e.g. graphics file whereas Asar searches for "sprites" inside another "sprites" (i.e. if the directory where PIXI is located is "PIXI", Asar tries to go to "PIXI/sprites/sprites") (which usually doesn't exist unless there is one for some reason).
No sprite can be inserted with the number 7B. That's because Lunar Magic expanded the goal tape to support up to four exits and that requires both extra bits and as a result, no custom sprite can be inserted in that place.
SA-1: This problem is similar to the TRASM problem: Not all sprites supports SA-1 natively so you can use the SA-1 converter (again, included with PIXI). If there are some conversion problems, please post it in eitherof these threads.
If you see any sprite which you just can't insert, crashes the game or notice any other problem, it's important to report it.
Wario wants to insert some random sprites except multiple errors appear. Most of them have got stuff like "Invalid Number", "Label XXX not found" and "Unknown Command".
Wario wants to insert a dynamic sprite instead. He run it though TRASHKAS but there is an error that a file couldn't been opened.
For Errors, I'd recommend adding a section for incbin/incsrc file not found. As pixi handles the working directory differently than romi's sprite tool. (Pixi has a temp asm file in the main directory which runs a an incsrc on the target sprite where romi's copies the sprite code into the temp file)
-------------------- Anime statistic on MyAnimeList:
400 animes completed ✓
6000 episodes completed ✓
100 Days completed ✓
... what even am I doing with my life?
I barely started, I already have 2 issues
- I don't really get the part with the batch file. No idea what to do and how to do it.
- I can't open "list.txt" since I have no such file
Not the best of starts
- I don't really get the part with the batch file. No idea what to do and how to do it.
Open notepad or any other text editor.
Copy the code in this thread an paste it into the editor.
Save the file as a batch file. That means, you when save it,
remember to use "Save As..." and chose either batch file extension or "All Files". Remember (if or especially if you use All Files) to attach the extension ".bat" (without quotes) at the end of the file too.
Originally posted by Romano338
- I can't open "list.txt" since I have no such file
Does anyone have a basic explanation on how the extra bytes work? I know they're supposed to be binary (represented in hex), but is there anything else to know about them? In particular, I don't know what the "Extra Bytes Count" option in the CFG editor does.
I don't know what the "Extra Bytes Count" option in the CFG editor does.
It tells the game (and Lunar Magic) how many extra bytes a sprite uses. If you put a 1 there it'll use 1 extra byte, if you put 2 there it'll use 2 etc (up to 4 extra bytes are supported)
I know they're supposed to be binary (represented in hex), but is there anything else to know about them?
I'm not sure what you mean.
If that's a complicated way of saying that it's a number then yes.
If not then idk.
The extra bytes are simply extra numbers a sprite can use. In Lunar Magic there is a field where you can set the extra bytes of a sprite.
The sprite itself can then load what you entered and do stuff with it.
Common uses are for variable effects like speed of a sprite or what sprite it spawns, but it can be used for anything.
When I try to insert a sprite and change the extension to FF, it instantly reverts back to zero. Why does this happen and how do I fix it?
The extension only applies for sprites with at least one extra bit. Sprites without these can't make use of it.
Moreover, the value isn't limited to just 0xFF but in theory infinitily high because you can set the sprite to infinite size (again, theoretically).
Yeah, it's a problem with the rain cluster sprite. But you can easily fix that: The RTS in the code is supposed to be an RTL.
A similar problem accurs with the sandstorm which has got the same problem.
And as a tip for the others: If the game crashes no what you do, try to insert other sprites to see if the crash happened because of the sprite itself and not because you inserted it wrongly.
That's not a code, it's a piece of a code (i.e. not enough to see how to fix it).
Anyways. The problem was some faulty conversion or sprite had a faulty code regardless of TRASM or Asar. Can you give us a link to the sprite? If not then post the code of the whole sprite and I'll on that. But please, if you give the code, don't add it to your post but link it from somewhere!