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 ?