Language…
8 users online: Fnaftendo, Golden Yoshi, Hot Sauce, JinRokhZenobi,  RussianMan, ShoopDaWhoop, SomeGuy712x, thegonzalex - Guests: 132 - Bots: 152
Users: 69,725 (2,526 active)
Latest user: ariahks

Apollo

Super Mario WorldToolWork in ProgressScreenshotsVideos

TL;DR
I built a tool that started as a graphics ripper but evolved into something much more.


Background
About a year ago, I joined this community and decided to try my hand at building a hack. I had a vision, but I quickly realized that the process would be painfully slow due to the need for custom assets. Existing tools like YY-CHR and GraphicsEditor felt too tedious, so I asked myself: Can I programmatically create a GFX file from a PNG image?

Thanks to the wealth of resources on SMWCentral, I found the answer to this question(and about a thousand other questions since), and I wrote a Python script to do just that. Soon, I expanded it to generate Map16 files as well. While using it for my hack, I realized I was still spending too much time for my liking manually placing tiles in Lunar Magic’s Map16 editor. Given that many of my levels were just recreations of environments from other games, I thought: If I can generate GFX and Map16 files, why not generate entire levels too?

Introducing Apollo
Apollo is a tool that takes an image and converts it into all the necessary resources for a SMW level—automating the entire process.



Examples
Over the past month, I’ve been active in the #graphics channel on Discord, looking for opportunities to test Apollo. Most of the following examples—except for Peach's Castle—took about 10 minutes from downloading the image to having the level ready in Lunar Magic. The majority of that time was spent editing the original image and configuring resources.

Peach's Castle took longer because the source image had extensive shading and lacked symmetry, requiring manual edits in Aseprite to fit within six GFX slots. However, once that was done, converting the image to an .mwl file took only a few seconds.


City


Building


Water


Peach's Castle






Additionally, here are some images I pulled from The Spriters Resource this morning and imported into Lunar Magic in a few minutes using Apollo.

Barrel Cannon Canyon


SnakeMan's Level


Hyrule Castle


Mt Woe





See Apollo in Action!
Here’s a video I put together of me recreating level 106 by exporting it from Lunar Magic, and then reimporting it into 107 via Apollo.






Sprites
Apollo handles sprite GFX generation and insertion much like Layer 1 and Layer 2—no problem. But I’ve been pushing this further. My hack relies heavily on custom sprites, and after learning how to code them, I quickly realized I didn’t want to do it repeatedly.

So, I developed an ASM library to work with the resources created by Apollo. With this system, adding new sprites only requires implementing their state behavior—while the library takes care of collision detection, graphics, and state lifecycle.

This works through a set of subroutines implemented using SharedSubroutines. Additionally, it leverages the following patches for fine-tuned sprite control:

- Better Platforms
- Custom Sprite Clipping
- Custom Object Clipping

Note
Apollo does not insert ASM into the ROM. It simply generates a .mwl file and imports it into Lunar Magic using its -ImportLevel CLI command. The shared subroutines and patches mentioned above are simply part of a custom ASM library I wrote for my hack. (I might release it as a patch if there’s interest.) Apollo’s role is to generate sprite GFX and ASM tables representing the sprites, while my library handles everything else.

Example
Here’s a video of me taking the Batadon sprite from SMWCentral and reimplementing a small subset of its behavior via Apollo—covering graphics, collision detection, and movement.




Another Example
Here’s a more complex sprite I’ve been working on. Keep in mind that much of my ASM library is still a work in progress, with plenty of rough edges. This example is mainly to demonstrate how Apollo can take a detailed Aseprite image and convert it into usable resources for coding sprites.






There are a lot more things I could add/share but I’m running out of time. I may update this post later with additional content if the interest is there. Happy to answer any questions you have.

Hope you all have a great C3!
Holy shit, it looks like the ripping game has reached another level. It's been a decade since I've ripped graphics, but seeing new technologies in that area (any hacking area for that matter) is always appreciated.
Excellent job! The graphics displayed here all turned well.
Please check out BOWSIE!
i shouldn't have ever been calling it love.
This is astonishing work. I remember making Mario World levels in MS Paint almost 20 years ago now, and it's buck wild to think that the scene has advanced to the point where levels could be generated out of images like them. Unreal.

Now I'm a little curious though - how does this handle the odd case where things aren't lined up right? If sprites are misaligned by a pixel here or there, or if a block has more than 16 colors in a tile. Also, could you go into a little more detail on how the auto 'acts like' assignment works?


