Thread: Reducing size of C program to fit in qr code

  1. #1
    Registered User
    Join Date
    Aug 2020
    Posts
    2

    Question Reducing size of C program to fit in qr code

    I wanted to fit minesweeper into a qr code, which has a maximum size allowance of 3KB. As it stands, my program's binary is 12KB, and its object file is 3KB. I tried using UPX on the binary and managed to get it down to 6KB. I've been compiling with these commands: gcc.exe -Wall -Os -ffunction-sections -fdata-sections -c C:\Users\mlfre\OneDrive\Desktop\Minesweeper2\main. c -o obj\Release\main.o and gcc.exe -o bin\Release\Minesweeper2.exe obj\Release\main.o -s -Wl,--gc-sections -lKernel32 -lgcc -lmsvcrt.
    I have not attempted removing the default libs because whenever I do I get a lot of undefined reference errors, and have tried many ways but each 'solution' brings up even more problems. I haven't tried editing the PE headers because they seem very complex and I have not found a low-enough level explanation on how to do so. Although I did make sure to limit the header files I used to just windows.h. I know the libraries I need are kernel32 because most need to have that, mscvrt since its windows.h's library, and gcc because if I were to use -nodefaultlibs it would get removed.
    My code can be seen here:
    Code:
    #include <windows.h>
    
    #define WIDTH 100
    #define HEIGHT 100
    #define BOMBS 800
    
    struct xorshift_state {
      int a;
    };
    
    int xorshift(struct xorshift_state *state)
    {
        int x = state->a;
        x ^= x << 13;
        x ^= x >> 17;
        x ^= x << 5;
        return state->a = x;
    }
    
    void ExpandGrid(int fullGrid[WIDTH][HEIGHT], int knownGrid[WIDTH][HEIGHT], int blankPos[2])
    {
        int neighbors[8][2] = {{0,1}, {1,0}, {1,1},
                              {0,-1},        {-1,0},
                              {-1,-1},{-1,1},{1,-1}};
        int curTile[2];
    
        knownGrid[blankPos[0]][blankPos[1]] = 1;
        if(fullGrid[blankPos[0]][blankPos[1]] != 0) return;
    
        for(int blck = 0; blck < 8; ++blck)
        {
            curTile[0] = blankPos[0]+neighbors[blck][0];
            curTile[1] = blankPos[1]+neighbors[blck][1];
            if(curTile[0] > WIDTH-1 || curTile[1] > HEIGHT-1 || curTile[0] < 0 || curTile[1] < 0) continue;
    
            if(fullGrid[curTile[0]][curTile[1]] == 0 && knownGrid[curTile[0]][curTile[1]] == 0)
            {
                knownGrid[curTile[0]][curTile[1]] = 1;
                ExpandGrid(fullGrid, knownGrid, curTile);
            }
            else if(fullGrid[curTile[0]][curTile[1]] > 0) knownGrid[curTile[0]][curTile[1]] = 1;
        }
    }
    
    int main(int argc, char *argv[])
    {
    
        COORD characterBufferSize = { WIDTH, HEIGHT };
        COORD characterPosition = { 0, 0 };
        SMALL_RECT consoleWriteArea = { 0, 0, WIDTH - 1, HEIGHT - 1 };
        CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
    
        HANDLE wHnd = GetStdHandle(-11);
        HANDLE rHnd = GetStdHandle(-10);
    
        DWORD numEventsRead = 0;
        DWORD numEvents = 0;
        INPUT_RECORD *eventBuffer = {0};
        int wait = 45;
    
        int startGrid[WIDTH][HEIGHT] = { 0 };
        int knownGrid[WIDTH][HEIGHT] = { 0 };
        int arrowPos[2] = {0, 0};
        int bomb[2] = {0};
        struct xorshift_state seed = {argc == 2 ? (int) argv[1] : 1};
    
        for (int i = 0; i < BOMBS; i++)
        {
            while (startGrid[bomb[0]][bomb[1]] < -1 || bomb[0] <= 0 || bomb[1] <= 0 || bomb[0] >= WIDTH-1 || bomb[1] >= HEIGHT-1)
            {
                bomb[0] = (xorshift(&seed) % WIDTH-1) + 1;
                bomb[1] = (xorshift(&seed) % HEIGHT-1) + 1;
            }
    
            startGrid[bomb[0]][bomb[1]] = -9;
    
            startGrid[bomb[0] + 1][bomb[1] + 1]++;
            startGrid[bomb[0] + 1][bomb[1]]++;
            startGrid[bomb[0]][bomb[1] + 1]++;
            startGrid[bomb[0] - 1][bomb[1] + 1]++;
            startGrid[bomb[0]][bomb[1] - 1]++;
            startGrid[bomb[0] + 1][bomb[1] - 1]++;
            startGrid[bomb[0] - 1][bomb[1] - 1]++;
            startGrid[bomb[0] - 1][bomb[1]]++;
        }
    
    
        while(1)
        {
            if (arrowPos[0] > WIDTH-1) arrowPos[0] = WIDTH-1;
            if (arrowPos[0] < 0) arrowPos[0] = 0;
            if (arrowPos[1] > HEIGHT-1) arrowPos[1] = HEIGHT-1;
            if (arrowPos[1] < 0) arrowPos[1] = 0;
    
            for (int x = 0; x < WIDTH; ++x)
            {
                for (int y = 0; y < HEIGHT; ++y)
                {
    
                    if (knownGrid[x][y] == 1)
                    {
                        if (startGrid[x][y] > 0)
                        {
                            consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
                            consoleBuffer[x][y].Attributes = 10;
                        }
                        else
                        {
                            consoleBuffer[x][y].Char.AsciiChar = 'o';
                            consoleBuffer[x][y].Attributes = startGrid[x][y] < 0 ? 4 : 17;
                        }
                    }
                    else
                    {
                        consoleBuffer[x][y].Char.AsciiChar = 00;
                        consoleBuffer[x][y].Attributes = 0;
                    }
    
                    if(arrowPos[0] == x && arrowPos[1] == y)
                    {
                        consoleBuffer[x][y].Attributes = 112;
                    }
                }
            }
    
            WriteConsoleOutput(wHnd, *consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
    
            numEvents = 0;
            numEventsRead = 0;
            GetNumberOfConsoleInputEvents(rHnd, &numEvents);
    
            if (numEvents)
            {
                eventBuffer = malloc(sizeof(INPUT_RECORD) * numEvents);
                ReadConsoleInput(rHnd, eventBuffer, numEvents, &numEventsRead);
            }
    
            if(numEventsRead && wait <= 0)
            {
                wait = 45;
                switch (eventBuffer[0].Event.KeyEvent.wVirtualKeyCode)
                {
                    case 38:
                        arrowPos[0]--;
                        break;
                    case 40:
                        arrowPos[0]++;
                        break;
                    case 37:
                        arrowPos[1]--;
                        break;
                    case 39:
                        arrowPos[1]++;
                        break;
                    case 13:
                        ExpandGrid(startGrid, knownGrid, arrowPos);
                        break;
                }
            }
    
            wait--;
        }
    }

    And if I turn on -nodefaultlibs this is the string of errors i get:
    Code:
    -------------- Build: Release in Minesweeper2 (compiler: GNU GCC Compiler)---------------
    
    gcc.exe -Wall -Os -ffunction-sections -fdata-sections  -c C:\Users\mlfre\OneDrive\Desktop\Minesweeper2\main.c -o obj\Release\main.o
    gcc.exe  -o bin\Release\Minesweeper2.exe obj\Release\main.o  -s -Wl,--gc-sections -nodefaultlibs  -lKernel32 -lgcc -lmsvcrt
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x13c): undefined reference to `fesetenv'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1a5): undefined reference to `__dyn_tls_init_callback'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1d9): undefined reference to `__cpu_features_init'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1de): undefined reference to `_CRT_fenv'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1e6): undefined reference to `fesetenv'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1eb): undefined reference to `_setargv'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x1f0): undefined reference to `_CRT_fmode'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x206): undefined reference to `_pei386_runtime_relocator'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x25d): undefined reference to `_CRT_fmode'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x271): undefined reference to `_CRT_fmode'
    c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../crt2.o:(.text+0x2a4): undefined reference to `_CRT_glob'
    collect2.exe: error: ld returned 1 exit status
    Process terminated with status 1 (0 minute(s), 0 second(s))
    12 error(s), 0 warning(s) (0 minute(s), 0 second(s))
    

    So now I'm wondering either a) how could i fix this nodefaultlibs error, or b) is there anything else i can do that i might've overlooked to reduce the size of the program ?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Pardon the question, but why do you want to fit an executable into a QR code?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2020
    Posts
    2
    wouldnt it be fun? to have minesweeper from a qr code? seemed like an interesting idea.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reducing the size of a dynamically allocated array?
    By DecoratorFawn82 in forum C++ Programming
    Replies: 5
    Last Post: 11-09-2018, 09:36 AM
  2. Reducing size of image pixel data to display in window
    By synthetix in forum C Programming
    Replies: 2
    Last Post: 11-16-2009, 05:10 AM
  3. Can reducing a vector's size cause a reallocation?
    By robatino in forum C++ Programming
    Replies: 19
    Last Post: 04-12-2007, 12:13 PM
  4. Reducing the size of compiled file
    By Diablo84 in forum C++ Programming
    Replies: 11
    Last Post: 04-07-2005, 04:00 PM
  5. Reducing Code size from ridiculous length
    By DanFraser in forum C# Programming
    Replies: 10
    Last Post: 01-18-2005, 05:50 PM

Tags for this Thread