Author Topic: Making tiny FB executable programs  (Read 15458 times)

0 Members and 1 Guest are viewing this topic.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Making tiny FB executable programs
« on: July 09, 2007 »
I was looking at nino's latest tiny executables, and trying to see how to link them without linking in freebasic's startup code and default libraries.  These are really large, so it's important to be able to get rid of them for tiny exes.  The problem is that FB's linker and compiler hard code a few things and that means the startup code always gets linked.

So here's my solution to the problem.

First, write your program as usual, obviously NOT using an built-in FB functions like print, graphics, etc.
Here's my test program (tiny.bas)
Code: [Select]
#include "windows.bi"

declare function WinMainCRTStartup alias "WinMainCRTStartup"

function WinMainCRTStartup() as integer
messagebox(0,"Very Small FB EXE Sample","Hello",MB_OK)
return 0
end function

compile this using

Code: [Select]
fbc -c tiny.bas
The -c tells the FB compiler just to make a .o file and not an .exe.  .o files are the building blocks used by linkers to make executable files.

Next, we need to stub the functions that FB has hardcoded.
I used assembler for this (stub.asm)
Code: [Select]
.386p
.model flat
.code
public _fb_RtInit@0
_fb_RtInit@0:
end
I assembled it with MASM, but it can be built with lots of other assemblers.
Command line
Code: [Select]
ml /c /coff stub.asmThis produces stub.obj.

Finally, you need to link these all together.  FB is no use for this, you need a proper linker.  I've used crinkler, which has the added advantage of compressing while it links.  You can download it from www.crinkler.net

The command line I used to do the link is
Code: [Select]
crinkler /SUBSYSTEM:WINDOWS /OUT:tiny.exe /LIBPATH:"C:\program files\microsoft platform sdk for windows server 2003 r2\lib" kernel32.lib user32.lib tiny.o stub.obj



You will need the libs from Microsoft Platform SDK to perform this step.  You will need to change LIBPATH to point to wherever you have them installed.  You can change the name of the output file by changing OUT.

And that produces an exe which is just 605 bytes in size!

Included in the archive are:
All the source from this article, stub.obj for those who don't have MASM, and the final exe.
Crinkler is here www.crinkler.net

Have fun!

Jim
« Last Edit: July 09, 2007 by Jim »
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Making tiny FB executable programs
« Reply #1 on: July 09, 2007 »
cool k+ jim!

lots of new stuff there for me to have fun with cheers.
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Making tiny FB executable programs
« Reply #2 on: July 09, 2007 »
Yep, very cool Jim.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #3 on: July 09, 2007 »
Here's taj's pixel shader 3.0 demo in FB.  Using the above technique it comes out at 1081 bytes.  Can anyone get it under the magic 1Kb?

Nino, this will definitely help you port trinity :)
Code: [Select]
' Chris Thornborrow (auld)... lalala credit would be nice ... lalala
' Example OGL + shaders in 1k
' Requires crinkler

' VS2005 modifications by benny!weltenkonstrukteur.de

' Freebasic modifications by Jim 9/7/2007

option explicit

#include "windows.bi"
#include "GL/gl.bi"
#include "GL/glu.bi"
#include "GL/glext.bi"

declare sub WinMainCRTStartup alias "WinMainCRTStartup"

' Draws the labyrinth using a pair of shaders...
' Vertex shader does NOT transform incoming vertex but stores that in p instead for later use
' The fragment shader is a complicated. It essentially raycasts into a constantly changing
' equation, similar in concept to chladni :-). Its carfully tuned so we dont crash into it as we move
' and so we get a feeling of depth. The for loop could be smaller when written as a do .. while but then
' it wouldnt work on NVidia cards of 7xxx series or below.
' Fragment shader has 2 lines for setup, 1 line for raycasting and function testing, 1 line for colour.

dim shared labvsh as zstring * 68 => "varying vec4 p;void main(){p=ftransform();gl_Position=gl_Vertex;}"
dim shared labfsh as zstring * 260 => "varying vec4 p;void main(){vec3 V=vec3(0,3.5*sin(p.z),p.z);vec3 D=vec3(p.x,p.y,0.5)*0.08;for(int i=800;i>0;i--,V+=D)if(length(fract(abs(sin(V))))>1.5+0.5*sin(V.z)*sin(p.z*0.4))i=0;gl_FragColor=vec4(1,0.8,0.8,0)*dot(vec3(0.4),fract(V))-length(V-p.xyz)*0.1;}"

type GenFP as sub () ptr

dim shared glFP(6) as GenFP
dim shared glnames(6) as zstring * 16 => {"glCreateShader", "glShaderSource", "glCompileShader", "glCreateProgram", "glAttachShader", "glLinkProgram", "glUseProgram"}

dim shared pfd as PIXELFORMATDESCRIPTOR
dim shared dmScreenSettings as DEVMODE

' declare everything global to save bytes
dim shared q as zstring ptr
dim shared i as integer
dim shared as GLuint v,f,p
dim shared hDC as HDC

dim shared m(15) as GLfloat ={1,-0.01f,0,0,0.01f,1,0,0,0,0,1,0,0,0,0.04f,1}

sub WinMainCRTStartup()
dmScreenSettings.dmSize=sizeof(dmScreenSettings)
dmScreenSettings.dmPelsWidth   = 640
dmScreenSettings.dmPelsHeight  = 480
'dmScreenSettings.dmBitsPerPel = 32
' its risky to remove the flag and bits but probably safe on compo machine :-)
dmScreenSettings.dmFields=DM_PELSWIDTH Or DM_PELSHEIGHT
ChangeDisplaySettings(@dmScreenSettings,CDS_FULLSCREEN)

' minimal windows setup code for opengl 
pfd.cColorBits = 32
pfd.cDepthBits = 32
pfd.dwFlags    = PFD_SUPPORT_OPENGL Or PFD_DOUBLEBUFFER
hDC = GetDC(CreateWindow("edit", 0, WS_POPUP Or WS_VISIBLE Or WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0))

SetPixelFormat(hDC, ChoosePixelFormat(hDC, @pfd), @pfd)
wglMakeCurrent(hDC, wglCreateContext(hDC))

' create the shaders inlined to save bytes
for i=0 to 6
glFP(i) = cast(GenFP, wglGetProcAddress(glnames(i)))
next

v = cast(PFNGLCREATESHADERPROC, glFP(0))(GL_VERTEX_SHADER)
f = cast(PFNGLCREATESHADERPROC, glFP(0))(GL_FRAGMENT_SHADER)
p = cast(PFNGLCREATEPROGRAMPROC, glFP(3))()

q = @labvsh
cast(PFNGLSHADERSOURCEPROC, glFP(1))(v, 1, cast(byte ptr ptr, @q), NULL)
cast(PFNGLCOMPILESHADERPROC, glFP(2))(v)

q = @labfsh
cast(PFNGLSHADERSOURCEPROC, glFP(1))(f, 1, cast(byte ptr ptr, @q), NULL)
cast(PFNGLCOMPILESHADERPROC, glFP(2))(f)

cast(PFNGLATTACHSHADERPROC, glFP(4))(p,v)
cast(PFNGLATTACHSHADERPROC, glFP(4))(p,f)

cast(PFNGLLINKPROGRAMPROC, glFP(5))(p)
cast(PFNGLUSEPROGRAMPROC, glFP(6))(p)

ShowCursor(FALSE)

'**********************
' NOW THE MAIN LOOP...
'**********************

' there is no depth test or clear screen...as we draw in order and cover
' the whole area of the screen.

while GetAsyncKeyState(VK_ESCAPE) = 0
' move forward and rotate slightly each frame
' glMultMatrix is smaller (20 bytes) than glTranslatef and glRotatef!!
glMultMatrixf(@m(0))
glRecti(-1,-1,1,1)
SwapBuffers(hDC)
wend
' necessary under vista it seems... :-( extra bytes required.
ExitProcess(0)
end sub

Jim
« Last Edit: July 09, 2007 by Jim »
Challenge Trophies Won:

Offline slippy

  • Atari ST
  • ***
  • Posts: 172
  • Karma: 42
    • View Profile
Re: Making tiny FB executable programs
« Reply #4 on: July 09, 2007 »
wow ... that's a fat tut ... k+ m8 ... and thanks for this :)

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Making tiny FB executable programs
« Reply #5 on: July 09, 2007 »
Cool cheers jim that helps a lot!
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17409
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Making tiny FB executable programs
« Reply #6 on: July 09, 2007 »
Also fails to compile here It is failing in glu.bi
Any clues?
Shockwave ^ Codigos
Challenge Trophies Won:

Offline benny!

  • Senior Member
  • DBF Aficionado
  • ********
  • Posts: 4384
  • Karma: 228
  • in this place forever!
    • View Profile
    • bennyschuetz.com - mycroBlog
Re: Making tiny FB executable programs
« Reply #7 on: July 09, 2007 »
I am not using FB ... but this is a very interesting tutorial, Jim.

K++ !!!
[ mycroBLOG - POUET :: whatever keeps us longing - for another breath of air - is getting rare ]

Challenge Trophies Won:

Offline p01

  • Atari ST
  • ***
  • Posts: 158
  • Karma: 51
    • View Profile
    • www.p01.org
Re: Making tiny FB executable programs
« Reply #8 on: July 09, 2007 »
Nifty.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #9 on: July 09, 2007 »
Quote
Also fails to compile here It is failing in glu.bi
Any clues?
Different versions of FB.  Me and nino are both using 0.16b.  Has everyone else upgraded while we weren't looking? :P
I'll try to get a fix for 0.17b later.

Jim
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Making tiny FB executable programs
« Reply #10 on: July 09, 2007 »
I'm using 0.17b and it's working here.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #11 on: July 09, 2007 »
I've just downloaded 0.17b and it works for me too (I just had to remove 'option explicit').  Which version of FB are you using Shockwave?

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Making tiny FB executable programs
« Reply #12 on: July 09, 2007 »
it could be 0.15 he is yousing as the problem he is getting is an incompatibility between glu.bi and windows.bi im sure check my trinity port thread for further details.
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #13 on: July 09, 2007 »
Any idea where I can download 0.15b - it's not available at freebasic.net any more!

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Making tiny FB executable programs
« Reply #14 on: July 09, 2007 »
not sure if it can be downloaded any more jim as i dont think many people use it anymore  :-\
Challenge Trophies Won:

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Re: Making tiny FB executable programs
« Reply #15 on: July 09, 2007 »
I have it here on my hd.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #16 on: July 09, 2007 »
Found it.  It's hidden on sourceforge :)
Jim
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #17 on: July 09, 2007 »
I'm really sorry Shockwave, there's no way 0.15b will ever compile this code.  It's easy to get round the 'max' problem, but then it fails on all the function pointer stuff :(
If anyone else wants a look, the 'max' fix is just
Code: [Select]
#define max
#include "windows.bi"
#undef max

Jim
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Making tiny FB executable programs
« Reply #18 on: July 09, 2007 »
bugger thats a real shame is there no way you could update sw?
Challenge Trophies Won:

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
Re: Making tiny FB executable programs
« Reply #19 on: July 09, 2007 »
You can install as many versions of fb into different directories/program groups as you like.  I've now got 0.15/0.16/0.17 all installed at the same time :)  You just have to change the default values the installer gives you.

Jim
Challenge Trophies Won: