flat assembler
Message board for the users of flat assembler.
Index
> Tutorials and Examples > Custom font & edit control colors. |
Author |
|
MHajduk 09 Apr 2013, 13:58
I'd like to present here a program written with FASM that is a simple example demonstrating an easy way to use arbitrarily chosen font as well as text and background colors inside any edit control.
The font (in TTF or OTF format) is attached from the external file to the executable during compilation and is placed inside one of the application resources. When the application runs the custom font is extracted from the resource and temporarily placed in memory so we can use it in the same way as other fonts installed in the system. When the application ends the font is removed from the process memory - the system set of installed fonts doesn't change at the run of the program. The change of the default colors used in the edit control is performed through the 'WM_CTLCOLOREDIT' message processing. http://www.youtube.com/watch?v=LKDmyM8IYJ8 Here you can take a look at the program code: Code: ; ; A simple program written with FASM that presents a way to use custom fonts and ; custom edit control colors (both of text and background). ; ; (C) Mikolaj Hajduk, 09.04.2013. ; format PE GUI 4.0 ; Include a header file containing necessary macros. ; include 'win32wx.inc' ; Use UTF-8 encoding if you want to have your strings displayed always the same ; way despite of local settings of the user system and if your application has to ; be multilingual. ; include 'ENCODING\utf8.inc' ; A definition of the constant describing the program version (encoded date of ; the last changes). ; PROG_VERSION equ '2013.04.09.0' ; Constants used to determine the application window minimal width and height. ; WND_MIN_WIDTH = 400 WND_MIN_HEIGHT = 300 ; Symbolic equivalents used to determine colors of an edit control text and its ; background. ; ; 0x00bbggrr ; ---------- EDIT_BG_COLOR = 0x005B196A EDIT_TEXT_COLOR = 0x00F3F1F7 ; A constant used to calculate the edit control sizes and position when the ; application window is to be resized. ; EDIT_MARGIN = 4 ; An identifier of the font resource. ; FONT_ID = 1 ; The data section. ; section '.data' data readable writeable HwndMain dd 0 ; The handle of the main application window. hFont dd 0 ; The handle of the font used to display strings ; inside window controls. FontsNum dd 0 ; A variable that is used to store the number of ; fonts loaded by the 'AddFontMemResourceEx' function. FontRes dd 0 ; A variable that stores the handle of the font ; added to the system by the 'AddFontMemResourceEx' ; function. ; An arbitrarily chosen class name of the created window. ; ClassName du 'CustomFontExample', 0 ; A string displayed in the application window title bar. ; WindowCaption du 'Custom font example v.', PROG_VERSION, 0 ; An instance of the WNDCLASSEX structure containing information about ; the created window class. ; wc WNDCLASSEX sizeof.WNDCLASSEX, 0, WindowProc, 0,\ \ 8,\ ; The number of extra bytes allocated \ ; following every class instance. \ ; Here we need two double words for \ ; the edit control handle (the first dword) \ ; and the brush handle (the second dword). \ NULL, NULL, NULL,\ \ COLOR_BTNFACE + 1,\ ; The color value used for painting the \ ; background (or a handle to the class \ ; background brush). If it is a color value \ ; then it must be one of the standard system \ ; colors plus 1. \ NULL, ClassName, NULL ; An instance of the MSG structure used to store information about ; messages from the thread message queue. ; msg MSG ; The name of the used font. ; FontName du 'Silubr', 0 ; A constant used in INITCOMMONCONTROLSEX as a flag indicating that ; all standard common control classes have to be loaded from the DLL. ; ICC_STANDARD_CLASSES = 0x4000 ; An instance of the structure carrying information used to load common ; control classes. ; icex INITCOMMONCONTROLSEX sizeof.INITCOMMONCONTROLSEX, ICC_STANDARD_CLASSES ; The code section. ; section '.code' code readable executable start: ; Ensure that the common control DLL (Comctl32.dll) is loaded ; and register chosen common control classes. ; invoke InitCommonControlsEx, icex stdcall ErrorRoutine, exit ; Retrieve a handle of the application file. ; invoke GetModuleHandle, 0 stdcall ErrorRoutine, exit mov [wc.hInstance], eax ; As an application icon use one of the predefined icons. ; invoke LoadIcon, 0, IDI_APPLICATION stdcall ErrorRoutine, exit mov [wc.hIcon], eax ; A cursor associated with the application is a standard, arrow ; shaped one. ; invoke LoadCursor, 0, IDC_ARROW stdcall ErrorRoutine, exit mov [wc.hCursor], eax ; Registering the application window class in the system. ; invoke RegisterClassEx, wc stdcall ErrorRoutine16, exit ; Create the main application window. ; invoke CreateWindowEx, 0, ClassName, WindowCaption, WS_VISIBLE + WS_OVERLAPPEDWINDOW + \ \ WS_CLIPCHILDREN,\ ; Exclude child windows from redrawing when \ ; the drawing occurs within the parent, i.e. \ ; main application window area. \ 128, 128, 350, 192, NULL, NULL, [wc.hInstance], NULL stdcall ErrorRoutine, exit mov [HwndMain], eax ; Determine the location of the font resource in the application module. ; The handle to the resource's information block is temporarily stored ; in the ebx register. ; invoke FindResource, [wc.hInstance], FONT_ID, RT_FONT stdcall ErrorRoutine, exit xchg ebx, eax ; Retrieve the size (in bytes) of the font resource and store it ; temporarily in the esi register. ; invoke SizeofResource, [wc.hInstance], ebx stdcall ErrorRoutine, exit xchg esi, eax ; Retrieve a handle to the data associated with the font resource. ; invoke LoadResource, [wc.hInstance], ebx stdcall ErrorRoutine, exit ; Retrieve a pointer to the first byte of the specified font ; resource. ; invoke LockResource, eax stdcall ErrorRoutine, exit ; Add the font resource from the memory image to the system what ; allows to refer to it's name as if it was manually installed ; by us in the system. ; invoke AddFontMemResourceEx,\ \ eax,\ ; The pointer to the font resource. \ esi,\ ; Number of bytes in the font resource. \ 0,\ ; Reserved, must be 0. \ FontsNum ; The pointer to the variable that specifies ; the number of fonts installed if the function ; succeeds. test eax, eax ; No additional error information is available jz exit ; when the function fails. mov [FontRes], eax ; Create a font that will be used to display all strings inside ; the application window controls. ; invoke CreateFont, 50, 0, 0, 0, 0, FALSE, FALSE, FALSE,\ DEFAULT_CHARSET, OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS,\ \ ANTIALIASED_QUALITY,\ ; The font is antialiased or smoothed \ ; depending on its size. \ FIXED_PITCH + FF_DONTCARE, FontName stdcall ErrorRoutine, cleanup mov [hFont], eax ; Set the created font to the main and additional application windows. ; invoke SendMessage, [HwndMain], WM_SETFONT, eax, TRUE ; A loop where all messages referring to the application window have been ; processed. ; msg_loop: ; Retrieve a message from the application message queue. ; invoke GetMessage, msg, NULL, 0, 0 ; Exit when the 'WM_QUIT' message has been retrieved. ; test eax, eax jz cleanup ; Display a proper error message when something has gone wrong ; (eax = -1). ; inc eax stdcall ErrorRoutine, cleanup ; Translate virtual-key strokes into character messages. ; invoke TranslateMessage, msg ; Dispatch the retrieved message to the window procedure. ; invoke DispatchMessage, msg jmp msg_loop ; Release all handles and allocated resources before exit. ; cleanup: ; Delete the font used to display strings in the application ; window controls. ; cmp [hFont], 0 je @f invoke DeleteObject, [hFont] @@: cmp [FontRes], 0 je exit ; Remove the font added from the memory image file. ; invoke RemoveFontMemResourceEx, [FontRes] ; Quit the application. ; exit: invoke ExitProcess, [msg.wParam] ; The error handling routine that organizes the program flow when any of ; API functions returns zero value. ; ErrorRoutine16: ; Zeroize bits of the eax register from the 16th to the 31st one. ; Done to assure that the eax register won't contain any "garbage" ; after calling API functions returning 16-bit result. ; and eax, 0xFFFF ErrorRoutine: ; Check value stored in the eax register. If it's nonzero then ; return to the address following the place the error procedure ; has been called. ; test eax, eax jz @f retn 4 ; Check value of the last error that has occurred. ; @@: invoke GetLastError test eax, eax jnz @f ; If there was no error, i.e. the 'GetLastError' function returned ; 'ERROR_SUCCESS', we return to the place when the 'ErrorRoutine' ; procedure was called and remove the 'ReturnTo' address stored on ; the stack before the procedure call. ; retn 4 @@: ; If there was an error, we display a message box with a human readable ; description of the error, remove the address of the procedure caller ; and return to the 'ReturnTo' address. ; stdcall ShowLastError, NULL, eax add esp, 4 retn ; The main application window procedure. Here we specify how to react ; on the events occurring inside the window. ; proc WindowProc, hwnd, wmsg, wparam, lparam locals .Edit dd 0 ; The handle of the edit control. .hBrush dd 0 ; The handle of the brush used to redraw ; the edit control background. .Rect RECT ; An instance of the RECT structure used ; to store the coordinates of the upper-left ; and the lower-right corners of the window ; client area. endl push ebx ; Retrieve the coordinates of the application window client area. ; The result of the procedure 'GetClientRect' is stored in the ; instance of the RECT structure. The coordinates of the upper-left ; corner of the client area rectangle are always equal to (0, 0), ; so the most important are coordinates of the lower-right corner ; as a containing the whole information. ; lea eax, [.Rect] invoke GetClientRect, [hwnd], eax stdcall ErrorRoutine, .finish ; Adjust the width and height of the edit control accordingly to the ; width and height of the application window client area. We subtract ; doubled value of 'EDIT_MARGIN' constant to obtain the proper width ; of the right and bottom margins (the left and top margins are constant ; and equal to 'EDIT_MARGIN'). ; sub [.Rect.right], 2*EDIT_MARGIN sub [.Rect.bottom], 2*EDIT_MARGIN ; Depending on the message type perform proper actions. ; cmp [wmsg], WM_CREATE je .wmcreate ; Retrieve the handle of the edit control from the window extra memory and ; store it in the local variable '.Edit'. ; invoke GetWindowLong, [hwnd], 0 stdcall ErrorRoutine, .wmdestroy mov [.Edit], eax ; Retrieve the handle of the brush from the window extra memory and store ; it in the local variable '.hBrush'. ; invoke GetWindowLong, [hwnd], 4 stdcall ErrorRoutine, .wmdestroy mov [.hBrush], eax cmp [wmsg], WM_SIZE je .wmsize cmp [wmsg], WM_SETFONT je .wmsetfont cmp [wmsg], WM_GETMINMAXINFO je .wmgetminmaxinfo cmp [wmsg], WM_SETFOCUS je .wmsetfocus cmp [wmsg], WM_CTLCOLOREDIT je .wmeditcolor cmp [wmsg], WM_DESTROY je .wmdestroy ; Ensure that all messages not processed by the application ; window procedure will be processed by default window procedure. ; .defwndproc: invoke DefWindowProc, [hwnd], [wmsg], [wparam], [lparam] jmp .finish ; Actions performed when the application window has been created. ; .wmcreate: ; Create the edit control window. ; invoke CreateWindowEx, WS_EX_CLIENTEDGE, 'EDIT', 0,\ WS_VISIBLE + WS_CHILD +\ \ \;WS_HSCROLL +\ ; Uncomment these lines if you don't \;ES_AUTOHSCROLL +\ ; want the edit control content to be \ ; wrapped. \ WS_VSCROLL +\ ; The edit control window has a vertical \ ; scroll bar. \ ES_AUTOVSCROLL +\ ; Automatically scroll text up one page \ ; when user presses the ENTER key on the \ ; last line. \ ES_MULTILINE +\ ; The edit control is multiline. \ ES_LOWERCASE,\ ; Convert all characters to lowercase \ ; while they are typed in (it's necessary \ ; in our case since the Gothic alphabet \ ; is unicase i.e. make no distinction \ ; between capital and lower case letters). \ EDIT_MARGIN, EDIT_MARGIN,\ ; Position and sizes of the created edit [.Rect.right], [.Rect.bottom],\ ; control. \ [hwnd], 0, [wc.hInstance], NULL stdcall ErrorRoutine, .wmdestroy mov [.Edit], eax ; Store the edit control handle in the reserved window extra ; memory. It's necessary because this value must be available ; during the next call of the 'WindowProc' procedure. ; invoke SetLastError, 0 invoke SetWindowLong, [hwnd], 0, [.Edit] stdcall ErrorRoutine, .wmdestroy ; Create a logical brush that has the specified solid color ; used to repaint the edit control background. ; invoke CreateSolidBrush, EDIT_BG_COLOR stdcall ErrorRoutine, .wmdestroy xchg ebx, eax ; Store for a moment the handle of the ; created brush in the ebx register. ; The handle of the created brush is stored in the second ; double word of the reserved window extra memory that follows ; any window class instance. ; invoke SetLastError, 0 invoke SetWindowLong, [hwnd], 4, ebx stdcall ErrorRoutine, .wmdestroy ; Window procedure should return 0 when processes the 'WM_CREATE' ; message. ; jmp .return0 ; Actions performed when the application window has changed its sizes. ; .wmsize: ; Move the edit control to the calculated position. ; invoke MoveWindow, [.Edit], EDIT_MARGIN, EDIT_MARGIN, [.Rect.right], [.Rect.bottom], TRUE stdcall ErrorRoutine, .finish ; Window procedure should return 0 when processes the 'WM_SIZE' ; message. ; jmp .return0 ; Actions performed when the window procedure receives the 'WM_SETFONT' ; message. Here we forward the 'WM_SETFONT' message to all controls ; located inside the window. ; .wmsetfont: ; Set the new font to the edit control instead the current one. ; invoke SendMessage, [.Edit], WM_SETFONT, [wparam], TRUE jmp .finish ; Assure that the width and height of the application window never be smaller ; than the values hold in the constants 'WND_MIN_WIDTH' and 'WND_MIN_HEIGHT'. ; .wmgetminmaxinfo: virtual at eax .minmax MINMAXINFO end virtual mov eax, [lparam] mov dword [.minmax.ptMinTrackSize.x], WND_MIN_WIDTH mov dword [.minmax.ptMinTrackSize.y], WND_MIN_HEIGHT ; Window procedure should return 0 when processes the 'WM_GETMINMAXINFO' ; message. ; jmp .return0 ; Operations performed when the application window gains the keyboard focus. ; .wmsetfocus: ; Set the keyboard focus to the edit control. ; invoke SetFocus, [.Edit] stdcall ErrorRoutine, .return0 ; The window procedure should return 0 when processes the 'WM_SETFOCUS' ; message. ; jmp .return0 ; Operations performed when the window procedure receives the 'WM_CTLCOLOREDIT' ; message sent by the edit control that is about to be (re)drawn. Through 'wparam' ; parameter of the message the window procedure receives the handle of the edit ; control device context. ; .wmeditcolor: ; Set the drawing mode for the edit control background ; (fill it with a chosen background color). ; invoke SetBkMode, [wparam], OPAQUE ; Set the text color for the edit control device context. ; invoke SetTextColor, [wparam], EDIT_TEXT_COLOR ; Set the current text background color to the specified color ; value. ; invoke SetBkColor, [wparam], EDIT_BG_COLOR ; The window procedure should return the handle of the brush ; if processes this message. The brush is used to paint the ; edit control background. ; mov eax, [.hBrush] jmp .finish ; Operations performed when the application window is to be destroyed. ; This is a regular cleanup after receiving the 'WM_DESTROY' message: here ; we delete objects and resources allocated during the application window ; creation. We don't need to destroy all controls (child windows) manually ; because it will be done automatically. ; .wmdestroy: ; Delete the brush used to draw the edit control background. ; cmp [.hBrush], 0 jz .quit invoke DeleteObject, [.hBrush] .quit: ; Post the 'WM_QUIT' message to the application message queue. ; invoke PostQuitMessage, 0 .return0: xor eax, eax .finish: pop ebx ret endp ; A simple procedure that displays a message box containing a human readable ; description of the last error. ; proc ShowLastError, hwnd, LastErr locals Buffer dd ? endl lea eax, [Buffer] invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + FORMAT_MESSAGE_FROM_SYSTEM, 0, [LastErr],\ LANG_NEUTRAL, eax, 0, 0 invoke MessageBox, [hwnd], [Buffer], NULL, MB_ICONERROR + MB_OK invoke LocalFree, [Buffer] ret endp .end start ; The section of the program resources. Here we specify information about the ; application (description, author, version), the application manifest (informing ; Windows which version of the common controls program should use giving it ; a modern visual style instead of the classical Win9x "boxy" style) and the custom ; font used in the application. ; section '.rsrc' resource data readable RT_MANIFEST = 24 ID_MANIFEST = 1 directory RT_VERSION, versions,\ RT_MANIFEST, manifest,\ RT_FONT, fonts resource versions,\ 1, LANG_NEUTRAL, version resource manifest,\ ID_MANIFEST, LANG_NEUTRAL, man resource fonts,\ FONT_ID, LANG_NEUTRAL, CustomFont versioninfo version, VOS__WINDOWS32, VFT_APP, VFT2_UNKNOWN, LANG_ENGLISH + SUBLANG_DEFAULT, 0,\ 'FileDescription', 'Custom font example',\ 'LegalCopyright', '(C) Mikolaj Hajduk, 2013',\ 'FileVersion', PROG_VERSION,\ 'ProductVersion', PROG_VERSION,\ 'OriginalFilename', 'CustomFont.exe' ; Content of the manifest included as an application resource. ; resdata man db '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' db '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">' db '<assemblyIdentity ' db 'version="', PROG_VERSION, '" ' db 'processorArchitecture="X86" ' db 'name="MikolajHajduk.CustomFont" ' db 'type="win32"' db '/>' db '<description>Custom font example.</description>' db '<dependency>' db '<dependentAssembly>' db '<assemblyIdentity ' db 'type="win32" ' db 'name="Microsoft.Windows.Common-Controls" ' db 'version="6.0.0.0" ' db 'processorArchitecture="X86" ' db 'publicKeyToken="6595b64144ccf1df" ' db 'language="*"' db '/>' db '</dependentAssembly>' db '</dependency>' db '</assembly>' endres ; Included font resource. ; resdata CustomFont file 'Silubr.otf' endres The archive containing the program source code, a file with the Gothic font "Silubr" and the executable may be downloaded here. ______________________________________________________________________________________ A little historical digression. The choice of the Gothic font was caused by two factors: the first one is an attractive visual appearance of it, the second factor is an interesting history that is hidden behind it. The Silubr font (created by Robert Pfeffer, here you can download it freely, description of the Gothic keyboard layout you may find here) is an example of the font created in order to help reviving ancient systems of writing, dedicated especially to historians and linguists. Gothic alphabet created in 4th century by bishop Ulfilas (Wulfila) for writing in Gothic language inherited some letters from Greek others from Latin and Runic alphabets hence sometimes it gives an "exotic" feel when you look at the text written with it: The choice of the edit control colors ("silver" letters on the purple background) has been inspired by the Codex Argenteus ("Silver Book"), the most important source of the knowledge about the Gothic language. Reconstruction of an exemplary page: Gothic language had been used as a lingua franca in the Hunnic empire and had also an impact on Slavic languages, some common Polish words used till this day are of Gothic origin (during their long migration from Scandinavia to the Crimean Peninsula Goths spent a few centuries in the areas of today's Poland and Ukraine, see here) leaving some traces of their presence here (for example a cemetery near the village of Odry just a few tens of kilometers to the north from the place I live), so I think the historical and esthetic factors may be easily justified here. |
|||
09 Apr 2013, 13:58 |
|
hanjin 10 Apr 2013, 10:34
Great! Very detail-full source code!. I don't need to look into msdn. Thanks MHajduk
|
|||
10 Apr 2013, 10:34 |
|
MHajduk 10 Apr 2013, 11:35
Thanks guys for your kind reviews!
hopcode Three fingers write yet the whole body works (and has been tired)? Yeah, that's true even today when we don't write much with pen but almost everything type on the keyboard. I have another Latin proverb for you: Verba docent, exempla trahunt. (i.e. "Words instruct, examples lead"). hanjin Yes, the main motive to create such elaborated description was to give simple working examples that can be used almost independently from the other sources of information. |
|||
10 Apr 2013, 11:35 |
|
Picnic 13 Apr 2013, 12:56
Very nice sample MHajduk, useful to me. Nice commented, i admire your ability and attitude to explain the code so well. Thanks for sharing.
|
|||
13 Apr 2013, 12:56 |
|
MHajduk 13 Apr 2013, 21:22
Picnic wrote: Very nice sample MHajduk, useful to me. Nice commented, i admire your ability and attitude to explain the code so well. Thanks for sharing. |
|||
13 Apr 2013, 21:22 |
|
bitRAKE 22 Apr 2013, 23:10
If the VersionInfo is not listed in the directory then Windows ignores it.
Code: directory RT_BITMAP, imagebmps,\ RT_VERSION, versions,\ RT_MANIFEST, manifest _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
22 Apr 2013, 23:10 |
|
MHajduk 23 Apr 2013, 08:28
bitRAKE, I'm not sure what do you mean exactly because in my program presented above I have just used these directives:
Code: directory RT_VERSION, versions,\ RT_MANIFEST, manifest,\ RT_FONT, fonts resource versions,\ 1, LANG_NEUTRAL, version resource manifest,\ ID_MANIFEST, LANG_NEUTRAL, man resource fonts,\ FONT_ID, LANG_NEUTRAL, CustomFont versioninfo version, VOS__WINDOWS32, VFT_APP, VFT2_UNKNOWN, LANG_ENGLISH + SUBLANG_DEFAULT, 0,\ 'FileDescription', 'Custom font example',\ 'LegalCopyright', '(C) Mikolaj Hajduk, 2013',\ 'FileVersion', PROG_VERSION,\ 'ProductVersion', PROG_VERSION,\ 'OriginalFilename', 'CustomFont.exe' |
|||
23 Apr 2013, 08:28 |
|
bitRAKE 23 Apr 2013, 08:51
Eh, sorry. I posted in the wrong thread. It's the rebar example with the error.
_________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
23 Apr 2013, 08:51 |
|
MHajduk 23 Apr 2013, 09:05
Anyway, no problem, your mistake have increased a bit viewership of my thread.
|
|||
23 Apr 2013, 09:05 |
|
flaith 10 Jun 2013, 04:07
Thanks a lot for sharing, and big thanks for the comments, it's really valuable for a novice like me
_________________ Je suis sur de 'rien', mais je ne suis pas sur du 'tout'. |
|||
10 Jun 2013, 04:07 |
|
MHajduk 10 Jun 2013, 17:32
flaith wrote: Thanks a lot for sharing, and big thanks for the comments, it's really valuable for a novice like me |
|||
10 Jun 2013, 17:32 |
|
edfed 10 Jun 2013, 21:03
of course it's usefull. not always for everybody, but it is a valuable resource available whenever we need it now !
i think it can be really good to make a sort of little lib with a simple api to exploit transparently your trick maybe a set of macros or functions. but something really easy for noobs to exploit. like Code: include "thelib.inc" makethething parameter1,parameter2;this is the macro mov eax,parameter1 mov ebx,parameter2 call thething;the simple calling convention version push parameter1 push parameter2 call [thething]; the little more tricky calling convention. ;and so on... what do you think about it? and about a generalization of this practice on every assembly code ? |
|||
10 Jun 2013, 21:03 |
|
MHajduk 11 Jun 2013, 08:34
Your post is slightly enigmatic, edfed. I'm not sure what did you mean exactly. One of possibilities is that your question refers to the "Simple Conversion Routines (EAX to ASCII, Win32)" thread but if not what kind of trick you were talking of? The main goal of the program presented here is to show how to load a font from resources section and make it temporary available for the application, so we aren't dependent on the fonts installed in the system.
|
|||
11 Jun 2013, 08:34 |
|
edfed 12 Jun 2013, 09:40
showing the trick to do it is really cool.
i only suggested to improve the trick in order to let noobs (like me) use the trick with the less lines of code possible. do you think this is possible in the case of resources? maybe it should create three sections in one place. (code, data, resources) and exploit them with just one single macro like: Code: customPrint "text",mycustomfont instead of having a lot of little codes everywhere to do the job. there is effectivelly a link with the ascii to eax post in the sense i suggest a sort of simplification of every contributions in order to make them as simple as a mov. |
|||
12 Jun 2013, 09:40 |
|
baldr 12 Jun 2013, 18:52
edfed,
I do agree with MHajduk, your messages became extra cryptic to decode. |
|||
12 Jun 2013, 18:52 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.