pouët.net

Go to bottom

64k intro in c#

category: code [glöplog]
I found klystrack
https://kometbomb.github.io/klystrack/
added on the 2019-12-03 22:20:06 by fxgen fxgen
.NET isn´t even installed on compo-machines!
(and if, thru WinUpdate, it´s not allowed!)
.net is an integral part of the operating system these days and comes pre-installed (though maybe not the latest version). Compo machines typically run the latest version of Windows 10. Don't just make up rules that don't exist.
My NetPacker work in progress ...
I compressed an 73ko executable to 27Ko !
Need now to remove not used classes ...


NetPacker V0.1
ILOptimizer: Original Size: 73216 bytes

ILOptimizer: Total number of classes: 181
ILOptimizer: Total number of methods: 449
ILOptimizer: Used Methods: 320/449
ILOptimizer: Removed methods count: 129
ILOptimizer: Packed Size: 65024 bytes

NetPacker: Compressed ExeToPack Size: 27324
added on the 2019-12-05 11:58:06 by fxgen fxgen
Quote:
.net is an integral part of the operating system these days and comes pre-installed

Exactly. If we disallowed .NET in the compo rules, the folks using Tooll² for their demos wouldn't be amused either ...
added on the 2019-12-05 13:14:49 by KeyJ KeyJ
And what about NetCore in demos ?
added on the 2019-12-05 14:17:41 by fxgen fxgen
The idea behind .NET core is to either redistribute the used assemblies or static-link them inside your EXE, to avoid side-by-side conflicts between different versions. That's not really practical for intros.
added on the 2019-12-06 00:58:23 by xTr1m xTr1m
Good job fxgen!
Making demos in C# actually makes sense. A quick recompile-test cycle is pretty much essential when you explore ideas :)
Out or curiosity, does your 27k thing do anything at all?
added on the 2019-12-11 04:34:36 by BarZoule BarZoule
Quote:
Out or curiosity, does your 27k thing do anything at all?


I'll share my code on github but my 27k display a voxelized metaball scene without music.

I'll need some help, we can do better with compression :-)
added on the 2019-12-12 22:42:14 by fxgen fxgen
I am looking forward to seeing your code on github!
added on the 2019-12-13 08:38:06 by Adok Adok
Quote:
I am looking forward to seeing your code on github!


...is typically sth a Lamer says, because he can´t code himself!

...then finally gets a GitHub-Link and realizes he doesn´t understand 75% of what´s going on there!
...then goes on writing stupid articles about some Race better than any other, which he thinks belongs to, just to feel better again about his stupid self!

You are in some super-stupid devils circle, get it already! :P


P.S.: FUCK Racism!
P.S.2: Make a fucking prod without stolen code and show off already, maybe i am wrong! :P ;) Make it 4K atleast, anything else is too bad for a person like you, with race-given-superskills! :P
P.S.3: asking Mensa-friends for help is cheating==lame!

There! Sorry to everyone else, had to!
If you want to help me on NetPacker, the project is shared now :-)
https://github.com/procfxgen/NetPacker
added on the 2019-12-16 13:42:28 by fxgen fxgen
nice :D (it even works on mono! \o/)

there's a lot of room for optimizations, though:
* ILOptimizer: most of the stuff I said here and here etc is still TODO it seems
* compression: gzip kinda sucks, but it looks like System.IO.Compression doesn't have anything better (brotli not in mono -> :( )... maybe a 2-stage plain->gzip->custom unpacker might be interesting (and compress the gzip with zopfli)
* unpacker: you really want to write this in IL, not C# :) , and maybe also mess with the headers to make it even smaller. Also, here's the disasm:

Code:.namespace CompressedApp { .class private auto ansi beforefieldinit Program extends [mscorlib]System.Object/*0100000b(TypeRef)*/ { // method line 1 .method public hidebysig specialname rtspecialname instance default void '.ctor' () /* 0x6000000 */ cil managed { // Method begins at RVA 0x2050 // Code size 7 (0x7) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void object/*0a00000f(MemberRef)*/::'.ctor'()/*0a00000f(MemberRef)*/ IL_0006: ret } // end of method Program::.ctor // method line 2 .method private static hidebysig default void Main (string[] args) /* 0x6000001 */ cil managed { .custom instance void class [mscorlib]System.STAThreadAttribute/*0a000001(MemberRef)*/::'.ctor'()/*0a000001(MemberRef)*/ = (01 00 00 00 ) // .... // Method begins at RVA 0x2058 .entrypoint // Code size 164 (0xa4) .maxstack 6 .locals /*11000001*/ init ( class [mscorlib]System.Resources.ResourceManager V_0, unsigned int8[] V_1, int32 V_2, class [mscorlib]System.IO.MemoryStream V_3, class [System]System.IO.Compression.GZipStream V_4, unsigned int8[] V_5, class [mscorlib]System.Reflection.Assembly V_6, class [mscorlib]System.Exception V_7) IL_0000: ldstr "resource" IL_0005: call class [mscorlib]System.Reflection.Assembly/*01000003(TypeRef)*/ class [mscorlib]System.Reflection.Assembly/*0a000002(MemberRef)*/::GetExecutingAssembly()/*0a000002(MemberRef)*/ IL_000a: newobj instance void class [mscorlib]System.Resources.ResourceManager/*0a000003(MemberRef)*/::'.ctor'(string, class [mscorlib]System.Reflection.Assembly/*01000003(TypeRef)*/)/*0a000003(MemberRef)*/ IL_000f: stloc.0 IL_0010: ldloc.0 IL_0011: ldstr "app" IL_0016: callvirt instance object class [mscorlib]System.Resources.ResourceManager/*0a000004(MemberRef)*/::GetObject(string)/*0a000004(MemberRef)*/ IL_001b: castclass unsigned int8[]/*1b000001(TypeSpec)*/ IL_0020: stloc.1 IL_0021: ldc.i4 3072 IL_0026: stloc.2 IL_0027: ldloc.1 IL_0028: newobj instance void class [mscorlib]System.IO.MemoryStream/*0a000005(MemberRef)*/::'.ctor'(unsigned int8[])/*0a000005(MemberRef)*/ IL_002d: stloc.3 IL_002e: ldloc.3 IL_002f: ldc.i4.0 IL_0030: newobj instance void class [System]System.IO.Compression.GZipStream/*0a000006(MemberRef)*/::'.ctor'(class [mscorlib]System.IO.Stream/*01000006(TypeRef)*/, valuetype [System]System.IO.Compression.CompressionMode/*01000007(TypeRef)*/)/*0a000006(MemberRef)*/ IL_0035: stloc.s 4 IL_0037: ldloc.2 IL_0038: newarr [mscorlib]System.Byte/*01000008(TypeRef)*/ IL_003d: stloc.s 5 IL_003f: ldloc.s 4 IL_0041: ldloc.s 5 IL_0043: ldc.i4.0 IL_0044: ldloc.2 IL_0045: callvirt instance int32 class [mscorlib]System.IO.Stream/*0a000007(MemberRef)*/::Read(unsigned int8[], int32, int32)/*0a000007(MemberRef)*/ IL_004a: pop IL_004b: ldloc.3 IL_004c: callvirt instance void class [mscorlib]System.IO.Stream/*0a000008(MemberRef)*/::Close()/*0a000008(MemberRef)*/ IL_0051: ldloc.s 4 IL_0053: callvirt instance void class [mscorlib]System.IO.Stream/*0a000008(MemberRef)*/::Close()/*0a000008(MemberRef)*/ IL_0058: ldloc.s 5 IL_005a: call class [mscorlib]System.Reflection.Assembly/*01000003(TypeRef)*/ class [mscorlib]System.Reflection.Assembly/*0a000009(MemberRef)*/::Load(unsigned int8[])/*0a000009(MemberRef)*/ IL_005f: stloc.s 6 IL_0061: ldnull IL_0062: stloc.s 5 IL_0064: call void class [mscorlib]System.GC/*0a00000a(MemberRef)*/::Collect()/*0a00000a(MemberRef)*/ .try { // 0 IL_0069: ldloc.s 6 IL_006b: callvirt instance class [mscorlib]System.Reflection.MethodInfo/*0100000a(TypeRef)*/ class [mscorlib]System.Reflection.Assembly/*0a00000b(MemberRef)*/::get_EntryPoint()/*0a00000b(MemberRef)*/ IL_0070: ldnull IL_0071: ldc.i4.1 IL_0072: newarr [mscorlib]System.Object/*0100000b(TypeRef)*/ IL_0077: dup IL_0078: ldc.i4.0 IL_0079: ldc.i4.0 IL_007a: newarr [mscorlib]System.String/*0100000c(TypeRef)*/ IL_007f: stelem.ref IL_0080: callvirt instance object class [mscorlib]System.Reflection.MethodBase/*0a00000c(MemberRef)*/::Invoke(object, object[])/*0a00000c(MemberRef)*/ IL_0085: pop IL_0086: leave IL_00a3 } // end .try 0 catch class [mscorlib]System.Exception { // 0 IL_008b: stloc.s 7 IL_008d: ldstr "Invoke Main error ! {0}" IL_0092: ldloc.s 7 IL_0094: callvirt instance string class [mscorlib]System.Exception/*0a00000d(MemberRef)*/::get_Message()/*0a00000d(MemberRef)*/ IL_0099: call void class [mscorlib]System.Console/*0a00000e(MemberRef)*/::WriteLine(string, object)/*0a00000e(MemberRef)*/ IL_009e: leave IL_00a3 } // end handler 0 IL_00a3: ret } // end of method Program::Main } // end of class CompressedApp.Program }


as you can see, it's huge!

some small notes:
* don't do a try/catch or try/finally OR using (compiler turns 'using' into try/finally)
* don't call GC.Collect, Stream.Close
* Main() can have no args, so the new string[0] isn't needed
* make all names as short as possible

but most importantly:
* DON'T use Resources! Use a simple byte array (if you need bytes) OR an EmbeddedResource (if you need a Stream). byte arrays and EmbeddedResources go to the Blobs section, but Resources have much more metadata in a wrapper format, and thus are larger! Plus getting data from a Resource needs more code.

P.S. WinForms+OpenGL should be possible (var dc = GetDC(form.Handle); wglMakeCurrent(dc, wglCreateContext(dc)); then use wglGetProcAddress). But do NOT use the GUI designer in Visual Studio, as the code it generates sucks :p
added on the 2019-12-16 17:30:20 by porocyon porocyon
you probably mean SDL instead of SQL in the readme ;)
also, SDL2.dll isn't part of vanilla Windows/.NET or is it? so you still have a 1MB+ intro in total then? :P
@Maali: SDL will be replaced by Winform :-)
@porocyon: Thanks for your feedbacks ! I'll optimize my unpacker ...
added on the 2019-12-16 20:07:35 by fxgen fxgen
yeah, but the other Monogame abstractions (see opengl.cs) you borrowed also use SDL2.dll as lib for the GL procaddresses. correct me if i'm wrong, but shouldn't that be wrapped around opengl.dll then? (just curious/ignorant cos back then I used some automatically generated wrapper crap around glfw3 and called GL functionalities via that, which is also not vanilla. its DLL was smaller though! :P)
Yes I'll remove sdl and I need to rewrite opengl wrapper.
I'll look at others opengl wrappers (glsharp ....)
added on the 2019-12-17 07:52:22 by fxgen fxgen
on the plus part of rewriting that, you probably don't need 50% of them :D
it's the work of my iloptimizer class, remove not used methods ... but it's a work in progress...
added on the 2019-12-17 08:34:32 by fxgen fxgen
I've actually learned quite a lot by studying source code... So, thanks for sharing it!
added on the 2019-12-17 08:50:38 by Adok Adok
Some one could look at my Intro02 example ?

https://github.com/procfxgen/NetPacker/tree/master/Examples/Intro02

glClearColor(1,0,0,1) doesn't work in C# .... my C++ version work.
added on the 2019-12-18 20:25:05 by fxgen fxgen
Once you've seen, nay even bugfixed Mono you really don't want it to be your interpreter. Trust me, please ;)
added on the 2019-12-18 21:13:25 by superplek superplek
superplek: Intro02 is an example without SDL but with winform ...
when this projet work, I'll look for Mono compatibility.
added on the 2019-12-19 08:00:04 by fxgen fxgen
That work now.

For Intro02 I have an 7680 bytes executable size just for a simple OpenGL Red Screen.
added on the 2019-12-19 18:30:18 by fxgen fxgen
The main problem is the launcher that take 5 ko ... I don't know how to reduce the size... If I edit executable in a binary editor, there's lot of 0x00 blocks ...

porocyon: an idea ?

Thanks
added on the 2019-12-19 20:01:48 by fxgen fxgen

login

Go to top