Other Submissions of mine!
Hopefully, I can rip title screen with Apollo
Overworld Design Contest 2025 After Nintendo Switch 2 Direct (Post-April Fools!!!)
Originally posted by Deeke
This is astonishing work. I remember making Mario World levels in MS Paint almost 20 years ago now, and it's buck wild to think that the scene has advanced to the point where levels could be generated out of images like them. Unreal.

Now I'm a little curious though - how does this handle the odd case where things aren't lined up right? If sprites are misaligned by a pixel here or there, or if a block has more than 16 colors in a tile. Also, could you go into a little more detail on how the auto 'acts like' assignment works?


Thanks! When it comes to layer1 and layer2, anything that happens to be misaligned by a pixel on the source image will just be generated as-is (i.e. a pixel off) in the level. There's just no way to be sure that a given 8x8 tile is meant to be the same as an existing tile, or if it's a new slightly different tile.
Sprites are trickier because the program knows about all possible sprites that could be in the layer ( any vanilla sprite + any sprite that has been defined in the config file ) but it has to "find" the sprites on the layer. It does this by finding all non-alpha tiles, and cross referencing them with the tiles from the sprites it knows about. Once it finds a match, it then does a BFS on adjacent tiles to confirm it's in fact the right sprite. For example, all the big koopa vanilla sprites use the same tile for their head, but have different color shells. So the head tile could be a match but the program can't be sure until it matches the entire sprite. The current impl only processes tiles at locations that are valid w.r.t to how you can place a sprite in LM. (i.e. at intervals of 16 pixels). In theory I could to the same kind of lookup at every pixel location but it would slow the program down exponentially and even if I did detect that scenario, it's still not a valid location w.r.t to lunar magic so I'd either have to shift the sprite to a valid location, ignore it, or throw an exception. The practical solution that I'll probably end up implementing is to just detect when tiles from that layer don't get mapped to a known sprite, and provide feedback to the user with an image of the sprite and (x,y) location so they can easily fix it.

A possible better solution overall would be to just paint the tile with the hex value of the corresponding pixi Id, similar to how I handle secondary exits. However, it makes the source image a little less easy to understand since you'd have to lookup the sprite by it's id in pixi if you ever forgot which sprite was there.




Palette coordination is one of the more complicated aspects of the program. I've gone through multiple iterations on the impl but the current one works pretty well. The way it works is:
1. First get the distinct sets of unique pixels for all 8x8 tiles.
2. Then eliminates any sets that are subsets of existing sets.
3. It then cross joins the remaining distinct sets against themselves to find which two sets have the highest overlap. It combines those two and then repeats this process. It repeats this step until the number of distinct sets of colors is less than or equal to the number of palettes the user has defined in the level config. At this point, it's very likely that many of the sets are greater than the 16 color limit.
4. It then takes all unique 8x8 tiles from the level and maps them to the palette that is a super set of its colors. What we end up with is a map of each palette to all the tiles that belong to it.
5. Finally, for each palette, it creates a new temporary image containing all of the tiles that belong to it, and then quantizes the image to 15 colors (excludes the alpha channel and then manually adds it post quantization)

The result of that quantization is what is used for the final palette.




The auto actsLike assignment is trivial for most vanilla tiles. I just have a reference file that contains all vanilla tiles, and encodes the LM tile id into it. From their it's just a hash lookup of tiles in the level to get their corresponding acts like id. Some vanilla map16 tiles share the same image and I don't currently have anything that handles those, but I have a few ideas how it could be done. Since this started as just a tool to streamline my own process, and the hack I'm working on doesn't use any vanilla tiles/sprites, I haven't really bothered implementing features to support them. In fact most of the stuff demo'd in the post related to vanilla resources was thrown together this week for C3 :).

Custom tiles are tricker since the actsLike has to be provided by the source image. I do this the same way I handle secondary entrances. There's another layer(two actually, one for layer1 and one for layer2) that can be included in the aseprite image for actsLike values. You just paint the tile in the actsLike layer with the hex value corresponding to the actsLike for the tile occupying the same (x,y) location in layer1/layer2. e.g. if you wanted the tile to act like a cement block, you'd paint the tile #000130 in the actsLike layer.
It's a bit of added overhead to setting up the source image but it's completely optional. If you were just using Apollo to import an image with custom tiles into LM there would be no reason to use it as LM is much easier. I did write an aseprite plugin that provides some support, for example you can select one tile and assign an acts like value to all identical tiles, but aseprite's plugin api is limiting and it's not near as proficient as LM. I tend to create a lot of new tiles while building levels so it's useful for me in that I can just create the level in aseprite and not be limited to a set of gfx files, and then quickly import into LM when I want to playtest.
Interesting tool.

Is Apollo compatible only on Mac or we can use it on Windows too?

Can we even port levels from Master System games, Megadrive games, PC-Engine games, etc...?
- Current game playing: Final Fantasy VII Rebirth (PS5)
- Last game completed: The Legend of Zelda: Twilight Princess (GC)

Currently working on The Mario's Greatest Adventure, Mario & Stitch: Part I and Super Mario World Re: Master Quest 1. My next projects will be Mario & Stitch: Part II, Mario & Stitch: Part III (MSU-1 only)
List Graphics. OLDC 2021.Online BG Ripper.
I do notice a curious tool here. While it is promising, I do have 1 question. The City, Building and Water screens do use more tiles than what the SNES could handle, but I'm mistaken since those are in the hack as a BG perhaps. How many tiles do those BGs use?

interesting tool! GG
This is insane! Also does it support ExGFX Rev and will there be a download for rippers?
Check out my DKC rips!

OMG HI DANNY!!! I remember ironing out that Peach’s Castle tileset with you, had no idea you had all this going on behind the scenes
Love what you’ve done with this, hopefully this tool proves useful for ripping
"What's 9 + 10?"
-Jah
Originally posted by Brutapode89
Interesting tool.

Is Apollo compatible only on Mac or we can use it on Windows too?

Can we even port levels from Master System games, Megadrive games, PC-Engine games, etc...?


It's compatible on Mac, Windows, and Linux.

It's not specific to any gaming system. It can rip any image as long as the unique number of 8x8 tiles contained within the image is less than 6 gfx slots each.




Originally posted by Rykon-V73
I do notice a curious tool here. While it is promising, I do have 1 question. The City, Building and Water screens do use more tiles than what the SNES could handle, but I'm mistaken since those are in the hack as a BG perhaps. How many tiles do those BGs use?

City uses ~4.2 gfx slots, Building and Water use almost the full 6 gfx slots.



Originally posted by Soul
This is insane! Also does it support ExGFX Rev and will there be a download for rippers?

What's ExGFX Rev?
It will be open source. It's in a github repo. I just need to clean up some stuff in the repo and then make sure the build/install instructions work for others. My dev environment is a bit unique, Linux + Windows VMs running inside an M1 mac(ARM64) , so I can't build/distribute binaries that will work any anyone elses system.
This is a game changing tool for ripping graphics. Do you have any estimate date for when a test build will be available for the public? My jaw dropped when I saw all these amazing rips. Also making graphics routine for sprites seems like a great feature, as well.




Originally posted by DannyLeeClark
Originally posted by Soul
This is insane! Also does it support ExGFX Rev and will there be a download for rippers?

What's ExGFX Rev?
It will be open source. It's in a github repo. I just need to clean up some stuff in the repo and then make sure the build/install instructions work for others. My dev environment is a bit unique, Linux + Windows VMs running inside an M1 mac(ARM64) , so I can't build/distribute binaries that will work any anyone elses system.

ExGFX Rev is a patch by edit1754 and yoshifanatic which enables using more exgfx in levels
Check out my DKC rips!

WITCHCRAFT!

This is truly a game-changer. I really want to try this out very soon! Well done.
Currently working on a new website. Don't expect any hopes soon. 『いけいけ団長、頑張れ頑張れ団長!』
Help us raise funds for the Armed Forces of Ukraine. #ДопомагаємоРазом / #HelpTogether
“Even if you personally are so dissatisfied with life that you want the world to end, surely the cruel reality is that it will continue on, unchanging. All the better for someone perfectly content, like me.”
Aya Shameimaru, Touhou Suzunaan ~ Forbidden Scrollery
Originally posted by Anorakun
This is a game changing tool for ripping graphics. Do you have any estimate date for when a test build will be available for the public? My jaw dropped when I saw all these amazing rips. Also making graphics routine for sprites seems like a great feature, as well.


Possibly now. I have a build but need to confirm distribution works so would need someone's help confirming they are able to run it. If you (or anyone else reading this) would be willing to do that, I can send it over.
A very impressive and useful looking tool! Can't wait for its release to check it out, it could be a huge game changer when it comes to ripping graphics into Super Mario World!
What!! This is so cool omg...

Watching the videos on how Apollo works in action is such a treat, I'm sure this will become a super useful tool for so many people. It seems very versatile too!

Awesome work on this, I'm looking forward to seeing where it goes from here.
What is a Lunar Magic, and can I eat it?
I'm waitng for this to be released,!

Super Mario WorldToolWork in ProgressScreenshotsVideos