Close
0%
0%

SNES Mario Paint Art Extractor

Transfer works of art from a Mario Paint cartridge onto an SD card

Similar projects worth following
Mario Paint, released for the Super Nintendo in 1992, allowed the user to create pictures, animations, and music on their television. Only one composition could be saved at a time, compressed onto the 32kB SRAM chip in the cartridge. Back in the day, the supported method of archiving your works of art was to connect the SNES to a video cassette recorder. Thirty years on VCRs are long gone, but we can build a device to read the cartridge's SRAM chip directly, decompress and extract the images, and save them to a modern SD card instead.

Initial exploration and testing of software is being done on computer, using the .srm Save RAM file from a SNES emulator. Once the structure of the .srm file is well-documented, and the relevant data can be decompressed and extracted, the code will be ported to a microcontroller, and expanded to read data from the SRAM chip to an SD card.

In the physical build, an LCD display will show the decompressed image that has been extracted from the cartridge.

The initial focus is on extracting the background picture, and saving it as a PC-compatible image. Future scope may include extracting animation frames, and/or recreating the full animation in a PC-compatible file (e.g. a GIF).

Processing and recreating the music is not a main focus of this project. Others have already done significant work on reverse engineering the music composer and its save format. It will, however, be possible to dump the music data, and potentially convert it into a suitable format on PC.

HelloWorldScreenshot.png

Snes9x emulator showing an image made with pen and stamps, ready for saving to SRAM

Portable Network Graphics (PNG) - 21.00 kB - 07/29/2023 at 22:03

Preview

HelloWorld.gif

GIF image extracted from an SRAM dump, as a proof of concept

Graphics Interchange Format - 2.52 kB - 07/29/2023 at 22:03

Preview

  • Exploring The Decompressed SRAM

    ansbaradigeidfran07/30/2023 at 12:55 0 comments

    The general layout of the decompressed SRAM is as follows:

    • 0x00000 to 0x057FF: Animation slides
      0x05800 to 0x05FFF: Animation path and settings
    • 0x06000 to 0x0B7FF: Background image
    • 0x0B800 to 0x0BA3F: Music track
    • 0x0BA40 onward: Music settings

    The music track and settings are structured as described by BoodaW at NesDev.

    The SNES uses bitplanes to store images, and follows the same approach in saving a Mario Paint image. (The series of YouTube videos on Super NES Features by Retro Video Game Mechanics Explained is a good primer on how this works.) Mario Paint images have fifteen colours (plus transparency), so are stored as a 4 bit-per-pixel bitplane.

    The colour pallette is as follows:

    • 0x00: Transparency
    • 0x01: Red
    • 0x02: Orange
    • 0x03: Yellow
    • 0x04: Light Green
    • 0x05: Dark Green
    • 0x06: Cyan
    • 0x07: Blue
    • 0x08: Maroon
    • 0x09: Brown
    • 0x0A: Pink
    • 0x0B: Purple
    • 0x0C: White
    • 0x0D: Black
    • 0x0E: Dark Grey
    • 0x0F: Light Grey

    This order nearly matches the order of the colour selectors on-screen when using Mario Paint, but note that White is in a different location. (It is positioned right-most inside Mario Paint.)

    The background image is generally known to have an area of 248x168 pixels. This is indeed the visible image, but the images is actually stored (in Save RAM and also in the SNES' Work RAM) as a 256x174 pixel image, with a four-pixel transparent border. This allows the image to be stored as a series of 8x8 tiles: 32 across, 22 down.

    The transparent border allows the picture to be centred on the TV, while still using the SNES's native tile layout. This border is replaced with a black & grey frame in-game, which can turn red depending on the user's actions.



    The animation frames are stored in another 256x174 pixel bitplane, at offset 0x0000. The same bitplane is used for 4, 6 and 9-frame animations: the bitplane is subdivided according to the number of frames being used.Individual frames can be addressed by selecting the appropriate tiles from the bitplane, and have their own 4 pixel transparent border surrounding each frame. There is some additional transparency at the edges of the bitplane when 6 or 9 animation frames are used, to keep each frame the same size. The 6-frame bitplane has eight transparent pixels on the left and right sides (instead of 4). This means there's a whole column of unused/transparent tiles on either side of the bitplane when using 6 frames. The 9-frame bitplane is likewise, but has an extra 8 pixels of transparency along the bottom (one whole row of tiles).

    Counting tiles from top-left, the relevant tiles for each size of animation frame is:

    • Large (4 frames): (0,0) to (15,11),   (16,0) to (31,10),   (0,11) to (15,21),   (16,11) to (31,21)
    • Medium (6 frames): (1,0) to (10,10),   (11,0) to (20,10),   (21,0) to (30,10),   (1,11) to (10,21),   (11,11) to (20,21),   (21,11) to (30,21)
    • Small (9 frames): (1,0) to (10,6),   (11,0) to (20,6),   (21,0) to (30,6),   (1,7) to (10,13)   (11,7) to (20,13),   (21,7) to (30,13),   (1,14) to (10,20),   (11,14) to (20,20),   (21,14) to (30,20)

    From 0x5800 to 0x5FFF, information is stored about displaying the animation frames on the background image.

    Animations can be set to display at a particular point, or along a given path, by drawing a path of pixels in Mario Paint. This information is stored from 0x5800 onwards; a maximum-length path occupies bytes up to 0x5FF1. Each path pixel appears to require three additional bytes (after an initial zero-byte). The number of path pixels is stored at location 0x5FFA.

    Location 0x5FF8 indicates the layout/number of animation frames in use. 0 indicates four frames, 1 means six frames, and 2 means nine.

    Location 0x5FFE stores the speed at which the animation can run, from speed one (0x000) to thirteen (0x0C00).

    Location 0x5FFC seems to hold some data (often 0x0100), but its purpose isn't yet clear. There's no clear use for bytes 0x5FF2 to 0x5FF7.

    I've yet...

    Read more »

  • Motivation and Initial Investigations

    ansbaradigeidfran07/29/2023 at 21:53 1 comment

    A short while ago, I bought a copy of Mario Paint (plus SNES mouse) as a birthday gift for my budding young artist. I'd not played this title when I was young, so this was my first exposure to it too.

    They had a play around with it, and having drawn their first artwork, they asked me to print it off for them. The explanation that it couldn't be printed off the TV, and the fact that only one picture could be saved, didn't cut the mustard.

    I'd learned that the image was compressed and saved onto an SRAM chip inside the cartridge. Wiring up a microcontroller to read the contents of the SRAM chip (with a suitable connector for the cartridge) would be straight-forward, but the challenge lay in interpreting the compressed data and extracting the image.

    Initial searches online turned up a partial disassembly of the Mario Paint ROM, which didn't include the portions for saving and loading images. I am passingly familiar with 6502 assembly (the little brother to the SNES' processor), but wading into a full ROM disassembly didn't appeal.

    The music composer of Mario Paint (and the in-game music) has a bit of a cult following. B00daW collected some findings on reverse engineering the music composer on a NesDev forum thread. He credits HertzDevil for identifying the compression algorithm as a combination of LZ77 and Huffman encoding, and attached a Lua script to decompress and extract the music from an SRAM dump.

    However...

    Mario Paint saves both the image and music (and animations) when prompted by the user. If they are saved and compressed at the same time, it would be sensible to compress them together to maximise the compression ratio.

    On running the Lua script on a sample .srm file, I was greeted with a 47kB output file, far larger than needed for the music alone. Using B00daW's notes I identified the region where the music was stored, leaving lots of space for the image to be hiding in. Armed with a SNES emulator and some spare time, I started creating images and searching the decompressed data with a hex editor to search for my simplistic works of art.

View all 2 project logs

Enjoy this project?

Share

Discussions

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates