5 ms·
Well the first optimization would be to roll my own libc (not that hard at all :) ) where i would load api calls by ordinal and only those that i really need (o
by _o_ 8y ago
Well the first optimization would be to roll my own libc (not that hard at all :) ) where i would load api calls by ordinal and only those that i really need (ok, for the sake of compatibility, i would dig them from IAT table based on 16bit hash (folding fnv32) of API name + dll name). Same for all other libraries, everything compiled with agressive optimization (at least /O2). Next step would be to take compiler that is minimizing the bloat, tinyc (https://bellard.org/tcc/ https://bellard.org/tcc/), compiling 32 bit binaries just to save some space. Maybe even go for .com to avoid PE header bloat. At the end compress everything with something like upx, but probably i would roll my own PE compressor. Instead of using functions, the macros would be used, absolutely no classes, #pragma pack(1) all structures (i never tryed what tinyc does :D). Also merging PE sections will save some bytes.
Size optimizing is fun and you can learn a lot but it is dying art, probably 99.9999% of todays developers dont understand what I have written in first part (today, you are learning the programming, but very indequately what the OS does, actually typical today programer understands the programing but is clueless what his code does on low level) ... but +1 for anyone that goes into that direction, my boss at my first job was saying that good software fits to one 1.44 floppy but this is today violated by HHLL. Well business wise no need for that unless you are making malware, but still cool.
- pjmlp 8y agoOn Windows a common approch is just to use Win32 directly, no libc APIs at all. Oh and link them by ordinal.
- jsheard 8y agoMost demoparties forbid linking by ordinal these days, since ordinals tend to change between Windows versions. Importing by hash is the go-to method now. https://in4k.github.io/wiki/import-by-hash https://in4k.github.io/wiki/import-by-hash
- _o_ 8y agoMaybe I wasnt clear enough, libc functions implemented as calls to GetProcAddress (by ordinal/hash) functions directly. :) But just those that you use :)
- pjmlp 8y agoYou were clear, my point is that you don't call any of them. For example use ZeroMemory() and not memset(), ReadFileEx() and not read(), and so forth, no use of GetProcAddress() at all.
- _o_ 8y agoYou still need to get function pointers using GetProcAddress or by searching for them after LoadLibrary within dll exports table (this is the idea with hashes). The third option is to leave it to the PE loader, but this is burning space in PE import table.
- 0x0 8y agoThere are specialized .exe packers/compressors for 64k intros (more tuned than UPX) such as http://www.farbrausch.de/~fg/kkrunchy/ http://www.farbrausch.de/~fg/kkrunchy/ I think one of the biggest challenges, size-wise, is coming up with good algorithms for procedural content (textures, 3d meshes, camera paths, audio/synths). Code for audio playback and for doing directx/opengl scene rendering shouldn't be too hard to keep small, but you really need to work to get interesting content to fit, since you can't really include much in the way of of bitmaps/audio samples/3d meshes as binary data assets.
- wiz21c 8y agothis. For a 4KB intro, well, coding skills/cleverness makes a difference. But at 64KB, the artistic side can exist and that's where you can make a difference. Farbrausch stuff is cleverly coded, but the aesthetics were just ahead.
- ralphb 8y agoOne thing you're missing: Smaller size before compression does not necessarily imply smaller size after compression. For instance, /O2 has a tendency to generate code that is difficult to compress. So it is always better to keep in mind how you achieve smaller file sizes after compression, and not worry so much about data sizes before compression.
- userbinator 8y agoTCC is not a good compiler for sizecoding. It is itself very small, but that's because it doesn't do much in the way of optimisation at all and generates lots of redundant instructions that you can't make up for with executable compression.