Skip to content

Instantly share code, notes, and snippets.

@bigdavedev
Created March 29, 2016 20:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bigdavedev/f046e8d449c2a7967575fca41827a9c6 to your computer and use it in GitHub Desktop.
Save bigdavedev/f046e8d449c2a7967575fca41827a9c6 to your computer and use it in GitHub Desktop.
Smallest exe for OpenGL window with shader

Download main.c and empty.vcxproj to your PC. Download Crinkler 2.0 from http://crinkler.net/crinkler20.zip and extract it to tools/ in your project folder and rename it to link.exe.

You should then be able to open the project in MSVC 2015 and compile and run it!

Many small cheats are used here to make the code as small as possible. Straight of the bat we never specify more than dwFlags in PIXELFORMATDESCRIPTOR. This struct actually required us to fill in a size field, but that costs four bytes and doesn't appear to do anything horrendous when left out...

In the Fragment Shader we do nothing in the main function. On my machine this implies that the gl_FragColor is black, but YMMV.

Stripping the entrypoint of it prologue and epilogue means that we save on bytes, but we must put some sort of prologue in. The asm on line seven is just the magic we need.

CreateWindow is another inspired cheat from . "edit" is a special type of Window Class and the parameter 0x91000000 is simply the result of OR'ing flags like maximize, popup, and visible.

The last byte saving cheat in empty.c is the call to glCreateShaderProgramv which creates a standalone shader for us (0x8B30 is GL_FRAGMENT_SHADER) saving us from loading all the symbols for creating a shader program manually.

Crinkler is used to get the exe down to size, which currently is 483 for me

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{77893DC0-0090-4153-BE7B-6F5325840450}</ProjectGuid>
<RootNamespace>Empty</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)Output\$(Configuration)\</OutDir>
<IntDir>$(OutDir)Intermediate</IntDir>
<ExecutablePath>$(SolutionDir)tools;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH)</ExecutablePath>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>None</DebugInformationFormat>
<CompileAsManaged>false</CompileAsManaged>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<OpenMPSupport>false</OpenMPSupport>
<CompileAs>CompileAsC</CompileAs>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;opengl32.lib</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>No</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<EntryPointSymbol>_start</EntryPointSymbol>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalOptions>/MERGE:.rdata=.text /CRINKLER /TINYHEADER /TINYIMPORT /UNSAFEIMPPORT /PRINT:IMPORTS /PRINT:LABELS /REPORT:report.html /COMPMODE:SLOW /HASHTRIES:3000 /ORDERTRIES:7000 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
#include <windows.h>
#include <GL/gl.h>
PIXELFORMATDESCRIPTOR const pfd = { .dwFlags = 0x21 };
char const* f = "void main(){}";
__declspec(naked) void _start()
{
__asm enter 0x10,0 __asm pushad
{
HDC dc = GetDC(CreateWindow("edit",0,0x91000000,0,0,0,0,0,0,0,0));
SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd);
wglMakeCurrent(dc, wglCreateContext(dc));
wglGetProcAddress("glUseProgram")(wglGetProcAddress("glCreateShaderProgramv")(0x8B30,1,&f));
do{ glRecti(1,1,-1,-1); SwapBuffers(dc); } while (!GetAsyncKeyState(VK_ESCAPE));
ExitProcess(0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment