two little win32 sizecoding tricks
category: code [glöplog]
In the following, two little tricks that might save you a tiny amount of bytes:
"Standard" 4k-style window creation:
Can be replaced with:
Why?!
The second parameter can also be an "ATOM" - see here
Now there are these system classes like edit and static. They have ATOMs which seem to be constant. Nice.
You can easily verify that the ATOM for edit seems to be 0xC018:
I didn't find any information on this except for this strange japanese page.
The second one is about audio setup/replay:
It seems that you can remove the waveOutPrepareHeader call completly if waveHeader.dwFlags is set to WHDR_PREPARED. Not sure how reliable this approach is but I didn't notice any problems yet. I'm also not exactly sure whether these tricks are new/unknown.
Just wanted to share these, make better 1k/4k/8k intros! ;)
las/mercury
"Standard" 4k-style window creation:
Code:
HWND hWnd = CreateWindowExA(0, "edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0);
Can be replaced with:
Code:
HWND hWnd = CreateWindowExA(0, (LPCSTR)0xC018, 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0);
Why?!
The second parameter can also be an "ATOM" - see here
Quote:
A null-terminated string or a class atom created by a previous call to the RegisterClass or RegisterClassEx function. The atom must be in the low-order word of lpClassName; the high-order word must be zero.
Now there are these system classes like edit and static. They have ATOMs which seem to be constant. Nice.
You can easily verify that the ATOM for edit seems to be 0xC018:
Quote:
HWND hWnd = CreateWindowExA(0, "edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0);
WORD atom = GetClassWord(hWnd, GCW_ATOM);
I didn't find any information on this except for this strange japanese page.
The second one is about audio setup/replay:
Quote:
waveOutOpen(&hWaveOut, WAVE_MAPPER, &waveFormat, NULL, 0, CALLBACK_NULL);
waveOutPrepareHeader(hWaveOut, &waveHeader, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, &waveHeader, sizeof(WAVEHDR));
It seems that you can remove the waveOutPrepareHeader call completly if waveHeader.dwFlags is set to WHDR_PREPARED. Not sure how reliable this approach is but I didn't notice any problems yet. I'm also not exactly sure whether these tricks are new/unknown.
Just wanted to share these, make better 1k/4k/8k intros! ;)
las/mercury
Thank you :)
haha, nice :D
Thanks! :D
BeRo^FR just mentioned that removing waveOutPrepareHeader might not work with some drivers.
Maybe it would be a good idea to test how reliable the approach really is.
I didn't encounter any problems on real machines yet.
Maybe it would be a good idea to test how reliable the approach really is.
I didn't encounter any problems on real machines yet.
Thanks for sharing!
Cool it save 8 bytes with MS VS 2012 and 6 bytes MS VS2008
Nice. If you have a more complete minimalist win32 framework (like goldenspider) I'd love a link to its sourcecode.
ja hammer ;-)
Nice :) Thanks!
Good to know! Nice tricks. Thank you.
Quote:
I didn't encounter any problems on real machines yet.
what would be an unreal machine? :-)
virtual ones? :)
a 386 running http://www.pouet.net/prod.php?which=1274
... in unreal mode? ;)
why to use:
instead
?
Code:
HWND hWnd = CreateWindowExA(0, "edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0);
instead
Code:
xor eax,eax
HWND hWnd = CreateWindowExA(0, "edit", eax, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, eax, eax, eax, eax, eax, eax, eax, eax);
?
if you write assembler, you'd do exactly that, this is C. Modern compilers will zero a register and push it as well.
I actually use:
push byte 0 is a 2 byter - and seems to compress really well if you use it often.
It turns out to be smaller than pushing a register often but totally depends on the context and the overall style used in your code.
And yes, I have proper nasm headers for DX11. :D
Code:
push byte 0
push byte 0
push byte 0
push byte 0
push byte 0
push byte 0
push byte 0
push byte 0
push dword WS_POPUP | WS_VISIBLE | WS_MAXIMIZE
push byte 0
push dword 0xC018
push byte 0
call _CreateWindowExA@48
mov [_swapChainDesc + DXGI_SWAP_CHAIN_DESC.OutputWindow], eax
push byte 0 is a 2 byter - and seems to compress really well if you use it often.
It turns out to be smaller than pushing a register often but totally depends on the context and the overall style used in your code.
And yes, I have proper nasm headers for DX11. :D
You never know what's going compress better, until you try. But for the "xor eax, eax" vs. "push 0 / pop eax" thing I'd say that the push+pop version has practically always been smaller. Read your crinkler output report, it's not hard.
Omitting waveOutPrepareHeader might not even be smaller. Since the waveOutPrepareHeader and waveOutWrite calls are so similar, the second call compresses quite a lot. I looked at a couple of reports, and it was between 2 and 3 bytes in all of them. So you would have to write WHDR_PREPARED into waveHeader.dwFlags using less than that in order for it to be a win.
Do you know of any other window class atom values? It seems WC_DIALOG (0x8002) is somehow official, but I can't find any other (one could of course just dig them out manually). It could be that some of them have better properties in some ways than EDIT.
Are the WS_POPUP | WS_VISIBLE | WS_MAXIMIZE flags necessary? I usually just put 0 all the way, and it seems to work fine (for D3D9 fullscreen at least).
Do you know of any other window class atom values? It seems WC_DIALOG (0x8002) is somehow official, but I can't find any other (one could of course just dig them out manually). It could be that some of them have better properties in some ways than EDIT.
Are the WS_POPUP | WS_VISIBLE | WS_MAXIMIZE flags necessary? I usually just put 0 all the way, and it seems to work fine (for D3D9 fullscreen at least).
There is a list of ATOMs on that japanese website (See first post).
In the tests I conducted removing the waveOutPrepareHeader call was smaller, might not be the case in all scenarios (+ you get rid of the 4 byte hash which usually does not compress well). The WAVEHDR struct compresses quite well, even with the flag set.
In the tests I conducted removing the waveOutPrepareHeader call was smaller, might not be the case in all scenarios (+ you get rid of the 4 byte hash which usually does not compress well). The WAVEHDR struct compresses quite well, even with the flag set.
Quote:
Are the WS_POPUP | WS_VISIBLE | WS_MAXIMIZE flags necessary? I usually just put 0 all the way, and it seems to work fine (for D3D9 fullscreen at least).
Found no way yet to get rid of the mouse cursor with dwStyle == 0. ShowCursor/SetCursor seem not to work at all.
win32.hlp says:
let me ask - where did you find byte 0?
Does anyone tried to use soundServer by Leonard?
Code:
HWND CreateWindowEx(
DWORD dwExStyle, // extended window style
LPCTSTR lpClassName, // pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // handle to menu, or child-window identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data
);
let me ask - where did you find byte 0?
Does anyone tried to use soundServer by Leonard?
Depends on the calling convention, but here (Win32/C) cdecl/stdcall is used.
Code:
[...]push byte 0[...]
causes 0x00000000 to be pushed onto the stack. What's the problem here?
"soundServer by Leonard"?! Example audio replay code can e.g. be found here http://4klang.untergrund.net/.
Blueberry: I checked some old DX9 setup code, I did also use zeros everywhere.
Seems something is different with DX11 - any ideas?
In addition, I had a look at some recent DX11 intros, they all set dwStyle.