Machine code Mario

Machine code Mario

Here’s an image of Mario, drawn using the machine code for Super Mario Brothers. Created using C++, the EasyBMP library and the GIMP. Source code after the break.

This program reads in a ROM file, and creates an image out of it using the specified aspect ratio. Each byte is drawn as a column of 8 pixels, which are arranged into rows and then columns to fill the space. Once the image is generated, I created the color overlay in GIMP by resizing and placing a sprite from the game in a separate layer, with mode set to ‘Screen’.

#include <iostream>
#include <fstream>
#include <cmath>            // for square root
#include <sys/stat.h>       // For file size
#include "easybmp/EasyBMP.h"
 
int main(int argc, char** argv) {
    // Rom info
    char fileName[] = "smb.nes";
 
    // Desired aspect ratio
    float aspectRatio =  1.333;
 
    // Determine the file size
    int romByteSize = 0;
 
    struct stat results;
 
    if (stat(fileName, &results) == 0) {
        romByteSize = results.st_size;
    }
    else {
        std::cout << "Sorry, could not determine file length!" << std::endl;
        return 1;
    }
 
    // Determine the height and with to achieve the proper aspect ratio
    // we know:
    //    h/w = aspectRatio/8
    //    h*w = romByteSize
    // So:
    //    h = aspectRatio*w
    //    h = romByteSize/w
    //    w^2 = romByteSize / (aspectRatio/8)
 
    int imageWidth = (int)(sqrt(romByteSize / (aspectRatio/8))+.5);
    int imageHeight = (aspectRatio)*imageWidth - (int((aspectRatio)*imageWidth)%8) + 8;
 
    std::cout << "romByteSize=" << romByteSize
              << " imageWidth=" << imageWidth
              << " imageHeight=" << imageHeight
              << std::endl;
 
    // Open the binary
    std::ifstream myFile (fileName, std::ios::in | std::ios::binary);
 
    if (!myFile) {
        std::cout << "Sorry, couldn't open file for reading!" << std::endl;
        return 1;
    }
 
    // Create a bitmap to hold the image
    BMP Output;
    Output.SetSize( imageWidth, imageHeight );
    Output.SetBitDepth( 1 );
 
    // Copy the image data over, byte by byte
    RGBApixel blackPixel = {0,0,0,0};
 
    for (int pos = 0; pos < romByteSize; pos++) {
        char byte;
 
        if (!myFile.read (&byte, 1)) {
            std::cout << "read error, bailing.  pos=" << pos << std::endl;
            return 1;
        }
 
        int Col = pos%imageWidth;
        int baseRow = (pos/imageWidth)*8;
        for (int i = 0; i < 8; i++) {
            if ((byte >> (7-i)) & 1) {
 
                Output.SetPixel( Col, baseRow + i, blackPixel );
            }
        }
    }
 
    // Then write it to a file
    Output.WriteToFile( "rom_image.bmp" );
 
    return 0;
}
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>