The MASM Forum

Projects => MasmBasic & the RichMasm IDE => Topic started by: jj2007 on August 20, 2017, 08:02:31 AM

Title: Miscellaneous snippets
Post by: jj2007 on August 20, 2017, 08:02:31 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Dim MyInts() As DWORD
  For_ ct=0 To 999
        mov MyInts(ct), Rand(100)       ; 0...99
  Next
  Open "O", #0, "even.txt"
  Open "O", #1, "odd.txt"
  For_ ct=0 To MyInts(?)-1
        test MyInts(ct), 1
        setne al
        movsx ecx, al
        Print #ecx, Str$("%__i ", MyInts(ct))
  Next
  Close
  PrintLine     "even.txt: ", FileRead$("even.txt"), CrLf$
  Inkey         "odd.txt:  ", FileRead$("odd.txt")
EndOfCode


Output (shortened):even.txt:  86  82  22  78   2  56  36  14  58  46  68  16  84  12  94  42   0  16  90  42   8  94  90  52  92  90  42  60  88  86  10  64  3
8  92  16  24  92  10  46  34  28  66  74  92  88  82  40  44  26  84  94  48  32   8   0  44  68  40  50   0   2  12  38  12  82  80   0  7
2  76   0  74   8   0  76  64   8  28  46  10  48   6  94  90  10  84  68  62   2  82  96   0  98  20  36  12  96  14  98   8  96

odd.txt:   45   7  13  65  51  57  67  25  97  63  23  77  87  95  39  57  33  87  55  99   5  47  69  79  87  67  19  95  83  49  21  85  4
9  53   7  39  25  31  49  83  17  65  29  27  99  61  19  67  67  77  49  61  73  79  29  47  31  95  49  45  55  81  71  29   7  79  65  2
3  89  93  19  81  17  19  87  83  63  93  25  75  51  79  75  99   7  55  17  19  57  45  33  83  81  87  51  75  81  79  55  93
Title: A suicide proggie
Post by: jj2007 on November 10, 2017, 09:39:13 PM
Ever tried to kill the current executable? It's not that straightforward, for security reasons, but it can be done with little helpers:include \masm32\include\masm32rt.inc ; pure Masm32

.data?
ThisExe db MAX_PATH dup(?)

.code
start:
  mov edi, offset ThisExe
  invoke lstrcpy, edi, chr$("KillMe.exe ")
  invoke lstrcat, edi, rv(GetCommandLine)  ; this returns the path of the current exe
  invoke WinExec, edi, SW_MINIMIZE
  add edi, 11 ; advance to compensate for <KillMe.exe >
  print "check your disk to see if "
  print edi
  print " was killed"
  exit

end start


Source and binaries attached, must sit in the same folder as the current exe.
Title: Re: Miscellaneous snippets
Post by: jj2007 on November 12, 2017, 09:14:40 PM
Playing with inline assembly in FreeBasic, source attached; see discussion (https://www.freebasic.net/forum/viewtopic.php?f=7&t=25305&p=239205#p239205). Watch out for the red calls below...

Function LeapYearJ(ByVal yea As ULong) As ULong
Asm
  mov ecx, dword ptr [yea]
  test ecx, 3
  setz al
  jne 0f
  mov eax, ecx
  cdq
  push 100
  idiv dword ptr [esp] ' 0, 4, 8, ..., 96, 0
  test edx, edx ' mod 100=0 should set zero flag
  jne 1f
  mov eax, ecx
  cdq
  push 400
  idiv dword ptr [esp]
  pop eax
  dec edx '*** invert the zero flag ***
  sets dl ' sign set if edx was zero
  test dl, dl
1:
  pop eax
  setnz al
0:
  movsx eax, al
  mov [function], eax ' MichaelW
End Asm
End Function

...
for i = 1 to years ' assembly function, inlined by compiler
asm int 3 ' forum
lyears=lyears+LeapYearJ(i)
asm nop
asm nop
asm nop
asm nop
next


00407C20        �> �CC                �int3
00407C21        �. �8B45 D0           �mov eax, [ebp-30]
00407C24        �. �8945 D8           �mov [ebp-28], eax
00407C27        �. �C745 DC 00000000  �mov dword ptr [ebp-24], 0
00407C2E        �. �C70424 24A04000   �mov dword ptr [esp], offset 0040A02 ; ASCII "C:\FreeBasic\tmp\TmpFile.bas"
00407C35        �. �E8 169EFFFF       �call 00401A50                       ; �TmpFile.00401A50
00407C3A        �. �56                �push esi                            ; �Arg1
00407C3B        �. �8945 C0           �mov [ebp-40], eax                   ; �
00407C3E        �. �C70424 80A04000   �mov dword ptr [esp], offset 0040A08 ; �ASCII "LEAPYEARJ"
00407C45        �. �E8 669EFFFF       �call 00401AB0                       ; �TmpFile.00401AB0
00407C4A        �. �57                �push edi
00407C4B        �. �8945 BC           �mov [ebp-44], eax
00407C4E        �. �8B4D D8           �mov ecx, [ebp-28]
00407C51        �. �F7C1 03000000     �test ecx, 00000003
00407C57        �. �0F94C0            �setz al
00407C5A        �.�75 22             �jnz short 00407C7E
00407C5C        �. �89C8              �mov eax, ecx
00407C5E        �. �99                �cdq
00407C5F        �. �6A 64             �push 64
00407C61        �. �F73C24            �idiv dword ptr [esp]
00407C64        �. �85D2              �test edx, edx
00407C66        �.�75 12             �jnz short 00407C7A
00407C68        �. �89C8              �mov eax, ecx
00407C6A        �. �99                �cdq
00407C6B        �. �68 90010000       �push 190
00407C70        �. �F73C24            �idiv dword ptr [esp]
00407C73        �. �58                �pop eax
00407C74        �. �4A                �dec edx
00407C75        �. �0F98C2            �sets dl
00407C78        �. �84D2              �test dl, dl
00407C7A        �> �58                �pop eax
00407C7B        �. �0F95C0            �setnz al
00407C7E        �> �0FBEC0            �movsx eax, al
00407C81        �. �8945 DC           �mov [ebp-24], eax
00407C84        �. �8B7D BC           �mov edi, [ebp-44]
00407C87        �. �893C24            �mov [esp], edi
00407C8A        �. �E8 219EFFFF       �call 00401AB0                       ; �TmpFile.00401AB0
00407C8F        �. �50                �push eax                            ; �Arg1
00407C90        �. �8B45 C0           �mov eax, [ebp-40]                   ; �
00407C93        �. �890424            �mov [esp], eax                      ; �
00407C96        �. �E8 B59DFFFF       �call 00401A50                       ; �TmpFile.00401A50
00407C9B        �. �50                �push eax                            ; �Arg1
00407C9C        �. �8B45 DC           �mov eax, [ebp-24]                   ; �
00407C9F        �. �0145 D4           �add [ebp-2C], eax                   ; �
00407CA2        �. �90                �nop                                 ; �
00407CA3        �. �90                �nop                                 ; �
00407CA4        �. �90                �nop                                 ; �
00407CA5        �. �90                �nop                                 ; �
00407CA6        �. �8B45 D0           �mov eax, [ebp-30]                   ; �
00407CA9        �. �40                �inc eax                             ; �
00407CAA        �. �8945 D0           �mov [ebp-30], eax                   ; �
00407CAD        �. �3D 80969800       �cmp eax, 989680                     ; �
00407CB2        �.�0F86 68FFFFFF     �jbe 00407C20                        ; �
Title: List of files in a zip archive
Post by: jj2007 on November 26, 2017, 10:55:33 PM
Build it, then drag an archive over the exe:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  UnzipInit CL$()
  .if !Sign?
        For_ ecx=0 To edx-1
                PrintLine Files$(ecx)
        Next
  .endif
  Inkey CrLf$, "Now copy the names from the console menu"
EndOfCode


Output e.g. from the COM interface archive (http://masm32.com/board/index.php?topic=6313.msg71823#msg71823):
GetComInterface.asc
GetComInterface.dll
Title: Re: A suicide proggie
Post by: aw27 on November 27, 2017, 02:08:34 AM
Quote from: jj2007 on November 10, 2017, 09:39:13 PM
Ever tried to kill the current executable? It's not that straightforward, for security reasons, but it can be done with little helpers:include \masm32\include\masm32rt.inc ; pure Masm32

.data?
ThisExe db MAX_PATH dup(?)

.code
start:
  mov edi, offset ThisExe
  invoke lstrcpy, edi, chr$("KillMe.exe ")
  invoke lstrcat, edi, rv(GetCommandLine)  ; this returns the path of the current exe
  invoke WinExec, edi, SW_MINIMIZE
  add edi, 11 ; advance to compensate for <KillMe.exe >
  print "check your disk to see if "
  print edi
  print " was killed"
  exit

end start


Source and binaries attached, must sit in the same folder as the current exe.

Come on, JJ  :badgrin: :badgrin:

Try this instead: http://masm32.com/board/index.php?topic=6713.0
Title: Set wallpaper with IActiveDesktop::SetWallpaper
Post by: jj2007 on December 13, 2017, 10:45:07 AM
This should work but it doesn't :(

It builds fine and returns S_OK, no error, but it does not set the wallpaper. MSDN says it's supported for XP and earlier - seriously? But even on XP it has no effect.

include \masm32\MasmBasic\MasmBasic.inc
include IActiveDesktop.inc      ; IActiveDesktop STRUCT, CLSID_ActiveDesktop, IID_IActiveDesktop (attached)
.code
SetMyWallpaper proc pDesktopImg  ; adapted from johnsa's code (http://masm32.com/board/index.php?topic=6736.msg72310#msg72310)
LOCAL pAD
  invoke CoCreateInstance, addr CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, addr IID_IActiveDesktop, addr pAD
  .if eax==S_OK
       CoInvoke pAD, IActiveDesktop.SetWallpaper, pDesktopImg, 0
       deb 4, "SetWp", $Err$()         ; OK, operation completed - but no effect
       CoInvoke pAD, IActiveDesktop.Release
  .endif
  ret
SetMyWallpaper endp
  Init
  If_ Not rv(CoInitializeEx, 0, COINIT_APARTMENTTHREADED) Then invoke SetMyWallpaper, wChr$("\Masm32\examples\exampl04\car\car.jpg")
  invoke CoUninitialize
EndOfCode
Title: Re: Miscellaneous snippets
Post by: Vortex on December 14, 2017, 05:41:02 AM
Hi Jochen,

Can you try the attached sample?
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 14, 2017, 06:56:10 AM
Hi Erol,
Your example changed slightly the position of the existing wallpaper, but the old image remained...
To be continued ;-)
Title: Re: Miscellaneous snippets
Post by: Vortex on December 14, 2017, 07:07:05 AM
Hi Jochen,

Not sure but maybe specifying the full path of the image can solve the problem.

WSTR        DesktopImg,"test.bmp"
.
.
coinvoke    pAD,IActiveDesktop,SetWallpaper,OFFSET DesktopImg,0


GetFullPathName can retrieve the full path.
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 14, 2017, 08:09:15 AM
Hi Erol,

Full path works, thanks a lot! Now I'll try my version 8)

P.S.: It works ;)

include \masm32\MasmBasic\MasmBasic.inc
include IActiveDesktop.inc      ; IActiveDesktop STRUCT, CLSID_ActiveDesktop, IID_IActiveDesktop
.code
SetMyWallpaper proc pDesktopImg         ; adapted from Vortex (http://masm32.com/board/index.php?topic=6483.msg72338#msg72338) and johnsa's code (http://masm32.com/board/index.php?topic=6736.msg72310#msg72310)
LOCAL pAD, wpo:WALLPAPEROPT
  ClearLocals
  .if !rv(CoCreateInstance, addr CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, addr IID_IActiveDesktop, addr pAD)
        add wpo.dwSize, WALLPAPEROPT
        add wpo.dwStyle, WPSTYLE_CENTER or WPSTYLE_STRETCH
        CoInvoke pAD, IActiveDesktop.SetWallpaper, wRec$(pDesktopImg), 0
        CoInvoke pAD, IActiveDesktop.SetWallpaperOptions, addr wpo, 0
        CoInvoke pAD, IActiveDesktop.ApplyChanges, AD_APPLY_ALL
        CoInvoke pAD, IActiveDesktop.Release
  .endif
  ret
SetMyWallpaper endp
  Init
  Let esi=wCL$()
  .if !rv(CoInitializeEx, 0, COINIT_APARTMENTTHREADED)
        wMsgBox 0, esi, "Set as wallpaper?", MB_OKCANCEL or MB_ICONQUESTION
        If_ eax==IDOK Then <invoke SetMyWallpaper, Qtrim$(Utf8$(esi))>
        invoke CoUninitialize
  .endif
EndOfCode


Full project attached, including a really nice wallpaper - a very special view of a European city. Extract all files to a folder, then drag the jpg over the exe :biggrin:
Title: Delay until
Post by: jj2007 on December 16, 2017, 02:51:15 PM
I am testing a new syntax for Delay (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1212) and would appreciate some results for other Windows versions:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
uselib ntdll
  SetGlobals resMin, resMax, resCurrent
  Init
  invoke NtQueryTimerResolution, addr resMin, addr resMax, addr resCurrent
  deb 4, "Timer resolution", resMin, resMax, resCurrent

  PrintLine CrLf$, "These lines should print about one second after the start, at ", fTime$(0, "HH:mm:??.123"), " millisecs"
  For_ ecx=0 To 4
        Delay Rand(500)         ; sleep 0..499 milliseconds
        NanoTimer()
        PrintLine fTime$(0, "HH:mm:ss.fff"), Tb$, "started"
        Delay until fTime$(s:1, "HH:mm:ss.123")         ; use time$(current plus one second)
        PrintLine fTime$(0, "HH:mm:ss.fff "), Tb$, NanoTimer$(), " passed", CrLf$
  Next
  Inkey Str$("This is Windows version %i", MbWinVersion()), Str$(".%i", ecx)
EndOfCode


Output:
Timer resolution
resMin          156001
resMax          5000
resCurrent      10000

These lines should print about one second after the start, at 04:47:??.123 millisecs
04:47:16.057    started
04:47:17.123    1066 ms passed

04:47:17.159    started
04:47:18.123    964 ms passed

04:47:18.191    started
04:47:19.123    932 ms passed

04:47:19.554    started
04:47:20.123    569 ms passed

04:47:20.450    started
04:47:21.123    673 ms passed

This is Windows version 6.1


The new version of the fTime$() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1268) macro can display milliseconds using the fff format specifier. See Microsoft: How to: Display Milliseconds in Date and Time Values (https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-display-milliseconds-in-date-and-time-values) for details.
Title: Re: Miscellaneous snippets
Post by: felipe on December 16, 2017, 02:54:37 PM
Timer resolution
resMin          156250
resMax          5000
resCurrent      156255

These lines should print about one second after the start, at 23:52:??.123 milli
secs
23:52:37.774    started
23:52:38.123    348 ms passed

23:52:38.161    started
23:52:39.123    962 ms passed

23:52:39.193    started
23:52:40.124    930 ms passed

23:52:40.556    started
23:52:41.123    567 ms passed

23:52:41.451    started
23:52:42.123    672 ms passed

This is Windows version 6.3

From windows 8.1
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 16, 2017, 07:36:52 PM
Thanks, Felipe :t
Here are Win10 results:Timer resolution
resMin          156250
resMax          5000
resCurrent      5007

These lines should print about one second after the start, at 09:35:??.123 millisecs
09:35:03.858    started
09:35:04.123    264 ms passed

09:35:04.159    started
09:35:05.123    964 ms passed

09:35:05.191    started
09:35:06.123    931 ms passed

09:35:06.554    started
09:35:07.123    568 ms passed

09:35:07.450    started
09:35:08.123    672 ms passed

This is Windows version 10.0


Note that even after a reboot, the current resolution is 0.5 milliseconds:resMax          5000
resCurrent      5007


Your Windows 8.1 results are still at the 15.6 ms resolution. It seems they changed it definitely with Win10, which makes sense because a) the hardware got faster and b) even an ordinary browser like FF or PaleMoon sets it to 10000 when you visit YouTube.

So has GetTickCount finally become a high resolution timer?

NOPE. Have a look at these GetTickCount results:ticks   systime
   0    10:02:51.678
   0    10:02:51.679
   0    10:02:51.681
   0    10:02:51.682
   0    10:02:51.683
   0    10:02:51.684
   0    10:02:51.686
  15    10:02:51.688
  15    10:02:51.689
  15    10:02:51.690
  15    10:02:51.691
  15    10:02:51.692
  15    10:02:51.693
  15    10:02:51.695
  15    10:02:51.696
  15    10:02:51.697
  15    10:02:51.698
  15    10:02:51.700
  15    10:02:51.701
  15    10:02:51.702
  31    10:02:51.703
  31    10:02:51.705
  31    10:02:51.706


Between each line, there is a Sleep(1), and the high resolution timer shows that the systemtime gets adjusted in one milliseconds increments; but GetTickCount keeps reporting with its low 15.625 ms granularity 8)
Title: Re: Miscellaneous snippets
Post by: Vortex on December 16, 2017, 09:11:50 PM
Hi Jochen,

Here are my results, XP 64-bit :


Timer resolution
resMin          156250
resMax          10000
resCurrent      156250

These lines should print about one second after the start, at 13:11:??.123 milli
secs
13:11:17.531    started
13:11:18.125    591 ms passed

13:11:18.156    started
13:11:19.125    966 ms passed

13:11:19.187    started
13:11:20.125    935 ms passed

13:11:20.562    started
13:11:21.125    560 ms passed

13:11:21.453    started
13:11:22.109    669 ms passed

This is Windows version 5.2
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 16, 2017, 09:15:25 PM
Thanks, Erol. So it starts always 2 ms later, 125 instead of 123... ::)

Similar for XP-32, a Virtual Machine:Timer resolution
resMin          100144
resMax          10032
resCurrent      100144

These lines should print about one second after the start, at 11:16:??.123 milli
secs
11:16:29.859    started
11:16:30.129    254 ms passed

11:16:30.159    started
11:16:31.121    963 ms passed

11:16:31.191    started
11:16:32.122    931 ms passed

11:16:32.553    started
11:16:33.124    570 ms passed

11:16:33.454    started
11:16:34.125    669 ms passed

This is Windows version 5.1
Title: Deleting selected elements from a string array
Post by: jj2007 on December 18, 2017, 08:28:38 AM
A little exercise in deleting elements from a string array:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  void NanoTimer()              ; start the timer
  Recall "TestFile.txt", b$()   ;
  PrintLine NanoTimer$(), " for loading the file into the b$() text array"
  void NanoTimer()              ; start the timer
  xor ecx, ecx
  .Repeat
        If_ Instr_(b$(ecx), "devil", 5) Then <mcs Delete b$(ecx) : dec ecx>
        inc ecx
  .Until ecx>=b$(?)
  Inkey NanoTimer$(), " for deleting the devil. Save the file (y)?"
  If_ eax=="y" Then Store "NoDevil.txt", b$()
EndOfCode


Result on an i5:3458 µs for loading the file into the b$() text array
4954 µs for deleting the devil. Save the file (y)?



The required text file is here (http://www.webalice.it/jj2006/pics/testfile.zip) - unzip to the folder where the attached exe sits.
Title: Deleting selected elements from a text file
Post by: jj2007 on December 19, 2017, 10:00:07 PM
Same as above, but not line-based. Words are removed with Replace$() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1079):

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  void NanoTimer()              ; start the timer
  Let esi=FileRead$("TestFile.txt")
  PrintLine NanoTimer$(), " for loading the file"
  void NanoTimer()              ; start the timer
  Let esi=Replace$(esi, "devil", 0, 5)         ; mode 5: case-insensitive, full word, i.e. devils & devilish still there ;-)
  Inkey NanoTimer$(), " for deleting the devil. Save & see the file (y)?"
  If_ eax=="y" Then <mcs FileWrite "NoDevil.txt", esi : ShEx "NoDevil.txt">
EndOfCode


2392 µs for loading the file
6269 µs for deleting the devil. Save & see the file (y)?
Title: Mirror$() for UTF-8 strings
Post by: jj2007 on December 24, 2017, 05:21:24 AM
Work in progress, looks fine so far:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
include uMirror$.inc
  SetGlobals a$="Enter text here"
  SetGlobals r$="Введите текст здесь"         ; "Enter text here" in Russian
  SetGlobals cm$, c$="在這裡輸入文字", c4$="<see attached source>"        ; "Enter text here" and some 4-byte encoded string in Chinese
  Init
  PrintLine uMirror$(a$)
  PrintLine uMirror$(r$)
  Let cm$=uMirror$(c$)
  uMsgBox 0, cm$, c$, MB_OK
EndOfCode


ereh txet retnE
ьседз тскет етидевВ


P.S.: For the first time, I see the SMF software (or the browser??) choke over a UTF-8 string, see the red part above. It works fine in RichMasm, see attached *.asc source. This is a rare type of UTF-8 using 4-byte encoding.
Title: ClearFileCache for timings and benchmarks involving disk I/O
Post by: jj2007 on December 24, 2017, 11:07:08 PM
Just learned a new trick from deltarho[1859] (https://www.freebasic.net/forum/viewtopic.php?f=7&t=26208&sid=cce04fa09c9fca354830eeb043f64a98#p241539) - clear the file cache for better testing:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)

ClearFileCache MACRO fname
  push ecx
  ClearLastError
  invoke CreateFile, repargA(f$), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN or FILE_FLAG_NO_BUFFERING, 0
  invoke CloseHandle, eax
  pop ecx
ENDM

  SetGlobals f$
  Init
  PrintLine "with file caching, ", Cpu$(), ":"  ; OPT_Arg1 C:\Masm32\MasmBasic\AscUser\FatFile.txt
  Let f$=CL$()
  PrintLine "Reading ", f$
  .if !Exist(f$)
        Let f$="\Masm32\include\Windows.inc"
        MsgBox 0, Cat$("Commandline empty or invalid - using this file now:"+CrLf$+f$), "Hi", MB_OK
  .endif
  For_ ecx=0 To 9
        NanoTimer()
        Recall f$, L$()                                                 ; file to array L$() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1172)
        Print Str$("%i strings, ", eax), NanoTimer$()
        NanoTimer()
        Let esi=FileRead$(f$)                                           ; file to buffer esi (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1075)
        PrintLine Str$("\t%i bytes, ", LastFileSize), NanoTimer$()
  Next
  PrintLine CrLf$, "no caching:"
  For_ ecx=0 To 9

        ClearFileCache f$
        NanoTimer()
        Recall f$, L$()
        Print Str$("%i strings, ", eax), NanoTimer$()

        ClearFileCache f$
        NanoTimer()
        Let esi=FileRead$(f$)
        PrintLine Str$("\t%i bytes, ", LastFileSize), NanoTimer$()
  Next
  Inkey "--- hit any key ---"
EndOfCode


The results are pretty clear - upper half uses the cache, lower half doesn't:with file caching, Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz:
Reading C:\Masm32\MasmBasic\AscUser\FatFile.txt
3038300 strings, 294 ms 404739200 bytes, 209 ms
3038300 strings, 354 ms 404739200 bytes, 237 ms
3038300 strings, 337 ms 404739200 bytes, 231 ms
3038300 strings, 346 ms 404739200 bytes, 229 ms
3038300 strings, 328 ms 404739200 bytes, 235 ms
3038300 strings, 332 ms 404739200 bytes, 229 ms
3038300 strings, 339 ms 404739200 bytes, 236 ms
3038300 strings, 337 ms 404739200 bytes, 238 ms
3038300 strings, 339 ms 404739200 bytes, 237 ms
3038300 strings, 334 ms 404739200 bytes, 239 ms

no caching:
3038300 strings, 4999 ms        404739200 bytes, 4903 ms
3038300 strings, 4998 ms        404739200 bytes, 4938 ms
3038300 strings, 5011 ms        404739200 bytes, 5061 ms
3038300 strings, 5010 ms        404739200 bytes, 4919 ms
3038300 strings, 5002 ms        404739200 bytes, 4897 ms
3038300 strings, 5003 ms        404739200 bytes, 4903 ms
3038300 strings, 5025 ms        404739200 bytes, 4923 ms
3038300 strings, 5016 ms        404739200 bytes, 4921 ms
3038300 strings, 4994 ms        404739200 bytes, 4906 ms
3038300 strings, 5038 ms        404739200 bytes, 4904 ms


Project attached. You can drag any plain text or Unicode file over the exe, but note that on Win7-64, for example, HeapAlloc begins to choke at around 900MB. If you haven't used the file for a while, the very first line will show a higher time - it needs to be cached...
Title: Spreadsheet editor
Post by: jj2007 on December 28, 2017, 04:15:40 AM
Work in progress, an extension of this post. (http://masm32.com/board/index.php?topic=5976.msg72774#msg72774)

Fearless and José put me on the right track, see Select a single cell in a listview (http://masm32.com/board/index.php?topic=6788.msg72804#msg72804). So here is the proof that it is indeed possible to use a listview control as a replacement for Excel :icon_mrgreen:

You may have to click two or three times on a cell to select it. Hitting Return does not work. Saving the edits works, provided that you selected another cell before; the resulting temp file will open with your user-defined *.tab viewer, Excel or LibreOffice, whatever. Note that both Excel and OpenCalc are too dumb to recognise that it's a UTF-8 coded *.tab file. RichMasm shows it correctly, though.

The control is Unicode-aware, as you can see in cell R3C1 ;)

P.S.: There is a little mystery about the order of the header columns. I swear it's not my fault.
Title: Re: Miscellaneous snippets
Post by: fearless on December 28, 2017, 05:25:03 AM
return in the listview or return in the editbox doesnt work?

Might be possible to get NM_RETURN and handle last known cell (row,col) to "edit" with the editbox placement. Or maybe some handling of WM_CHAR / WM_KEYDOWN directly in a subclass of listview parent, or NM_RETURN in that subclass. Might require IsDialogMessage in messageloop and handle want all keys or want return thing from dlg message thing (forget exact name of the msg event)
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 28, 2017, 06:49:10 AM
Slow down, man :P

Seriously: I will check what is available. Just discovered a very old article: Easy Navigation Through an Editable List (https://www.codeguru.com/cpp/controls/listview/editingitemsandsubitem/article.php/c937/Easy-Navigation-Through-an-Editable-List-View.htm) Posted by Lee Nowotny on June 19th, 1999 - just a bit over 18 years ago. Good to see that I'm not the first one to attack this. Fortunately I have a nice tool called deb (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1019):Event Message
  inc msgCount
  deb 4, "main WndProc", chg:msgCount


With another one for the listview subproc, you can wade through tons of stuff like this:main WndProc    810     WM_NOTIFY: -121
SubListview     811     WM_NOTIFY: -121
main WndProc    813     WM_PARENTNOTIFY
SubListview     817     WM_MOUSEACTIVATE
SubListview     819     WM_LBUTTONDOWN
main WndProc    821     WM_MOUSEACTIVATE
main WndProc    823     WM_NOTIFY: NM_TOOLTIPSCREATED
main WndProc    825     WM_KILLFOCUS
SubListview     826     WM_CAPTURECHANGED
SubListview     827     WM_IME_SETCONTEXT
main WndProc    829     WM_IME_SETCONTEXT
SubListview     832     WM_SETFOCUS
main WndProc    874     WM_NOTIFY: -121
main WndProc    881     WM_NOTIFY: -121
main WndProc    888     WM_NOTIFY: -121
main WndProc    895     WM_NOTIFY: -121
main WndProc    902     WM_NOTIFY: -121
main WndProc    909     WM_NOTIFY: -121
main WndProc    911     WM_NOTIFY: -121
main WndProc    913     WM_NCACTIVATE
main WndProc    915     WM_GETTEXT
main WndProc    917     WM_ACTIVATE
SubListview     918     WM_CAPTURECHANGED
main WndProc    920     WM_ACTIVATEAPP
SubListview     921     WM_KILLFOCUS


I will need SubListview     5030    WM_LBUTTONDOWN, the built-in activation is too clumsy. And there are many more interesting messages to exploit...
Title: Table control
Post by: jj2007 on December 29, 2017, 10:40:18 AM
Playtime :P

The main features are implemented: Loading, editing, navigation and saving. Let me know if it works on your machine.

There will be two ways to create it:

  if 0
       Recall "FatTable.tab", some$(), tab
        GuiControl MyData, "table", y500, h500, some$()
  else
       GuiControl MyData, "table", y500, h500, "FatTable.tab"
  endif


The first one assumes that you have already a two-dimensional array, so you pass it as some$().
The second one simply passed a filename.

Confused source, exe and two other files attached. Extract to a folder and launch the exe.
Title: Re: Miscellaneous snippets
Post by: HSE on December 29, 2017, 10:56:12 AM
Working JJ :t

Still don't work ESC nor Ctrl-Z  :biggrin:
Title: Floating point comparisons
Post by: jj2007 on December 29, 2017, 11:08:45 AM
Quote from: HSE on December 29, 2017, 10:56:12 AM
Still don't work ESC nor Ctrl-Z  :biggrin:

Thanks - it's work in progress and needs a lot of cleanup.

Another topic, floating point comparisons:

include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals REAL10 MyPI=3.141592653589793238, hiPI=3.141592653589793239, loPI=3.141592653589793237
  SetGlobals REAL10 MyPI30=3.141592653589793238e30, hiPI30=3.141592653589793239e30, loPI30=3.141592653589793237e30
  SetGlobals REAL10 MyPIm30=3.141592653589793238e-30, hiPIm30=3.141592653589793239e-30, loPIm30=3.141592653589793237e-30
  Init
  PrintLine Str$("\nPI=%Jf", MyPI), " - top precision:"
  Fcmp hiPI, PI, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPI, PI, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine "---- high precision:"
  Fcmp hiPI, PI, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif

  Fcmp loPI, MyPI, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine Str$("\nPI30=%Jf", MyPI30), " - top precision:"

  Fcmp hiPI30, MyPI30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPI30, MyPI30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine "---- high precision:"
  Fcmp hiPI30, MyPI30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPI30, MyPI30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine Str$("\nPI-30=%Jf", MyPIm30), " - top precision:"

  Fcmp hiPIm30, MyPIm30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPIm30, MyPIm30, top
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  PrintLine "---- high precision:"
  Fcmp hiPIm30, MyPIm30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "hiPi is greater"
  .else
        PrintLine "hiPi is lesser"
  .endif
  Fcmp loPIm30, MyPIm30, hi
  .if Zero?
        PrintLine "they are equal"
  .elseif FcmpGreater
        PrintLine "loPi is greater"
  .else
        PrintLine "loPi is lesser"
  .endif

  Inkey
EndOfCode


Output (as expected):PI=3.141592653589793238 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI30=3.141592653589793238e+30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI-30=3.141592653589793238e-30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal
Title: Re: Miscellaneous snippets
Post by: LiaoMi on December 29, 2017, 11:34:53 AM
Theoretically, if the source code is a template like in Delphi, then it's time to start writing a good decompiler for a MasmBasic  :P


PI=3.141592653589793238 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI30=3.141592653589793238e+30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal

PI-30=3.141592653589793238e-30 - top precision:
hiPi is greater
loPi is lesser
---- high precision:
they are equal
they are equal
Title: Get size of a file over 4 GB
Post by: jj2007 on January 05, 2018, 07:15:54 AM
For syntax and options, see Lof() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1036)

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  .if !Exist("GigaTest.txt")
        Inkey "Are you sure you want to create a 4 GB file in ", CurDir$(), "(y)?", CrLf$
        .if eax=="y"
                ClearLastError
                Open "O", #1, "GigaTest.txt"
                .if eax==INVALID_HANDLE_VALUE
                                Print "Open:  ", Err$()
                .else
                                ClearLastError
                                Let edi=FileRead$("\Masm32\include\Windows.inc")+FileRead$("\Masm32\include\WinExtra.inc")
                                PrintLine Str$("Len=%i bytes\n", Len(edi))      ; 2045966 bytes
                                Print "Read:  ", Err$()
                                ClearLastError
                                For_ ecx=0 To 2500      ; 2501*2045966=5116960966
                                       PrintLine #1, edi
                                Next
                                Print "Write: ", Err$()
                                Close
                .endif
        .endif
  .endif
  Inkey Str$("Filesize = %u bytes", edx::Lof("GigaTest.txt")), Str$(" = %3f GB", edx::Lof("GigaTest.txt")/(1 shl 30))
EndOfCode


Output: Filesize = 5116965968 bytes = 4.77 GB
Title: Re: Miscellaneous snippets
Post by: HSE on January 12, 2018, 12:10:41 AM
Hi JJ!

I extract part of the program. Still not working very well, but the main features are there (I think).

Regards

LATER: New file. I forget a little problem if first column is activated.

A lot later: New file. I forget something else.
Title: Re: Miscellaneous snippets
Post by: jj2007 on January 12, 2018, 01:24:04 AM
Very nice work :t
Title: Send mail with attachments
Post by: jj2007 on March 12, 2018, 08:55:41 PM
Drag files over the exe and tell me how your mail client reacts. I've tested it on Win7-64 and Win10 Home with Thunderbird.

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
mapiMsg         MapiMessage <>

  Init
  Dll "Mapi32"
  Declare MAPISendMail, 5

  mov edi, offset mapiMsg
  Mapi equ [edi.MapiMessage]
  mov Mapi.ulReserved, CP_UTF8   ; does not work *)
  mov Mapi.lpszSubject, Chr$("Greetings from Masm")
  mov Mapi.lpszNoteText, cfm$("Hi folks,\nNever was sending mails easier!\nSincerely,\njj2007")
  GetFiles CL                           ; get a list of files from the commandline
  mov Mapi.nFileCount, eax
  xchg eax, ecx
  Dim MapiFiles(ecx) As MapiFileDesc
  or MapiFiles(ecx, nPosition), -1
  For_ ecx=0 To ecx-1
        push Files$(ecx)
        lea eax, MapiFiles(ecx, lpszPathName)
        pop [eax]
  Next
  lea eax, MapiFiles(0, ulReserved)
  mov Mapi.lpFiles, eax
  .if MAPISendMail(0, 0, addr mapiMsg, MAPI_DIALOG, 0)
        MsgBox 0, Str$("Mapi error %i", eax), "An error occurred:", MB_OK
  .endif
EndOfCode



Project attached. Note that there is a blank line before the "Hi folks"; in theory, the nPosition member of the MapiFileDesc structure could influence that, but according to this post on ExpertExchange (https://www.experts-exchange.com/questions/28399412/MapiSendMail-attachments-don%27t-display.html), "It appears that MapiSendMail does not perform as Microsoft has stated in their documentation" 8)

*) MapiMessage structure (https://msdn.microsoft.com/en-us/library/windows/desktop/dd296732%28v=vs.85%29.aspx):

QuoteulReserved

    Reserved; must be zero or CP_UTF8. If CP_UTF8, the following are UTF-8 instead of ANSI strings: lpszSubject, lpszNoteText, lpszMessageType, lpszDateReceived, lpszConversationID.

And this is simply not true, Redmond - see https://stackoverflow.com/questions/9943314/windows-mapi-unicode-issue  :icon_redface:
Title: GetRandomStrings
Post by: jj2007 on March 15, 2018, 01:30:08 AM
Could be useful for testing sort algos etc:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Dll "RandomStrings"                   ; the DLL must be in the same folder
  Declare RandomString
  .Repeat
        For_ ecx=0 To 5
                Print RandomString(), " "
        Next
        Inkey cfm$("- more (no=n)?\n")
  .Until eax=="n" || eax==VK_ESCAPE
EndOfCode


Output:
imprisoning barked channel superstitious practical spectre - more (no=n)?
currants shower agitation lions motherly forces - more (no=n)?
negus proofs devil chose observation individuals - more (no=n)?
quarrelled whistled place commanded stipulation cannot - more (no=n)?
deeds settled taught verdict unsocial goeth - more (no=n)?
nefarious herald extinguishes accounted system military - more (no=n)?
worse colouring attacks transfixed hearts binding - more (no=n)?
instruments rally singly sword until profit - more (no=n)?
tranquilly luring convinced unchecked trade hears - more (no=n)?
violent packet sternly tearing kneeled crumbled - more (no=n)?
... etc ...
Title: Re: Miscellaneous snippets
Post by: anunitu on March 15, 2018, 03:33:13 AM
i am thinking JJ is the REAL MASM Wizard for sure.
Title: Re: Miscellaneous snippets
Post by: jj2007 on March 15, 2018, 05:37:33 AM
Thanks - too much honour :icon_redface:

Here is version 2, with pseudo and real random modes (and 20,000 words for choice):

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Dll "RandomStrings"                   ; the DLL must be in the same folder
  Declare RandomString, 1
  .Repeat
        For_ ecx=0 To 5
                Print RandomString(0), " "      ; 0=pseudo, 1=real random
        Next
        Inkey cfm$("- more (no=n)?\n")
  .Until eax=="n" || eax==VK_ESCAPE
EndOfCode


In mode 0, the sequence is always identical. It looks random, and is random according to some popular measures of randomness, but you'll always see the same strings. This is particular useful if, for example, your sort algo stumbles over a specific word, and you want to debug that event. It's also a bit faster - in "real" mode, one Million strings need almost one second on my i5. The pseudo mode is 70 times faster.
Title: Tweety rotates
Post by: jj2007 on April 26, 2018, 12:24:16 PM
Little demo for image rotation (strangely enough, this GdiPlus function has never been used in this forum ::)):

GuiParas equ "Image rotation demo", w400, h440
include \masm32\MasmBasic\Res\MbGui.asm
  GuiImageCallback Rotate       ; user-defined function
  SetGlobals halfWidth, halfHeight, REAL4:rotateAngle, movX, movY
Event Paint
  imul eax, GuiWidth, 100       ; width*100/128
  sar eax, 8
  add eax, 20
  mov halfWidth, eax
  imul eax, GuiHeight, 100      ; height*100/128
  sar eax, 8
  mov halfHeight, eax
  GuiImage 99, 0, 0, halfWidth, halfHeight      ; res ID, x, y, w, h 
  GuiCls                               ; trigger next paint event
EndOfEvents
Rotate:
  fild halfWidth                        ; an integer
  fadd FP4(35.0)                        ; add a fixed x offset
  fstp movX                             ; Gdi+ needs a float
  fild halfHeight
  fadd FP4(32.0)
  fstp movY
  gdi+ GdipTranslateWorldTransform, giGraphics, movX, movY, MatrixOrderPrepend  ; move to the middle
  gdi+ GdipRotateWorldTransform, giGraphics, rotateAngle, MatrixOrderPrepend    ; rotate
  fld rotateAngle                       ; add one degree for next paint event
  fadd FP4(1.0)
  fstp rotateAngle
  ret
GuiEnd
Title: Where do you live?
Post by: jj2007 on May 03, 2018, 09:39:29 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
include Geo.inc
  Init
  PrintLine "GEO_LCID:   ", Tb$, Geo$(GEO_LCID)
  PrintLine "GEO_RFC1766:", Tb$, Geo$(GEO_RFC1766), CrLf$
  Inkey "I live in ", Geo$(), " (aka ", Geo$(GEO_OFFICIALNAME), ") at ", Geo$(GEO_LATITUDE), " North, ", Geo$(GEO_LONGITUDE), " East"
EndOfCode


Output:GEO_LCID:       00000809
GEO_RFC1766:    en-it

I live in Italia (aka Repubblica italiana) at 42.768 North, 12.492 East
Title: Push & Pop xmm registers
Post by: jj2007 on May 06, 2018, 08:03:06 PM
Inspired by the Campus post PUSH & POP question (http://masm32.com/board/index.php?topic=7113.msg76861#msg76861) by DayDreamer:

include \Masm32\MasmBasic\Res\JBasic.inc        ; ## builds in 32- or 64-bit mode with ML and UAsm
include PushPopXmm.inc
.code
xvalue0         OWORD 11111111222222223333333344444444h
xvalue1         OWORD 55555555666666667777777788888888h
Init           ; OPT_64 1      ; put 0 for 32 bit, 1 for 64 bit assembly
  PrintLine Chr$("This code was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format")
  movups xmm0, xvalue0
  movups xmm7, xvalue1
  usedeb=1
  deb 4, "before", x:xmm0, x:xmm7
  ppxInit
  PushX xmm0
  PushX xmm7
  PopX xmm0                     ; note the order: we
  PopX xmm7                     ; are swapping values
  deb 4, "popped & swapped", x:xmm0, x:xmm7
  ; PopX xmm0                           ; uncomment to see the error handling
  MsgBox 0, "Wow, it works!!!!", "Hi", MB_OK or MB_SETFOREGROUND
EndOfCode


Output:
This code was assembled with UAsm64 in 64-bit format
before
x:xmm0  3333333344444444h
x:xmm7  7777777788888888h
popped & swapped
x:xmm0  7777777788888888h
x:xmm7  3333333344444444h


Attached the macro and a standard MasmBasic example.
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 07, 2018, 01:02:13 AM
great macros :t
Title: Re: Where do you live?
Post by: HSE on May 07, 2018, 05:44:32 AM
Quote from: jj2007 on May 03, 2018, 09:39:29 AM

Output:GEO_LCID:       00000809
GEO_RFC1766:    en-it

I live in Italia (aka Repubblica italiana) at 42.768 North, 12.492 East

Are tou sure?

:biggrin:
GEO_LCID:       00000C0A
GEO_RFC1766:    es-es

I live in España (aka Reino de España) at 40.396 North, -3.551 East

Title: GeoInfo
Post by: jj2007 on May 07, 2018, 08:08:04 AM
Well, I do live in Italy, but I haven't check how exact the LatLong figures are. Any idea how the OS determines a user's position?
Title: Re: GeoInfo
Post by: HSE on May 07, 2018, 09:28:14 AM
Quote from: jj2007 on May 07, 2018, 08:08:04 AM
Any idea how the OS determines a user's position?

OS don't know user's position. I think it's just a point in country center. You declare country when setting language and location. In spanish language España it's default country. In italian language... let me think... mmh  ::)
Title: Re: GeoInfo
Post by: daydreamer on May 07, 2018, 02:47:29 PM
Quote from: jj2007 on May 07, 2018, 08:08:04 AM
Well, I do live in Italy, but I haven't check how exact the LatLong figures are. Any idea how the OS determines a user's position?
Same as timezone= the capital of your country?cant you check Rome in google maps and see if its same long and latitude?
Title: Re: GeoInfo
Post by: jj2007 on May 07, 2018, 05:08:02 PM
Quote from: daydreamer on May 07, 2018, 02:47:29 PMSame as timezone= the capital of your country?cant you check Rome in google maps and see if its same long and latitude?

Yes, you can: Enter the result as e.g. 42.768, 12.492 into Google Maps. It seems that the Geo$() function returns the middle of the country. In theory, you can fine-tune your location, but it's a per user setting in the Control Panel, be careful.
Title: Re: Miscellaneous snippets
Post by: LordAdef on May 09, 2018, 04:30:36 PM
QuoteGEO_LCID:       00000416
GEO_RFC1766:    pt-us

I live in Estados Unidos (aka Estados Unidos da América) at 39.450 North, -98.908 East

Hey, the little guy placed me in the US!
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 11, 2018, 04:17:15 AM
Curious if masm or masm basic also supports print in hexadecimal like c++  cout has?
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 11, 2018, 06:28:44 AM
Quote from: daydreamer on May 11, 2018, 04:17:15 AM
Curious if masm or masm basic also supports print in hexadecimal like c++  cout has?

Sure:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  mov ecx, 123456789
  Print Str$("Decimal:\t%i\n", ecx)
  mov esi, 12345678h
  PrintLine "Hexadecimal:", Tb$, Hex$(esi)
  movd xmm0, esi
  pshufd xmm0, xmm0, 0
  deb 4, "for debugging", ecx, x:esi, x:xmm0
  Inkey "-- hit any key --"
EndOfCode


Decimal:        123456789
Hexadecimal:    12345678

for debugging
ecx             123456789
x:esi           12345678
x:xmm0          12345678 12345678 12345678 12345678


The Masm32 SDK has the hex$() macro, e.g. as print hex$(esi), 13, 10
Title: Create a temp web page to save a link
Post by: jj2007 on May 14, 2018, 06:37:05 AM
Sometimes I need to save a webpage but don't want to open it. So I copy the URL and run this proggie (source+exe attached):

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=Clip$()               ; get URL from clipboard, e.g. http://masm32.com/board/index.php?action=unread
  .if Instr_(esi, "://")
        FileWrite "SaveLinkAsTemp.html", Cat$(Chr$("<html><head><title>Temporary link</title></head>", 13, 10, "<body>", 60, "a href=", 34)+esi+Chr$(34, 62, "Right-click here and choose 'Save Link as...' to download ")+esi+Chr$(60, "/a", 62, "</body></html>"))
        ShEx "SaveLinkAsTemp.html"      ; launch the browser
  .else
        MsgBox 0, esi, "No URL found:", MB_OK
  .endif
EndOfCode


Title: Check a file for http:// and friends
Post by: jj2007 on May 18, 2018, 11:59:07 AM
Attached a little file DownloadMasm32.exe that does something entirely harmless:
include \masm32\MasmBasic\MasmBasic.inc
  Init
  Let esi="0.75=draob?php.xedni/draob/moc.23msam//:ptth"
  PrintLine esi
  Let edi=FileRead$(Mirror$(esi))
  Inkey NoTag$(edi)
EndOfCode


In addition, the attachment contains a project that finds http:// and https:// in files, even if they are mirrored; just drag a file over SpyWareScanMB.exe 8)

Warning: While SpyWareScanMB.exe finds interesting http:// and https:// matches in exes and dlls, it is not a replacement for an AntiVirus. Malware writers use more sophisticated tricks to hide their URLs.
Title: Print formatted text
Post by: jj2007 on June 25, 2018, 03:55:17 AM
This snippet
- reads a text file into a RichEdit control (its name is supplied by the commandline)
- formats the first line in bold
- on request via the menu, prints the text.

To test it, extract all files to a temporary folder and drag the text file over the exe (the *.asc file is the source as RTF).

If needed, the whole process can be automated, i.e. eliminate the Event Menu step and just run the exe with the commandline argument, then exit automatically. See PrintRtf (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1384) for printer dialog handling options.


GuiMenu equ @File, &Open, &Print, E&xit
GuiParas equ "Print formatted text demo", x100, y100, w400, h200; , cblack, b00FFFFD0h
include \masm32\MasmBasic\Res\MbGui.asm

  MakeFont hMyFont, Height:20, "Lucida Handwriting"
  GuiControl MyEdit, "RichEdit", font hMyFont
  SetGlobals f$, charfmt:CHARFORMAT2
  Let f$=FileRead$(CL$())               ; read the text file passed in the commandline
  SetWin$ hMyEdit=f$
  .if Instr_(f$, CrLf$)
       dec edx                         ; index of CrLf-1
       invoke SendMessage, hMyEdit, EM_SETSEL, 0, edx
       m2m charfmt.cbSize, CHARFORMAT2
       m2m charfmt.dwMask, CFM_BOLD            ; CharFtMask
       m2m charfmt.dwEffects, CFE_BOLD         ; Character effects
       invoke SendMessage, hMyEdit, EM_SETCHARFORMAT, SCF_SELECTION, ADDR charfmt
       invoke SendMessage, hMyEdit, EM_SETSEL, 0, 0
  .endif

Event Menu
  .if MenuID==1
        void PrintRtf(hMyEdit, 1)     ; 0=use default printer, 1=ask for printer dialog
  .endif
GuiEnd
Title: Launcher
Post by: jj2007 on June 27, 2018, 02:54:41 PM
include \masm32\include\masm32rt.inc

.data
txFile db "extracted.exe", 0
bytesWritten dd ?

.code
start:
  invoke FindResource, 0, 99, RT_RCDATA
  .if eax
xchg eax, ebx ; hRes
push rv(SizeofResource, 0, ebx)
push rv(LoadResource, 0, ebx) ; returns pointer to content in eax
invoke CreateFile, addr txFile, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0
xchg eax, esi
pop eax ; pointer to content
pop ecx ; size in bytes
invoke WriteFile, esi, eax, ecx, addr bytesWritten, 0
invoke CloseHandle, esi
invoke WinExec, addr txFile, SW_SHOW
  .endif
  exit
end start
Title: Re: Miscellaneous snippets
Post by: HSE on June 27, 2018, 11:36:18 PM
 :t
Title: Check if a file is older than a specified date
Post by: jj2007 on July 07, 2018, 08:20:15 PM
Just encountered a case where I had to check if a file was older than dd.month.year, and needed a snippet to perform this check:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  .if Exist(CL$())
        sub esp, 2*FILETIME             ; create two structures on the stack
        movlps QWORD ptr [esp], TimeSF (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1328)("02.07.2018 11:16:50")   ; European format!
        lea ecx, [esp+QWORD]
        movlps QWORD ptr [ecx], GfLastWrite (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1067)(-1)         ; the lower QWORD returns the FILETIME
        invoke CompareFileTime, ecx, esp
        add esp, 2*FILETIME             ; correct the stack
        .if signed eax<0
                wMsgBox 0, wCL$(), "File is older. Process?", MB_YESNOCANCEL
                .if eax==IDYES
                                ; ... do stuff ...
               .endif
        .else
                wMsgBox 0, wCL$(), "File is younger:", MB_OK
        .endif
  .else
        wMsgBox 0, wCL$(), "No such file:", MB_OK
  .endif
EndOfCode
Title: Create a hundred folders
Post by: jj2007 on July 11, 2018, 09:26:40 PM
Create a hundred folders, write a testfile to each of them:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  For_ ecx=0 To 99
        Let esi=Str$("New Folder%i", ecx)
        MakeDir esi
        .Break .if !Zero?
        Print "+"
        Let esi=esi+"\test.txt"
        PrintLine Str$(ecx), Tb$, esi
        FileWrite esi, Str$("Test %i", ecx)
  Next
EndOfCode

Title: Numbers only
Post by: jj2007 on July 14, 2018, 05:10:28 AM
An edit control that allows to enter only valid decimal numbers. Bug feedback welcome :biggrin:

P.S.: PNG_LoadFile à la MasmBasic attached, using GuiImage (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1362). The *.asc source opens in WordPad, but here it is anyway for those who can't find WordPad or RichMasm (http://masm32.com/board/index.php?topic=5314.0):

include \masm32\MasmBasic\Res\MbGui.asm
Event Paint
GuiImage "car.png", fit
GuiEnd
Title: Re: Numbers only
Post by: zedd151 on July 19, 2018, 09:20:26 AM
Quote from: jj2007 on July 14, 2018, 05:10:28 AM
An edit control that allows to enter only valid decimal numbers. Bug feedback welcome :biggrin:


oops!    :greensml: 


You did say 'decimal' numbers, not integers, right?




Also for the png image 'fit' viewer, when resizing from either side or from the top, the image resizes reflecting the new dimensions of the window.
But when resizing the window from the bottom, it crops or cuts off the image.
Title: Re: Numbers only
Post by: jj2007 on July 19, 2018, 10:26:39 AM
Quote from: zedd151 on July 19, 2018, 09:20:26 AMYou did say 'decimal' numbers, not integers, right?

Thanks for the feedback. Try 1234567890.123456784 vs 1234567890.123456785 - this is REAL10 precision, and it has its limits, i.e. around 18 digits.

        MovVal ST(0), Win$(@hWnd)
        SetWin$ hMyResult=Str$("Result=%Jf", ST(0)v)

If you replace the "J" with an "I", it displays one digit less, and all numbers will be correct.

Quotewhen resizing the window from the bottom, it crops or cuts off the image.

Interesting. It works correctly on this Win7-64 machine. Just made a test with my WinXP VM, and you are right: When resizing from left or top, it works (but with tremendous flicker - on Win7, it's smooth); when resizing from right or bottom, it crops. Hmmm :(
Title: Re: Miscellaneous snippets
Post by: zedd151 on July 19, 2018, 10:34:20 AM
Windows XP Pro SP3  in VirtualBox <-- may have something to do with it?


The screen capture shows the top image resized from lower right upward


The bottom shows resized from top left downward.


Windows 7 32 bit works as advertised.


With the newer hardware that is out these days, it's a shame to have to run xp in a virtual machine.
Title: Re: Miscellaneous snippets
Post by: jj2007 on July 19, 2018, 10:52:06 AM
Quote from: zedd151 on July 19, 2018, 10:34:20 AM
Windows XP Pro SP3  in VirtualBox <-- may have something to do with it?

I doubt it, VM and real machine will probably behave the same. Googling for "wm_sizing" "xp" yields lots of results, it could be a known problem.
Title: Re: Miscellaneous snippets
Post by: zedd151 on July 19, 2018, 11:01:25 AM
Quote from: jj2007 on July 19, 2018, 10:52:06 AM


Googling for "wm_sizing" "xp" yields lots of results, it could be a known problem.


Only way to know for sure is to get someone that has XP installed natively on their system to test the program.

Title: Re: Miscellaneous snippets
Post by: FORTRANS on July 20, 2018, 01:12:44 AM
Hi,

   Tested the ShowPng on Windows XP.  Seems to crop on resizing.
maximize and restore causes the image to fit the window.  Is
that what was wanted?

Regards,

Steve
Title: Re: Miscellaneous snippets
Post by: jj2007 on July 20, 2018, 04:06:05 AM
Quote from: FORTRANS on July 20, 2018, 01:12:44 AMon Windows XP.  Seems to crop on resizing.... Is that what was wanted?

Steve,
No, not really, see reply #53+#54. It's limited to XP, though. Apparently one message is not being sent correctly in XP.
Title: Re: Miscellaneous snippets
Post by: FORTRANS on July 20, 2018, 04:42:33 AM
Hi Jochen,

   Okay, how about:

Upper left  Resize
Top         Resize
Upper right Resize
Right       Crop
Lower right Crop
Bottom      Crop
Lower left  Resize
Left        Resize
Cropped to maximize, Resize
Maximum to restore, Resize


   More useful I hope?  Or am I still missing things as usual?

Regards,

Steve N.
Title: Re: Miscellaneous snippets
Post by: jj2007 on July 20, 2018, 04:53:05 AM
Your analysis is absolutely correct: XP behaves like that. Those resizing attempts that actually move the window trigger the resizing of the image. All others don't. But I would have to dig deep into the code to find a workaround, and I am not sure if XP is important enough to justify that effort :icon_mrgreen:
Title: Len, wLen, uLen
Post by: jj2007 on July 20, 2018, 12:17:04 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi="Нажмите на эту кнопку"              ; "Click on this button" in Russian
  Print Str$("Len(esi)=\t%i\n", Len(esi))      ; treated as Ansi
  Print Str$("uLen(esi)=\t%i\n", uLen(esi))    ; treated as Utf8
  Print Str$("wLen(esi)=\t%i\n", wLen(wRec$(esi)))     ; treated as Unicode (wRec$ (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1381): convert Utf8 to wide string)
  Print
  Let esi="在這裡輸入文字"                       ; "Enter text here" in Chinese
  Print Str$("Len(esi)=\t%i\n", Len(esi))      ; treated as Ansi
  Print Str$("uLen(esi)=\t%i\n", uLen(esi))    ; treated as Utf8
  Print Str$("wLen(esi)=\t%i\n", wLen(wRec$(esi)))     ; treated as Unicode
EndOfCode


Len(esi)=       39
uLen(esi)=      21
wLen(esi)=      21

Len(esi)=       21
uLen(esi)=      7
wLen(esi)=      7


Note that the uLen macro does not check whether the string is valid Utf8 (credits to PaulSquires (https://www.freebasic.net/forum/viewtopic.php?f=6&t=26888&sid=a194cedab48d078a6e22d2eca6cae2f7#p249682)). Example:

  Let esi="Click on this button"+Chr$(169)      ; Ansi with one extra character
  .if rv(MultiByteToWideChar, CP_UTF8, MB_ERR_INVALID_CHARS, esi, Len(esi), NULL, 0) == 0
        PrintLine "[", esi, "] is not a valid Utf8 string"
  .else
        Print "[", esi, "]", Str$("has %i bytes and is a valid Utf8 string\n", eax)
  .endif


[Click on this button©] is not a valid Utf8 string
Len(esi)=       21
uLen(esi)=      21
wLen(esi)=      21


Full project attached.
Title: Re: Miscellaneous snippets
Post by: Antariy on July 21, 2018, 06:53:12 AM
Hi Jochen

You wondered why strlen for UTF8 should be different proc than regular (single-byte encodings like ASCII/ANSI/ISO/etc) strlen.
Now probably you can review that thread just for fun :biggrin:

http://masm32.com/board/index.php?topic=2369.msg24543#msg24543
Title: Utf8 macros
Post by: jj2007 on July 21, 2018, 07:12:05 AM
Welcome back, my friend! Yes, that thread was interesting - almost 5 years ago. Time flies. In the meantime, I had forgotten that exchange of views, but MasmBasic does have some dedicated macros, like uLen, uLeft$ and uMid$...
Title: Re: Miscellaneous snippets
Post by: Antariy on July 21, 2018, 07:21:32 AM
Quote from: jj2007 on July 21, 2018, 07:12:05 AM
Welcome back, my friend! Yes, that thread was interesting - almost 5 years ago. Time flies. In the meantime, I had forgotten that exchange of views, but MasmBasic does have some dedicated macros, like uLen, uLeft$ and uMid$...

Yes, that was purpose of that thread and algo research (making utf8 chars walking faster if possible)... strlen is the simplest usage of that implementation, but more important are string-manipulation functions like basic-like ones you mentioned :biggreen: It is harder to Mid$ something from the random dataflow of utf8 string than from other - fixed-width (length/size) - encodings like ASCII/ANSI/UTF16/32/etc are.
Title: Re: Miscellaneous snippets
Post by: Antariy on July 21, 2018, 07:25:44 AM
So, you implemented those in your MB project, very cool and nice :T :t
Title: Re: Miscellaneous snippets
Post by: jj2007 on July 21, 2018, 07:52:21 AM
I rolled my own, actually. Your code is too complex for my old brain. But we could organise a speed test ;-)
uLen MACRO arg
  push esi
  push edx
  ifdifi <esi>, <arg>
mov esi, repargA(arg)
  endif
  xor edx, edx
  .While 1
lodsb
.Break .if !al
inc edx
.if al>=10000000b ; 128
inc esi
.if al>=11100000b
inc esi
.if al>=11110000b
inc esi
.if al>=11111000b
    inc esi
.endif
.endif
.endif
.endif
  .Endw
  xchg eax, edx
  pop edx
  pop esi
  EXITM <eax>
ENDM
Title: MRU: Most Recently Used
Post by: jj2007 on July 25, 2018, 09:30:58 AM
Attached a little demo project; I'd like to get some feedback on the behaviour of the MRU menu. The archive has source code (*.asc), but it won't build with the current MasmBasic version.

I am testing three macros:
- SetMru "somefile.ini": reads recently used files from disk and adds them to the menu
- AddMru SomeFile$: adds opened or saved filename to the menu
- MenuText$(): returns the full file path in response to a menu event

Finally,

Event Close
  StoreUtf8 Cat$(MbExeFolder$+"\EditorDemo.ini"), Mru$(), 8     ; write up to 8 strings to file


... serves to store the MRU list to disk. Note that only a few functions of the toolbar are actually implemented - use at your own risk, test it with non-important files 8)

This is work in progress, grateful for feedback, especially also from people using non-Latin alphabets.
Title: Input$
Post by: jj2007 on July 31, 2018, 10:11:23 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals MyString
  Init
  PrintLine "You can hit keys as you like, but when the countdown approaches zero, you should stop"
  For_ ecx=1000 To 0 Step -1
        Print At(0, 3) Str$(ecx), "   "
        Delay 2
  Next
  Let MyString=Input$ (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1041)("Your hobby: ", "Basic programming (this string is editable)", flush)
  MsgBox 0, MyString, "The string:", MB_OK or MB_SETFOREGROUND
EndOfCode
Title: Creating and erasing a numerical array
Post by: jj2007 on August 02, 2018, 06:32:53 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  N=500000000                           ; 500 Mio
  PrintCpu 0
  For_ outerloop=0 To 5

        NanoTimer()
        Dim MyBytes(N) As BYTE
        PrintLine "allocating took ", NanoTimer$()
       
        NanoTimer()
        For_ ecx=0 To N-1
                mov MyBytes(ecx), cl
        Next
        PrintLine "filling took ", NanoTimer$()
       
        NanoTimer()
        % Erase MyBytes()
        PrintLine "erasing took ", NanoTimer$(), CrLf$
  Next
  Inkey
EndOfCode


Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
allocating took 13 µs
filling took 1228 ms
erasing took 40 ms

allocating took 24 µs
filling took 1229 ms
erasing took 40 ms

allocating took 22 µs
filling took 1228 ms
erasing took 38 ms

allocating took 23 µs
filling took 1227 ms
erasing took 37 ms

allocating took 23 µs
filling took 1229 ms
erasing took 38 ms

allocating took 18 µs
filling took 1232 ms
erasing took 40 ms


Writing the bytes to file costs an extra 7-9 seconds:

        NanoTimer()
        Open "O", #1, "MyBytes.dat"
        Store #1, MyBytes()
        Close
        PrintLine "writing took ", NanoTimer$()
Title: Converting a *.csv file to a fixed size file
Post by: jj2007 on August 12, 2018, 10:26:55 AM
Usage: Drag a csv file over the attached exe. The required fixed size is calculated automatically, see results below.

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals f$, records, maxcol, record$, endreached   ; see FB thread: CSV to fixlength data files (https://www.freebasic.net/forum/viewtopic.php?f=3&t=26946&p=250502&sid=bedd271c83f18dff8305ce58a49aa5fb#p250499)
  Init
  NanoTimer()
  Dim MxLen() As DWORD          ; OxPT_Arg1 J:\Masm32\MasmBasic\BugTests\TableControl\FatTable.csv
  Dim fix$()
  Let f$=CL$()
  .if !Exist(f$)
        GetFiles *.csv
        SortFiles
        Let f$=Files$(0)
  .endif
  Recall f$, L$(), csv
  mov records, eax
  For_ ct=0 To eax-1
        For_ ecx=0 To 99
                xchg Len(L$(ct, ecx)), eax
                .if eax>MxLen(ecx)
                                mov MxLen(ecx), eax
                                Print "*"
                .endif
       Next
  Next
  Print CrLf$, "Length of records: "
  For_ ecx=0 To 127
        mov eax, MxLen(ecx)
        .Break .if !eax
        add esi, eax
        Print Str$(eax), " "    ; record length
  Next
  mov maxcol, ecx
  lea esi, [esi+ecx+1]
  Print Str$("\nLen of full record=%i", esi), Str$(", %i columns", maxcol)
  Let edi=Space$(esi)
ComposeString MACRO maxcol
  mov ecx, maxcol
  Clr endreached
  .Repeat
        lodsb
        .if !al
                inc endreached
        .endif
        .if endreached || !al || !ecx
                mov al, 32
        .endif
        stosb
        dec ecx
  .Until Sign?
ENDM
  For_ ct=0 To records-1
        push edi
        mov esi, L$(ct, 0)
        ComposeString MxLen(0)
        For_ col=1 To maxcol-1
                mov esi, L$(ct, col)
                ComposeString MxLen(col)
       Next
        xor eax, eax
        stosb
        pop edi
        Let fix$(ct)=edi
  Next
  .if Instr_(f$, ".csv", 1)
        mov [eax], Mirror$(".fix")
        PrintLine CrLf$, "Storing to ", f$
        Store f$, fix$()
  .endif
  Inkey "Converting ", f$, " took ", NanoTimer$()
EndOfCode


For a 19MB csv database, the whole process takes about 2 seconds, but the resulting file gets bloated to >100MB:Length of records: 11 646 348 13 141 82 20 4 10 20 4 10 28 4 10 20 4 10 25 4 10 25 4 11 25 4 11 25 4 11 25 4 11 25 4 11 25 4 10 27 4 11 26 4
11 28 4 11 27 4 11 23 4 11 23 4 15 23 4 15 23 4 15 23 4 15 25 4 15 23 4 15 23 4 11 22 4 10 12 4 6 9 4 4 9 4 4 9 4 4 9 4
Len of full record=2376, 92 columns
Storing to C:\Masm32\MasmBasic\BugTests\TableControl\FatTable.fix
Converting C:\Masm32\MasmBasic\BugTests\TableControl\FatTable.fix took 2367 ms
Title: Subclassing a RichEdit control (dual 64-/32-bit code)
Post by: jj2007 on August 12, 2018, 10:16:52 PM
Numbers only in a RichEdit control (full project attached):
SubEdit proc <cb> uses rbx hWnd, uMsg, wParam, lParam ; <cb> indicates that it is a callback function
  mov ebx, wParam ; default: process wParam
  cmp uMsg, WM_CHAR
  jne @F
  cmp wParam, "9"
  jle @F
  Print Str$("char %i not allowed\n", ebx)
  xor ebx, ebx ; don't process
@@: jinvoke CallWindowProc, PreviousWndProc, hWnd, uMsg, ebx, lParam
  ret
SubEdit endp
Title: The console isn't completely dead yet
Post by: jj2007 on August 14, 2018, 09:31:20 AM
(http://www.webalice.it/jj2006/pics/DosSymbols.png)

Full project attached (the exe includes the fake database). Use cursor up/down to scroll among the records, hit Escape to quit.

Here is the source (50 lines of code):

include \masm32\MasmBasic\MasmBasic.inc         ; symbols (https://altcodeunicode.com/windows-alt-codes-symbols/)
include NewAtMacro.inc
  SetGlobals TopRecord
  Init
  invoke ShowWindow, rv(GetConsoleWindow), SW_MAXIMIZE
  StringToArray 100, d$(), tab
  ConsoleColor cDarkGray, cBlack
  Print 0                               ; override codepage setting
  $Data 11C #, 91C LastName, O1C FirstName, Z1C Street, s1C City, 6+1A ProdCode, A+1A UnitPrice
  Read Header$()       ; create a string array
  invoke SetConsoleOutputCP, 437        ; we need that codepage for the graphic characters
  Print ConvertCp$(ResFile$(101), CP_UTF16, 437)        ; resource 101 (boxes.txt) is Unicode and needs to be converted
  invoke SetConsoleOutputCP, 1252      ; Windows default
  For_ ecx=0 To Header$(?)-1
        xchg Header$(ecx), esi
        Print At(#esi) esi      ; the new At() macro has some goodies... it can set xy and colours based on the start of the string
  Next
  Print At(0, 20) "Use cursor up/down to scroll, Escape to quit"                ; override codepage setting
  .While 1
        m2m ecx, 3              ; start displaying data in row 3
        For_ ct=TopRecord To TopRecord+6
                mov esi, Cat$(Chr$("1", ecx+48, "F ")+Str$("%______i", ct))     ; right-aligned record number
                Print At(#esi) Left$(esi, 19)
                mov esi, Cat$(Chr$("9", ecx+48, "F ")+d$(ct, 0)+String$(20, " "))
                Print At(#esi) Left$(esi, 19)
                mov esi, Cat$(Chr$("O", ecx+48, "F ")+d$(ct, 1)+String$(10, " "))
                Print At(#esi) Left$(esi, 10)
                mov esi, Cat$(Chr$("Z", ecx+48, "E ")+d$(ct, 2)+String$(20, " "))
                Print At(#esi) Left$(esi, 18)
                mov esi, Cat$(Chr$("s", ecx+48, "E ")+d$(ct, 3)+String$(10, " "))
                Print At(#esi) Left$(esi, 10)
                mov esi, Cat$(Chr$("6+", ecx+48, "F9 ")+d$(ct, 4)+String$(10, " "))
                Print At(#esi) Left$(esi, 10)
                mov esi, Cat$(Chr$("A+", ecx+48, "C ")+d$(ct, 5)+String$(9, " "))
                Print At(#esi) Left$(esi, 9)
                add ecx, 2      ; next data two rows down
       Next
        Inkey
        .Break .if eax==VK_ESCAPE
        mov edx, TopRecord
        .if eax==VK_UP
                dec edx
        .elseif eax==VK_DOWN
                inc edx
        .endif
        mov TopRecord, Max(0, edx)
        sub d$(?), 7                   
        mov TopRecord, Min(eax, TopRecord)
  .Endw
EndOfCode
Title: The console isn't completely dead yet (part II)
Post by: jj2007 on August 15, 2018, 05:44:43 PM
How does it work?

mov esi, Cat$(Chr$("z", ecx+48, "EC ")+d$(ct, 3))  ; City: Column z (=10+26+26), row ecx, foregroundcolour E (yellow), bg C (red)
Print At(#esi) Left$(esi, 13, "_")     ; for short strings, fill right half with "_"


esi points to a string with a specific format:
ABCD this is a string

A is the print column, where
0   0
9   9
A   10+0=10
Z   10+25=35
a   10+26+0=36
z   10+26+25=61

B is the print row, using the same scheme.
C and B are the foreground and background colours, with
cBlack = 0 ; http://support.microsoft.com/kb/319883
cDarkBlue = 1
cDarkGreen = 2
cDarkCyan = 3
cDarkRed = 4
cDarkMagenta = 5
cDarkYellow = 6
cGray = 7
cDarkGray = 8
cBlue = 9
cGreen = 10 ; A
cCyan = 11 ; B
cRed = 12 ; C
cMagenta = 13 ; D
cYellow = 14 ; E
cWhite = 15 ; F


The attachment contains sources and files to build this; including a new Left$() macro:

Print Left$("some string", 20, "_")  ; prints some string_________

The third optional argument is a fill char for padding the string to the right in case it's shorter than 20 chars. Can be quite useful in some situations, inter alia for overwriting the previous field when filling the screen as shown above. In the attached exe, the Street column does not have padding, and when scrolling through the database you can see the effect.
Title: Re: Miscellaneous snippets
Post by: HSE on August 15, 2018, 10:14:30 PM
Not exactly perfect here:
Title: Re: Miscellaneous snippets
Post by: jj2007 on August 16, 2018, 01:15:44 AM
Interesting ::)

Which OS version? Console is maximised, I suppose?

Just checked with Win XP, and that looks indeed like what you posted. Unlike Win7 & Win10, the console isn't enlarged enough by the invoke ShowWindow, rv(GetConsoleWindow), SW_MAXIMIZE. You have to enlarge it manually in the console properties, then save "for all future windows with the same name", and restart. Then it works.

On Win7, the display refreshes immediately, i.e. in milliseconds. With Win10, it seemed initially very slow, but now it has become fast. I have yet to find out if there is a pattern - mysteries of Windows 8)
Title: Re: Miscellaneous snippets
Post by: HSE on August 19, 2018, 10:59:37 AM
In 7-32 I changed console properties and that look a lot better. Some characters are not intended ones, I think.
Title: Re: Miscellaneous snippets
Post by: jj2007 on August 19, 2018, 11:38:56 AM
Weird, codepage 437 should be pretty standard. Which language is your OS?
Title: Re: Miscellaneous snippets
Post by: HSE on August 20, 2018, 01:43:37 AM
Spanish. Selected: Español(España)

UASM v2.46, Jan  8 2018, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.

*** MasmBasic version 25.12.2017 ***
** SetProcessUserModeExceptionPolicy
** read Header$()
DosSymbols.asm(69) : Error A2228: Missing right parenthesis in expression
MbFor(218)[MasmBasic.inc]: Macro called from
  DosSymbols.asm(69): Main line code
DosSymbols.asm(69) : Error A2228: Missing right parenthesis in expression
MbFor(243)[MasmBasic.inc]: Macro called from
  DosSymbols.asm(69): Main line code
DosSymbols.asm(69) : Error A2210: Syntax error: ]
MbFor(256)[MasmBasic.inc]: Macro called from
  DosSymbols.asm(69): Main line code
DosSymbols.asm: 100 lines, 1 passes, 199 ms, 0 warnings, 3 errors


There is a problem moving up and down because Quantity doesn't stop when reach limits.
Title: Re: Miscellaneous snippets
Post by: jj2007 on August 20, 2018, 05:13:40 AM
Quote from: HSE on August 20, 2018, 01:43:37 AM
Spanish. Selected: Español(España)
...
There is a problem moving up and down because Quantity doesn't stop when reach limits.

Weird. Sorry for the build errors, it seems the current MasmBasic version is not compatible with my newest one.
Re Quantity, that's by design: It is set by Rand() and does its job even if the position does not change. Just for testing...
Title: The console isn't completely dead yet (part III)
Post by: jj2007 on August 22, 2018, 07:39:08 AM
Quote from: HSE on August 19, 2018, 10:59:37 AM
In 7-32 I changed console properties and that look a lot better. Some characters are not intended ones, I think.

Can you check the attached version, please? I replaced codepage 437 with another one.
Title: Re: Miscellaneous snippets
Post by: HSE on August 24, 2018, 11:43:26 PM
Worst !

Still not posible to assemble  :eusa_naughty:

Except first character, I see perfectly boxes.txt with MASM32 Unicode Editor .
Title: Re: Miscellaneous snippets
Post by: jj2007 on August 25, 2018, 12:06:20 AM
Yes, it won't build, sorry. I am working on a major MasmBasic update, and that will take some time.

Still, the exe should work OK. It's now codepage UTF8, and your machine should understand that. Anybody else having such problems?
Title: Re: Miscellaneous snippets
Post by: HSE on August 25, 2018, 01:43:33 AM
Ja!

Default font configuration here is "Fuentes de mapas de bits".

Changing that to "Lucida Console" work perfect, also previous version  :t

With third option Nidud's "Doszip Console" letters dont' look so well.
Title: Re: Miscellaneous snippets
Post by: jj2007 on August 25, 2018, 01:49:39 AM
Thanks :biggrin:
One day I will find a way to set the console font programmatically ;)
Title: Dll problems
Post by: jj2007 on August 25, 2018, 05:08:26 AM
Attached an archive with
- an exe compiled with FreeBasic
- that needs the second file, a DLL using Input$("prompt", "prefilled for editing") (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1041)
Title: Pcg32
Post by: jj2007 on September 11, 2018, 04:12:10 AM
All three are brilliant with the FourmiLab ENT (http://www.fourmilab.ch/random/) test, but only the first two have been tested with PractRand. If you need a very good hi-speed PRNG, stick with MasmBasic Rand() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1030).
Testing 32000000 numbers generated, CPU: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz

833 ms for Pcg32  FB, last result: 817EEE81
390 ms for Pcg32 Asm, last result: 817EEE81
107 ms for MB Rand(), last result: 8E1531E8

771 ms for Pcg32  FB, last result: 15670CA0
378 ms for Pcg32 Asm, last result: 15670CA0
107 ms for MB Rand(), last result: C44145CE

764 ms for Pcg32  FB, last result: D422CFAD
398 ms for Pcg32 Asm, last result: D422CFAD
118 ms for MB Rand(), last result: 2C03A5D1

840 ms for Pcg32  FB, last result: ECD79C2B
377 ms for Pcg32 Asm, last result: ECD79C2B
107 ms for MB Rand(), last result: BFFA6298

766 ms for Pcg32  FB, last result: 5248B397
377 ms for Pcg32 Asm, last result: 5248B397
107 ms for MB Rand(), last result: 675D19A4

766 ms for Pcg32  FB, last result: 54A9248A
382 ms for Pcg32 Asm, last result: 54A9248A
110 ms for MB Rand(), last result: E59BD461
202     bytes for Pcg32
111     bytes for Pcg
26      bytes for MbRand


ENT results:
Testing 8000000 numbers generated, CPU: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz

############ ENT results Pcg32 (FB):
Entropy = 7.999994 bits per byte.

Optimum compression would reduce the size
of this 32000000 byte file by 0 percent.

Chi square distribution for 32000000 samples is 274.62, and randomly
would exceed this value 25.00 percent of the times.

Arithmetic mean value of data bytes is 127.4936 (127.5 = random).
Monte Carlo value for Pi is 3.141756196 (error 0.01 percent).
Serial correlation coefficient is 0.000371 (totally uncorrelated = 0.0).

############ ENT results Pcg32 (MB):
Entropy = 7.999994 bits per byte.

Optimum compression would reduce the size
of this 32000000 byte file by 0 percent.

Chi square distribution for 32000000 samples is 274.62, and randomly
would exceed this value 25.00 percent of the times.

Arithmetic mean value of data bytes is 127.4936 (127.5 = random).
Monte Carlo value for Pi is 3.141756196 (error 0.01 percent).
Serial correlation coefficient is 0.000371 (totally uncorrelated = 0.0).

############ ENT results MB Rand(-1):
Entropy = 7.999995 bits per byte.

Optimum compression would reduce the size
of this 32000000 byte file by 0 percent.

Chi square distribution for 32000000 samples is 213.24, and randomly
would exceed this value 95.00 percent of the times.

Arithmetic mean value of data bytes is 127.4976 (127.5 = random).
Monte Carlo value for Pi is 3.141366946 (error 0.01 percent).
Serial correlation coefficient is -0.002006 (totally uncorrelated = 0.0).
Title: Pcg32, spreadsheet control, GCC version info
Post by: jj2007 on September 14, 2018, 07:23:41 PM
* PCG32.zip: Comparing SIMD vs FPU-based methods for mapping a QWORD (0...-1) to a double (0.0 ... 1.0)

* GuiTableControl.zip: latest tests with a spreadsheet control

* GetGccVersion.zip: echo a short version string to your FB output window. Source:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let edi=MbExeFolder$+"Win32\gcc.exe --version"
  Let esi=Launch$(edi)
  .if dword ptr [esi]==Mirror$("La$?")
        PrintLine edi, Chr$(": no answer.", 13, 10, 10, "Check if GetGccVersion.exe sits above the bin\Win32 folder")
  .else
        PrintLine esi
        Let ebx=Extract$(esi, "project)", 0)
        Let ecx=Extract$(esi, "(C)", "Free Soft")
        PrintLine "gcc version", ebx, " (", Trim$(ecx), ")"
  .endif
EndOfCode


Sample output of gcc.exe --version:
gcc.exe (i686-win32-sjlj-rev2, Built by MinGW-W64 project) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Sample output of the attached batch file:
** compiling somefile.bas with -t 2000 -gen gcc -Wc -Ofast -s console **
gcc version 8.1.0 (2018)
Title: Re: Miscellaneous snippets
Post by: hutch-- on September 14, 2018, 08:19:31 PM
This is what I got running it the second time. Could not read the fonts as they were so small, copied it into my text editor first.

-8910786331291756801  0.5169453050529669    0.5169453050529669718
6730337785313497944   0.3648523424199086    0.3648523424199086505
-5974524377861002328  0.6761203844977746    0.6761203844977747243
2695508904680093984   0.1461238305204089    0.1461238305204090194
8502576381364090992   0.4609255892199442    0.4609255892199443155
-385216515766393995   0.9791173708364389    0.9791173708364389530
3034485871582637989   0.1644998087173231    0.1644998087173232765
2286379689918253082   0.1239448913468051    0.1239448913468051986
-4131041815082152639  0.7760557744729732    0.7760557744729734316
-853861575098310801   0.9537120712638256    0.9537120712638258368
7275931949313747423   0.3944290613151327    0.3944290613151328044
7844949285505684199   0.4252755529191934    0.4252755529191934295
140239247804428540    0.007602384856864708  0.007602384856864721546

timings for 100 Mio loops:
280 ms for SIMD
414 ms for FPU

197 ms for SIMD
409 ms for FPU

212 ms for SIMD
431 ms for FPU

223 ms for SIMD
378 ms for FPU

201 ms for SIMD
363 ms for FPU
Title: Search and dump
Post by: jj2007 on November 01, 2018, 10:04:36 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=FileRead$(CL$())
  Let edi="SendMessage"         ; just a proposal
  .While 1
        PrintLine "Hit Escape, Return to exit", Space$(40)
        Let edi=Input$("Search for ", edi)
        .Break .if !Len(edi)
        xor ebx, ebx
        NextMatch:
        inc ebx
        .if !Instr_(ebx, esi, edi, 1)
                PrintLine "No match for [", edi, "]                 "
        .else
                mov ebx, edx
                xchg eax, ecx
                sub ecx, 4*16
                ConsoleColor cBlue
                Print HexDump$(ecx, 64)
                ConsoleColor cWhite
                add ecx, 4*16
                .Repeat
                                PrintLine HexDump$(ecx)
                                add ecx, 512
                                Inkey "more? (Return: continue, F3: next match)", Cr$
                                cmp eax, VK_F3
                                je NextMatch
                .Until eax!=13
                ConsoleColor
        .endif
  .Endw
EndOfCode


Output:
Hit Escape, Return to exit
Search for SendMessage
002A899C  6E 65 64 09 65 71 75 20 73 64 77 6F 72 64 20 70 ned.equ sdword p
002A89AC  74 72 20 0D 0A 73 74 61 63 6B 09 65 71 75 20 3C tr ..stack.equ <
002A89BC  44 57 6F 72 64 20 50 74 72 20 5B 65 73 70 5D 3E DWord Ptr [esp]>
002A89CC  0D 0A 73 6D 09 65 71 75 20 69 6E 76 6F 6B 65 20 ..sm.equ invoke
002A89DC  53 65 6E 64 4D 65 73 73 61 67 65 2C 20 0D 0A 4C SendMessage, ..L
002A89EC  61 73 74 46 69 6C 65 4E 61 6D 65 24 09 65 71 75 astFileName$.equ
002A89FC  20 6F 66 66 73 65 74 20 77 66 64 2E 63 46 69 6C  offset wfd.cFil
002A8A0C  65 4E 61 6D 65 0D 0A 4C 61 73 74 46 69 6C 65 53 eName..LastFileS
002A8A1C  69 7A 65 09 65 71 75 20 77 66 64 2E 6E 46 69 6C ize.equ wfd.nFil
002A8A2C  65 53 69 7A 65 4C 6F 77 0D 0A 77 43 72 4C 66 24 eSizeLow..wCrLf$
002A8A3C  09 65 71 75 20 6F 66 66 73 65 74 20 77 43 72 4C .equ offset wCrL
002A8A4C  66 5F 74 78 74 0D 0A 77 4C 66 24 09 65 71 75 20 f_txt..wLf$.equ
002A8A5C  6F 66 66 73 65 74 20 77 4C 66 5F 74 78 74 0D 0A offset wLf_txt..
002A8A6C  77 54 62 24 09 65 71 75 20 6F 66 66 73 65 74 20 wTb$.equ offset
002A8A7C  77 54 61 62 5F 74 78 74 0D 0A 43 72 4C 66 09 65 wTab_txt..CrLf.e
002A8A8C  71 75 20 31 33 2C 31 30 0D 0A 0D 0A 4D 62 45 76 qu 13,10....MbEv
002A8A9C  43 74 3D 30 0D 0A 45 6E 64 4F 66 43 6F 64 65 20 Ct=0..EndOfCode
002A8AAC  4D 41 43 52 4F 20 61 72 67 64 0D 0A 20 20 69 66 MACRO argd..  if
002A8ABC  65 20 4D 62 45 78 69 74 0D 0A 09 45 78 69 74 20 e MbExit...Exit
002A8ACC  61 72 67 64 0D 0A 20 20 65 6E 64 69 66 0D 0A 20 argd..  endif..
002A8ADC  20 69 66 20 54 63 6C 43 74 43 20 67 74 20 31 0D  if TclCtC gt 1.
002A8AEC  0A 09 54 72 79 43 61 74 63 68 45 6E 64 0D 0A 20 ..TryCatchEnd..
002A8AFC  20 65 6E 64 69 66 0D 0A 20 20 69 66 20 4D 62 45  endif..  if MbE
002A8B0C  76 43 74 0D 0A 09 47 75 69 45 6E 64 20 30 0D 0A vCt...GuiEnd 0..
002A8B1C  20 20 65 6E 64 69 66 0D 0A 20 20 69 66 20 4D 62   endif..  if Mb
002A8B2C  4E 61 54 69 43 74 20 61 6E 64 20 31 0D 0A 09 65 NaTiCt and 1...e
002A8B3C  63 68 6F 0D 0A 09 65 63 68 6F 20 23 23 23 20 63 cho...echo ### c
002A8B4C  68 65 63 6B 20 79 6F 75 72 20 4E 61 6E 6F 54 69 heck your NanoTi
002A8B5C  6D 65 72 20 63 61 6C 6C 73 20 23 23 23 0D 0A 20 mer calls ###..
002A8B6C  20 65 6E 64 69 66 0D 0A 20 20 65 6E 64 20 73 74  endif..  end st
002A8B7C  61 72 74 0D 0A 45 4E 44 4D 0D 0A 43 6C 65 61 72 art..ENDM..Clear
002A8B8C  4C 61 73 74 45 72 72 6F 72 20 4D 41 43 52 4F 0D LastError MACRO.
002A8B9C  0A 20 20 69 66 20 75 73 65 64 65 62 0D 0A 09 70 .  if usedeb...p
002A8BAC  75 73 68 61 64 0D 0A 09 69 6E 76 6F 6B 65 20 53 ushad...invoke S
002A8BBC  65 74 4C 61 73 74 45 72 72 6F 72 2C 20 30 0D 0A etLastError, 0..
002A8BCC  09 70 6F 70 61 64 0D 0A 20 20 65 6E 64 69 66 0D .popad..  endif.

more? (Return: continue, F3: next match)
Title: Re: Miscellaneous snippets
Post by: jj2007 on November 03, 2018, 04:43:25 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals left, right, row   ; geeks for geeks: Print string of odd length in 'X' format (https://www.geeksforgeeks.org/print-string-of-odd-length-in-x-format/)
  Init
  Let edi="Assembly is a great language"
  .While 1
        Let edi=Input$("\n\n\n\nGimme a string please: ", edi)
        .Break .if !Len(edi)
        Clr left, row
        mov right, eax
        Cls
        .Repeat
                mov edx, left
                movzx eax, byte ptr [edi+edx]
                Print At(left, row) Chr$(eax)
                inc left
                dec right
                mov edx, right
                movzx eax, byte ptr [edi+edx]
                Print At(right, row) Chr$(eax)
                inc row
        .Until right<=0
  .Endw
EndOfCode


A                          e
s                        g
  s                      a
   e                    u
    m                  g
     b                n
      l              a
       y            l

         i        t
          s      a
                e
            a  r
              g
              g
            a  r
                e
          s      a
         i        t

       y            l
      l              a
     b                n
    m                  g
   e                    u
  s                      a
s                        g
A                          e
Title: Re: Miscellaneous snippets
Post by: TimoVJL on November 03, 2018, 08:01:55 AM
So you spotted G-point with MasmBasic 8)
Title: Changing the file date and time based on the filename
Post by: jj2007 on November 07, 2018, 10:11:00 PM
I've got a video converter (DVDVideoSoft) that works fine but it has the bad habit to set the time stamp of the output file to "right now". Fortunately, it creates new file names that contain the original date and time, e.g. C:\Users\Jochen\Videos\VID_20170621_153022.mp4 meaning original file was created 21 June 2017, 15:30:22

Here is a little program that touches the file and sets the time stamp back (source & exe attached, use at your own risk). Just drag any file from the folder over the exe:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals gfMatch$, pathLeft
  Init
  Let gfMatch$=CL$()
  mov pathLeft, Rinstr(eax, "\")
  .Repeat
        inc eax
  .Until byte ptr [eax]<="."
  xchg eax, ecx
  Let gfMatch$=Left$(gfMatch$, pathLeft)+"*"+ecx
  PrintLine gfMatch$
  GetFiles gfMatch$
  deb 4, "matches", eax
  SortFiles                             ; optional: latest files first
  For_ ecx=0 To eax-1
        mov esi, Files$(ecx)
        .if InstrOr(esi, ".mp4" or ".avi" or ".gp", 1)
                PrintLine GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Files$(ecx)
                .if Instr_(esi, "201")  ; 20160602_170844
                                xchg eax, esi
                                .if byte ptr [esi+8]=="_"
                                        Let edi=Mid$(esi, 7, 2)+"."+Mid$(esi, 5, 2)+"."+Left$(esi, 4)+Spc2$+Mid$(esi, 10, 2)+":"+Mid$(esi, 12, 2)+":"+Mid$(esi, 14, 2)
                                        ; ClearLastError
                                       Touch Files$(ecx), TimeSF(edi)
                                        ; deb 4, "Touch", eax, $Err$()
                                       .if Exist(Files$(ecx))
                                        PrintLine GfDate$(-1), Spc2$, GfTime$(-1)
                                        .endif
                                .else
                                        PrintLine "skipped, unknown date format: ", Tb$, esi
                                .endif
                .else
                                PrintLine "skipped, no 201 detected: ", Tb$, esi
                .endif
        .else
                PrintLine "skipped, not a video file: ", Tb$, esi
        .endif
  Next
  Inkey "ok?"
EndOfCode


Typical output (the second, shorter line shows the changed date):
C:\Users\Jochen\Videos\*.mp4
matches eax             18
07.11.2018  12:27:53    C:\Users\Jochen\Videos\20160602_170844.mp4
02.06.2016  17:08:44
07.11.2018  12:27:42    C:\Users\Jochen\Videos\VID_20170531_195446.mp4
31.05.2017  19:54:46
07.11.2018  12:12:22    C:\Users\Jochen\Videos\VID_20170621_153022.mp4
Title: Sorting strings
Post by: jj2007 on November 19, 2018, 03:06:10 AM
Generates two Million random strings and sorts them using QSort (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1175) (which is an in-place mergesort).
Source & binaries attached: Extract exe and dll to the same folder, then run the exe. Typical result for a Core i5:
11 s for writing 2 Millon strings
106 ms for reading 5 Million strings
3.2 seconds for sorting 5 Million strings

Title: Re: Miscellaneous snippets
Post by: TimoVJL on November 20, 2018, 01:59:09 AM
With my slow AMD:62 s for writing 2 Millon strings
383 ms for reading 5 Million strings
12. seconds for sorting 5 Million strings

Title: Re: Miscellaneous snippets
Post by: jj2007 on November 20, 2018, 01:21:13 PM
Where has your code gone? I've tested it (attached), and that's a really fast sort, Timo - interesting :t
Title: TitleCase$
Post by: jj2007 on November 21, 2018, 01:43:12 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  NoTitleCase$ equ <Chr$(".a.an.and.are.as.but.by.for.is.in.or.the.that.")>        ; this is the default, inspired by Lauren Ipsum (https://writing.stackexchange.com/questions/4621/which-words-should-not-be-capitalized-in-title-case), but you can use others
  Init 
  Let ecx="World bank and OECD are organisations that - as a rule - i consider very powerful"
  PrintLine ecx
  Inkey TitleCase$(ecx)
EndOfCode


Output:
World bank and OECD are organisations that - as a rule - i consider very powerful
World Bank and OECD are Organisations that - as a Rule - I Consider Very Powerful


Inspired by Munair on the FreeBasic forum (https://www.freebasic.net/forum/viewtopic.php?f=7&t=27174) :icon14:
Title: PSHUFB
Post by: jj2007 on December 05, 2018, 08:56:48 PM
Just for fun, a little demo showing the use of the PSHUFB instruction, and some macro tricks:
include \masm32\MasmBasic\MasmBasic.inc

SwapBytes MACRO pBytes
  if type(pBytes) eq REAL8
movlps xmm0, pBytes
  else
mov edx, pBytes
movups xmm0, oword ptr [edx]
  endif
  mov eax, esp
  and esp, -16
  push 00010203h ; the magic numbers
  push 04050607h
  push 08090a0bh
  push 0c0d0e0fh
  PSHUFB xmm0, oword ptr [esp] ; shuffle the bytes! (will crash on very old CPUs, sorry...)
  movups oword ptr [esp], xmm0
  if type(pBytes) eq REAL8
fld qword ptr [esp]
xchg eax, esp
EXITM <ST(0)> ; leave the double in the FPU
  else
xchg eax, esp
EXITM <> ; the bytes are in xmm0, but the macro is not used as a function
  endif
ENDM
 
.data
MyReal8 REAL8 1234567890.1234567890
thestring db "!taerg si 23msaM", 0
.data?
SwappedR8 REAL8 ?
out$ db 20 dup(?)

  Init
  PrintLine "Original:", Tb$, offset thestring
  SwapBytes(offset thestring) ; return 16 bytes in xmm0
  movups oword ptr out$, xmm0
  PrintLine "Swapped:", Tb$, offset out$
 
  Print Str$("\nMyReal8  \t%Hf", MyReal8), Str$("\nas BigEndian\t%Hf", SwapBytes(MyReal8)) ; SwapBytes leaves the double in the FPU
  fstp SwappedR8
  Inkey Str$("\nreconverted\t%Hf\n", SwapBytes(SwappedR8)v)
EndOfCode


Note that the macro can be used either as a function:
Print Str$(SwapBytes(MyReal8))

or "standalone":
SwapBytes(offset thestring)

Output:Original:       !taerg si 23msaM
Swapped:        Masm32 is great!

MyReal8         1234567890.1234567
as BigEndian    3.5842524504192598e+246
reconverted     1234567890.1234567
Title: Two-dimensional string arrays
Post by: jj2007 on December 08, 2018, 01:23:31 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Dim My$(tab)                          ; create a two-dimensional string array
  For_ ecx=0 To 7
        Let edi=Str$("Test %i\t", ecx)
        Let My$(ecx)=String$(8, edi)    ; create a string with 8 columns
  Next
  For_ ecx=0 To 7
        Let My$(ecx, ecx)="Hello!!"     ; set individual elements
        Let My$(ecx, 7-ecx)="*Ciao*"
  Next
  For_ ecx=0 To 7
        For_ ct=0 To 7
                Print My$(ecx, ct), Spc2$
        Next
        Print
  Next
EndOfCode


Output:Hello!  Test 0  Test 0  Test 0  Test 0  Test 0  Test 0  *Ciao*
Test 1  Hello!  Test 1  Test 1  Test 1  Test 1  *Ciao*  Test 1
Test 2  Test 2  Hello!  Test 2  Test 2  *Ciao*  Test 2  Test 2
Test 3  Test 3  Test 3  Hello!  *Ciao*  Test 3  Test 3  Test 3
Test 4  Test 4  Test 4  *Ciao*  Hello!  Test 4  Test 4  Test 4
Test 5  Test 5  *Ciao*  Test 5  Test 5  Hello!  Test 5  Test 5
Test 6  *Ciao*  Test 6  Test 6  Test 6  Test 6  Hello!  Test 6
*Ciao*  Test 7  Test 7  Test 7  Test 7  Test 7  Test 7  Hello!


Purest assembly :bgrin:
Title: Good ol' EOF(#1) and User-Defined Types
Post by: jj2007 on January 13, 2019, 01:58:51 PM
Strange - I had forgotten to code the Eof() macro, here it is:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)

SOMEUDT STRUCT  ; a user-defined type
  mydouble      REAL8 ?
  mydword       DWORD ?
  myfloat       REAL4 ?
SOMEUDT ENDS

MyUDT SOMEUDT <?>

Eof MACRO arg
  push Loc(arg)
  void Lof(arg)
  pop edx
  cmp edx, eax
  exitm <!Sign?>
ENDM

  Init
  Open "O", #1, "TypeTest.udt"
  For_ ecx=101 To 103
       mov MyUDT.mydword, ecx  ; 101, 102, ...
       lea eax, [ecx+900]
       SetFloat MyUDT.myfloat=eax      ; 1001, 1002, ...
       add eax, 9000
       SetFloat MyUDT.mydouble=eax     ; 10001, 10002, ...
       Store #1, MyUDT         ; save UDT to file
  Next
  Close
  Open "I", #1, "TypeTest.udt"
  .Repeat
        Recall #1, MyUDT
        deb 4, "Test", MyUDT.mydouble, MyUDT.myfloat, MyUDT.mydword
  .Until Eof(#1)
  Close
  Inkey CrLf$, "Yep, that's purest assembler ;-)"
EndOfCode



Output:
Test
MyUDT.mydouble  10001.00000000000
MyUDT.myfloat   1001.000
MyUDT.mydword   101

Test
MyUDT.mydouble  10002.00000000000
MyUDT.myfloat   1002.000
MyUDT.mydword   102

Test
MyUDT.mydouble  10003.00000000000
MyUDT.myfloat   1003.000
MyUDT.mydword   103

Yep, that's purest assembler ;-)


P.S.: To get random access to some record, use this before closing the file:

  m2m eax, 1                   ; get record #1
  imul eax, SOMEUDT            ; calculate position in file
  Seek #1, eax
  Recall #1, MyUDT
  deb 4, "Test with Seek", MyUDT.mydouble, MyUDT.myfloat, MyUDT.mydword
  Close
Title: Re: Good ol' EOF(#1) and User-Defined Types
Post by: TimoVJL on January 13, 2019, 11:50:18 PM
Quote from: jj2007 on January 13, 2019, 01:58:51 PM
P.S.: To get random access to some record, use this before closing the file:

  m2m eax, 1                   ; get record #1
  imul eax, SOMEUDT            ; calculate position in file
I didn't understood that :icon_rolleyes:
  mov eax, 1
  imul eax, sizeof SOMEUDT

EDIT:
OK
push 1 / pop eax is two bytes shorter.
imul eax, SOMEUDT is same as imul eax, sizeof SOMEUDT
Title: Re: Miscellaneous snippets
Post by: ragdog on January 14, 2019, 12:56:07 AM
Quote
I didn't understood that :icon_rolleyes:
Code: [Select]

  mov eax, 1
  imul eax, sizeof SOMEUDT

Hello Timo

1 * size of  SOMEUDT structur
Title: Re: Good ol' EOF(#1) and User-Defined Types
Post by: jj2007 on January 14, 2019, 02:05:30 AM
Quote from: TimoVJL on January 13, 2019, 11:50:18 PM
push 1 / pop eax is two bytes shorter.
imul eax, SOMEUDT is same as imul eax, sizeof SOMEUDT

Yes, as ragdog already noted. It took me years to realise that mov eax, sizeof SOMESTRUCT is the same as mov eax, SOMESTRUCT ;)

And m2m eax, n is simply some bytes shorter for n=-128 ... +127, so I always use it, except perhaps for a really speed-critical innermost loop.
Title: Download URL with UTF8
Post by: jj2007 on January 15, 2019, 11:16:20 PM
include \masm32\MasmBasic\MasmBasic.inc
  Init
  Inkey NoTag$(FileRead$("https://de.wikipedia.org/wiki/Spezial:Zufällige_Seite"))
EndOfCode
Title: Animated GIF
Post by: jj2007 on January 16, 2019, 02:26:28 AM
include \masm32\MasmBasic\Res\MbGui.asm
Event Paint
  .if !Exist("test.img")
        Let esi=FileRead$("https://i.gifer.com/6H3K.gif")
        FileWrite "test.img", esi, LastFileSize
  .endif
  GuiImage "test.img", fit
EndOfCode
Title: Creating a matrix of doubles and store it to a text file
Post by: jj2007 on February 08, 2019, 09:14:05 PM
This snippet
- generates a 512*512 matrix of random double values
- writes all values to a string array
- saves the strings to disk

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  elements=512
  PrintCpu 0
  NanoTimer()
  Dim matrix(elements,elements) As REAL8
  For_ ct=0 To elements-1
        For_ ecx=0 To elements-1
                Rand(-12345.6789, 12345.6789, matrix(ct, ecx))
        Next
  Next
  PrintLine NanoTimer$(), Str$(" for generating %i random doubles", matrix(?))
  NanoTimer()
  Dim out$()                    ; create a zstring array
  Let edi=New$(16*elements)    ; prepare for long numbers, e.g. 12345.6789
  For_ ct=0 To elements-1
        push edi
       For_ ecx=0 To elements-1
                invoke MbCopy, edi, Str$("%9f\t", matrix(ct, ecx)), -2
                xchg eax, edi
        Next
        and dword ptr [edi-1], 0
        pop edi
       Let out$(ct)=edi
  Next
  PrintLine NanoTimer$(), Str$(" for %i strings", ct)
  Store "Matrix.txt", out$()    ; save to disk
  Inkey "wanna see the result? (y)"
  If_ eax=="y" Then ShEx "Matrix.txt"   ; show it in Notepad etc
EndOfCode


Typical output:Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
5078 µs for generating 262144 random doubles
66 ms for 512 strings
Title: Duplicate bits
Post by: jj2007 on February 17, 2019, 02:34:07 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)

DuplicateBits MACRO arg
Local Lb0, Lb1, Lb2
  mov edx, arg
  xor eax, eax
  push ecx
  mov ecx, 11000000000000000000000000000000b
Lb0:
  rol ecx, 2                            ; in the first round, ecx will be 11b
  shr edx, 1                            ; get the carry flag
  je Lb1
  jnc Lb0
  or eax, ecx
  jmp Lb0
Lb1:
  jnc Lb2
  or eax, ecx
Lb2:
  pop ecx
  EXITM <eax>
ENDM

  Init
  m2m ecx, 1
  mov edi, 256
  .Repeat
        mov esi, ecx
        shr edi, 1
        or esi, edi
        Print Right$(Cat$(Replace$(Bin$(esi), "0", " ")), 8 ), Spc4$     ; print the original without the 0s
        Print Right$(Cat$(Replace$(Bin$(DuplicateBits(esi)), "0", " ")), 16), CrLf$  ; print the duplicate
        shl ecx, 1
  .Until ecx>255
  Inkey CrLf$, "-- hit any key --"
EndOfCode


Output:1      1    11            11
1    1       11        11
  1  1          11    11
   11             1111
   11             1111
  1  1          11    11
1    1       11        11
1      1    11            11


Source attached. The macro will also work for plain Masm32 sources.
Title: FizzBuzz
Post by: jj2007 on May 09, 2019, 12:33:31 AM
The "Fizz-Buzz test" (http://wiki.c2.com/?FizzBuzzTest) is an interview question designed to help filter out the 99.5% of programming job candidates who can't seem to program their way out of a wet paper bag. The text of the programming assignment is as follows:

Quote"Write a program that prints the numbers from 1 to 100. But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz". For numbers which are multiples of both three and five print "FizzBuzz"."

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  For_ ct=1 To 100
        xor esi, esi            ; flag Fizz or Buzz
        mov eax, ct
        cdq
        mov ecx, 3
        div ecx
        test edx, edx
        .if Zero?
                inc esi
                Print "Fizz"
        .endif
        mov eax, ct
        cdq
        mov ecx, 5
        div ecx
        test edx, edx
        .if Zero?
                inc esi
                Print "Buzz"
        .endif
        .if !esi
                Print Str$(ct)
        .endif
        Print " "
  Next
  Inkey "ok?"
EndOfCode
Title: Re: Miscellaneous snippets
Post by: TimoVJL on May 09, 2019, 01:50:29 AM
In C, perhaps it works ::)int __cdecl main(void)
{
char *Fizz = "Fizz";
char *Buzz = "Buzz";
char *pF, *pB;
for (int i=0; i<100; i++) {
pF = 0;
pB = 0;
if (i) {
if (i % 3 == 0) pF = Fizz;
if (i % 5 == 0) pB = Buzz;
}
if (pF || pB) {
if (pF) printf(pF);
if (pB) printf(pB);
printf("\n");
} else printf("%d\n", i);
}
return 0;
}
Title: Re: Miscellaneous snippets
Post by: aw27 on May 09, 2019, 02:21:18 AM
Another C version (may be can be made shorter   ::)):

int main()
{
   char buff[16];
   for (int i = 1; i <= 100; i++)
      printf("%s\n", !(i % 3) && !(i % 5) ? "FizzBuff": (!(i % 5) ? "Buzz": (!(i % 3) ? "Fizz": itoa(i,buff,10))));
}
Title: Re: Miscellaneous snippets
Post by: TimoVJL on May 09, 2019, 02:59:28 AM
Nice!
4 bytes shorter, but not C99.

Jose's version unpacked:
#pragma comment(lib, "msvcrt.lib")
char *_itoa(int value, char *dst, int base);
void __cdecl mainCRTStartup(void)
{
__declspec(dllimport) void __cdecl exit(int status);
int __cdecl main(void);
exit(main());
}
int main(void)
{
   char buff[16];
char *p;
   for (int i = 1; i <= 100; i++) {
if (!(i % 3) && !(i % 5)) p = "FizzBuff";
else if (!(i % 5)) p = "Buzz";
else if (!(i % 3)) p =  "Fizz";
else p = _itoa(i,buff,10);
puts(p);
}
return 0;
}

EDIT:#pragma comment(lib, "msvcrt.lib")
char *_itoa(int value, char *dst, int base);
void __cdecl mainCRTStartup(void)
{
__declspec(dllimport) void __cdecl exit(int status);
int __cdecl main(void);
exit(main());
}
int __cdecl main(void)
{
char *Fizz = "Fizz";
char *Buzz = "Buzz";
char *pF, *pB;
char buf[16];
for (int i=0; i<100; i++) {
pF = 0;
pB = 0;
if (i % 3 == 0) pF = Fizz;
if (i % 5 == 0) pB = Buzz;
if (pF || pB) {
if (pF) printf(pF);
if (pB) printf(pB);
puts("");
} else {
puts(_itoa(i, buf, 10));
}
}
return 0;
}
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 09, 2019, 03:30:54 AM
Choose (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1289) is purest Assembly :P

include \masm32\MasmBasic\MasmBasic.inc
  Init
  For_ ct=1 To 100
        xor ebx, ebx ; flag Fizz or Buzz
        mov eax, ct
        cdq
        mov ecx, 3
        div ecx
        test edx, edx
        sete bl
        mov eax, ct
        mov ecx, 5
        div ecx
        test edx, edx
        sete dl
        lea ebx, [ebx+2*edx]
        Print Choose(ebx, Str$("%i ", ct), "Fizz ", "Buzz ", "FizzBuzz ")
  Next
  Inkey "ok?"
EndOfCode
Title: Re: Miscellaneous snippets
Post by: aw27 on May 09, 2019, 03:57:50 AM
 :( itoa  :biggrin: _itoa  :lol: purest Assembly
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 09, 2019, 11:51:40 AM
Certain similarities should be accepted 8)

printf("%s\n", !(i % 3) && !(i % 5) ? "FizzBuff": (!(i % 5) ? "Buzz": (!(i % 3) ? "Fizz": itoa(i,buff,10))));
Print Choose(ebx, Str$("%i ", ct), "Fizz ", "Buzz ", "FizzBuzz ")


Full version:

include Modulo.inc
  Init
  For_ ecx=1 To 30
        lea ebx, [2*IsModulo(ecx, 5)]
        add ebx, IsModulo(ecx, 3)
       PrintLine Choose(ebx, Str$("%i ", ecx), "Fizz ", "Buzz ", "FizzBuzz ")
  Next
  Inkey
EndOfCode


I wonder if it should be called ModZero(src, imm)?

Output:1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz

;)
Title: Plotting data
Post by: jj2007 on May 16, 2019, 01:33:12 PM
include \masm32\MasmBasic\Res\MbGui.asm
  ArraySet current() As double=120, 125, 122, 119, 134, 138, 141, 159, 162, 178
  ArraySet voltage() As double=250, 210, 180, 155, 140, 125, 110, 100, 90, 80
  SetAxisX "Электроток", s 0, d 1/5, grid 1   ; s=start value, d=difference between gridlines
  SetAxisY "Voltage", s 0, d 5/5, grid 1
Event Paint
  ArrayPlotValues "%i V", 8, -12        ; format$, dx & dy positions
  ArrayPlot current():voltage(), RgbCol(0, 0, 255), lines=3
  ArrayPlot exit, "繪製科學數據非常容易!"
EndOfCode


(http://www.jj2007.eu/images/PlotVoltageOverCurrent.png)
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 18, 2019, 03:54:37 AM
Impressive Jochen :t
how fast is arrayplot compared to GDI?
is it masmbasic functions used in Lord Adef's game,scrolling and sprite functions included already in masmbasic?
strange if not,because its included GET and PUT in qbasic
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 18, 2019, 10:29:03 AM
Thanks, Daydreamer. Arrayplot is Gdi, actually. Speedwise, check the Sinus plot template (attached). Re GET & PUT: There are ways to do something similar in MasmBasic, but I doubt that LordAdef is using them.
Title: Re: Plotting data
Post by: LiaoMi on May 18, 2019, 06:22:21 PM
Quote from: jj2007 on May 16, 2019, 01:33:12 PM
include \masm32\MasmBasic\Res\MbGui.asm
  ArraySet current() As double=120, 125, 122, 119, 134, 138, 141, 159, 162, 178
  ArraySet voltage() As double=250, 210, 180, 155, 140, 125, 110, 100, 90, 80
  SetAxisX "Электроток", s 0, d 1/5, grid 1   ; s=start value, d=difference between gridlines
  SetAxisY "Voltage", s 0, d 5/5, grid 1
Event Paint
  ArrayPlotValues "%i V", 8, -12        ; format$, dx & dy positions
  ArrayPlot current():voltage(), RgbCol(0, 0, 255), lines=3
  ArrayPlot exit, "繪製科學數據非常容易!"
EndOfCode


(http://www.jj2007.eu/images/PlotVoltageOverCurrent.png)

Hi jj2007,

is it possible to make smoothing lines? the soul requires aesthetics)
Smoothing a curve in VB.Net https://www.codeproject.com/Questions/358853/Smoothing-a-curve-in-VB-Net (https://www.codeproject.com/Questions/358853/Smoothing-a-curve-in-VB-Net)
Title: Re: Plotting data
Post by: jj2007 on May 18, 2019, 07:06:10 PM
Quote from: LiaoMi on May 18, 2019, 06:22:21 PMis it possible to make smoothing lines?

Probably, but the CodeProject guy is on the wrong track. For scientific data visualisation, you can't use "shortcuts" of that sort, they must be exact. What you can do, though, is smoothing a ragged line by anti-aliasing:
(https://joeycamson.files.wordpress.com/2011/11/aliasing.png)

If I find the time, I'll find a way to let GdiPlus draw these lines 8)
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 19, 2019, 12:19:26 AM
Quote from: jj2007 on May 18, 2019, 10:29:03 AM
Thanks, Daydreamer. Arrayplot is Gdi, actually. Speedwise, check the Sinus plot template (attached). Re GET & PUT: There are ways to do something similar in MasmBasic, but I doubt that LordAdef is using them.
if its gdi draw chinese characters,please check in my thread if you can show a smoother solution to this problem Jochen
http://masm32.com/board/index.php?topic=7834.0 (http://masm32.com/board/index.php?topic=7834.0)
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 19, 2019, 05:16:09 AM
The text is not the problem, Gdi draws fonts OK. It is the ragged line. Below an excerpt from the plot where I added a line drawn with Gdi+, using high quality anti-aliasing. It does make a difference, but the extra quality is not overwhelming.

You must zoom in quite a lot to see a difference. On Chrome/SlimJet it's holding Control and pushing the mousewheel forward.

Btw this is line width 3; for finer lines, the difference between plain Gdi and high quality anti-aliased Gdi+ is almost negligible. On the right side of the graph, I added a comparison between 5px and 1px lines. If you zoom to 200 or 250%, the difference becomes evident. Note also how neat the Chinese text looks - it's really fine.
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 19, 2019, 06:01:06 AM
Quote from: jj2007 on May 19, 2019, 05:16:09 AM
The text is not the problem, Gdi draws fonts OK. It is the ragged line. Below an excerpt from the plot where I added a line drawn with Gdi+, using high quality anti-aliasing. It does make a difference, but the extra quality is not overwhelming.

You must zoom in quite a lot to see a difference. On Chrome/SlimJet it's holding Control and pushing the mousewheel forward.

Btw this is line width 3; for finer lines, the difference between plain Gdi and high quality anti-aliased Gdi+ is almost negligible. On the right side of the graph, I added a comparison between 5px and 1px lines. If you zoom to 200 or 250%, the difference becomes evident. Note also how neat the Chinese text looks - it's really fine.
maybe d3d can antialias better and faster with full antialias settings
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 19, 2019, 06:18:16 AM
maybe - post a demo ;-)
Title: Re: Miscellaneous snippets
Post by: LiaoMi on May 19, 2019, 07:08:31 PM
Hi,

I take my words back  :biggrin: It looks like its just impossible to make normal smoothing with GDI, other technologies have to deal with it.

https://software.intel.com/en-us/articles/mlaa-efficiently-moving-antialiasing-from-the-gpu-to-the-cpu (https://software.intel.com/en-us/articles/mlaa-efficiently-moving-antialiasing-from-the-gpu-to-the-cpu)
SMAA: Subpixel Morphological Antialiasing https://github.com/iryoku/smaa (https://github.com/iryoku/smaa)
Demo - https://web.archive.org/web/20121023110459/http://www.iryoku.com/mlaa/downloads/Jimenez-MLAA-DX10-v1.5.exe (https://web.archive.org/web/20121023110459/http://www.iryoku.com/mlaa/downloads/Jimenez-MLAA-DX10-v1.5.exe)

Below, I gave examples showing the difference between display technologies.
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 19, 2019, 08:03:31 PM
Project upgrade failed (your source is 2007, I tried with Visual Crap 2010) 8)
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 20, 2019, 09:01:26 PM
Quote from: jj2007 on May 19, 2019, 06:18:16 AM
maybe - post a demo ;-)
docs says it doesnt antialias lines,only polys in fullscene antialias
Title: Re: Miscellaneous snippets
Post by: LiaoMi on May 20, 2019, 10:46:18 PM
Quote from: jj2007 on May 19, 2019, 08:03:31 PM
Project upgrade failed (your source is 2007, I tried with Visual Crap 2010) 8)

Hi jj2007,

I also have no success in the visual studio 2019, I will try on another machine. The first example shows that in GDI it is not reachable, and the second example shows how ideally it should be, taking into account that another mechanism is used. The speed and processing of both techniques are completely different. I do not think it's worth puzzling over this problem  :rolleyes:
Title: Re: Miscellaneous snippets
Post by: daydreamer on May 25, 2019, 10:34:45 PM
Quote from: jj2007 on May 18, 2019, 10:29:03 AM
Thanks, Daydreamer. Arrayplot is Gdi, actually. Speedwise, check the Sinus plot template (attached). Re GET & PUT: There are ways to do something similar in MasmBasic, but I doubt that LordAdef is using them.
you use GDI background color=bitmap? or use background color=null?
for example want to have a moving object,just redraw it together with erase few pixels behind it?

I found this direct2d vs GDI,look below at the images direct2d is smoother curves
https://docs.microsoft.com/sv-se/windows/desktop/direct2d/direct2d-overview (https://docs.microsoft.com/sv-se/windows/desktop/direct2d/direct2d-overview)
Title: Re: Miscellaneous snippets
Post by: jj2007 on May 25, 2019, 11:26:11 PM
Quote from: daydreamer on May 25, 2019, 10:34:45 PMI found this direct2d vs GDI,look below at the images direct2d is smoother curves

The curves are Gdi vs D2D, not Gdi+. They write "When rendering in software, applications that use Direct2D experience substantially better rendering performance than with GDI+ and with similar visual quality." - and I bet they mean "almost the same quality".
Title: WM_DROPFILES
Post by: jj2007 on June 20, 2019, 06:15:26 PM
GuiParas equ "Event Dropfiles demo", x1000, y20, w350, h700, cblack, b00FFFFD0h
include \masm32\MasmBasic\Res\MbGui.asm

Event DropFiles
  GfNoPaths=1                           ; optional: don't include the paths
  For_ ecx=0 To eax-1                   ; #files was returned in eax
        wPrintLine wRec$(Files$(ecx))   ; show the files in the console window
  Next
  GuiRefresh                            ; GuiText needs a WM_PAINT handler

Event Paint
  For_ ecx=0 To Files$(?)-1
        GuiText 3, ecx*20, Files$(ecx)
  Next
GuiEnd
Title: InternetCrackUrl
Post by: jj2007 on July 03, 2019, 08:13:59 AM
Little problems, it works only partially:

include \masm32\MasmBasic\MasmBasic.inc ; download
uselib WinInet

if 0
URL_COMPONENTSA STRUCT
dwStructSize DWORD ?
lpszScheme LPSTR ?
dwSchemeLength DWORD ?
nScheme DWORD ?
lpszHostName LPSTR ?
dwHostNameLength DWORD ?
nPort      INTERNET_PORT <>
lpszUserName LPSTR ?
dwUserNameLength DWORD ?
lpszPassword LPSTR ?
dwPasswordLength DWORD ?
lpszUrlPath LPSTR ?
dwUrlPathLength DWORD ?
lpszExtraInfo LPSTR ?
dwExtraInfoLength DWORD ?
URL_COMPONENTSA ENDS
endif
.data?
UrlComp URL_COMPONENTS <>
HostName db 100 dup(?)
UserName db 100 dup(?)
UrlPath db 1000 dup(?)
ExtraInfo db 100 dup(?)

  Init
  add UrlComp.dwStructSize, URL_COMPONENTS
  mov UrlComp.lpszScheme, Chr$("Whatever suits you")
  add UrlComp.dwSchemeLength, c$Len
  mov UrlComp.lpszHostName, offset HostName
  add UrlComp.dwHostNameLength, 100
  add UrlComp.nScheme, INTERNET_SCHEME_UNKNOWN ; INTERNET_SCHEME_DEFAULT
  mov UrlComp.lpszUserName, offset UserName
  add UrlComp.dwUserNameLength, 100
  mov UrlComp.lpszUrlPath, offset UrlPath
  add UrlComp.dwUrlPathLength, 1000
  mov UrlComp.lpszExtraInfo, offset ExtraInfo
  add UrlComp.dwExtraInfoLength, 100

  invoke InternetCrackUrl, Chr$("https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetcrackurla"), 0, ICU_DECODE, addr UrlComp
  deb 4, "res", eax, $Err$(), $UrlComp.lpszScheme, $offset HostName, $offset UserName, $UrlPath, $ExtraInfo, UrlComp.nPort
  invoke InternetCrackUrl, Chr$("http://www.google.com/test.html"), 0, ICU_DECODE, addr UrlComp
  deb 4, "res", eax, $Err$(), $UrlComp.lpszScheme, $offset HostName, $offset UserName, $UrlPath, $ExtraInfo, UrlComp.nPort

EndOfCode


res
eax             1
$Err$()         Operazione completata.__
$UrlComp.lpszScheme     https
$offset HostName        docs.microsoft.com
$offset UserName
$UrlPath        470     <not a pointer>
$ExtraInfo      00      <not a pointer>
UrlComp.nPort   443

res
eax             0
$Err$()         Area dati passata ad una chiamata al sistema troppo piccola.__
$UrlComp.lpszScheme     http
$offset HostName        www.google.com
$offset UserName
$UrlPath        470     <not a pointer>
$ExtraInfo      00      <not a pointer>
UrlComp.nPort   80
Title: Re: Miscellaneous snippets
Post by: TimoVJL on July 03, 2019, 04:55:34 PM
Init buffer sizes between calls
Title: Re: Miscellaneous snippets
Post by: jj2007 on July 03, 2019, 05:59:18 PM
Thanks, Timo. Right, even a mov UrlComp.dwUserNameLength, 1 is sufficient. It seems that if you pass a pointer to a buffer, the length must be at least one even if you don't get a text back.
Title: Export a table to the Masm32 Forum
Post by: jj2007 on December 07, 2019, 01:09:58 AM
A snippet that allows to copy a table e.g. from Excel and paste it here:

include \masm32\MasmBasic\MasmBasic.inc
  Init
  Let esi=Clip$()
  .if Len(esi)
Let esi=Replace$(esi, CrLf$, Chr$("[/td][/tr]", 13, 10, "[tr][td]"))
Let esi=Replace$(esi, Tb$, "[/td][td]")
Let esi="[table][tr][td]"+esi+"[/td][/table]"
Inkey "Put table on clipboard (y)?"
If_ eax=="y" Then SetClip$ esi ; put table on the clipboard
  .else
MsgBox 0, "No text on clipboard, sorry", "Hi", MB_OK
  .endif
EndOfCode


Example (see attached SimpleTable.tab):
NameFirst nameStreetCity
FerrellAaliyah2716 Simpson StreetBelyando
OnealAaron2033 Rosales StreetPort Iatta
CooperAbagail1381 Lee StreetPalmers Oaky
DavidAbagail2445 Price StreetPopanyinning
HamptonAbagail35 Boyer StreetRed Range
Title: Working with maps
Post by: jj2007 on December 14, 2019, 01:48:12 PM
Quote from: daydreamer on December 14, 2019, 12:00:52 PMAlso seen map drawing,why don't add a Fun quiz to geography and country stats on different things?

Yes, that could be fun. Prepare a file with questions and answers, and we'll add it to the attached template (which requires Europe.zip from the MB extras (http://masm32.com/board/index.php?topic=94.msg265#msg265)).

Here is the source (attached, with exe):

include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl MyMap, "canvas", w660      ; define a canvas control using 66% of the client rect width
  GuiControl TheManual, "richedit", res:92, x660, w340, bcol RgbCol(255, 255, 240)
  GuiControl Sbar, "statusbar"
  ArrayLoadMap 0, 90                    ; Europe.dmi and Europe.map in resources
  MapColours(0, "abcdefghiabcdefghiabcdefghiabcdefghiabcdefghiabcdefghi")      ; set colours to map 0 (a=red, i=green)
Event CanvasPaint
  ArrayPlot RgbCol(0, 240, 255)         ; init and set background colour
  PaintMap RgbCol(127, 127, 127), lines=2       ; map with grey borders 2px thick
  GuiTextBox 99.0-120, 51.0, 120, auto, "This program requires the file Europe.map", bcol LiteGreen, font -16:FW_NORMAL
  ArrayPlot exit, "Europe"
Event Message
  .if uMsg_==WM_MAPCLICKED
        .if MapRegion>=0
                SetWin$ hSbar="You clicked on "+MapRegion$      ; *** add your ideas here ***
        .else
                SetWin$ hSbar=Time$     ; user clicked into water ;-)
        .endif
  .endif
GuiEnd
Title: Re: Working with maps
Post by: LiaoMi on December 14, 2019, 10:34:20 PM
Quote from: jj2007 on December 14, 2019, 01:48:12 PM
Quote from: daydreamer on December 14, 2019, 12:00:52 PMAlso seen map drawing,why don't add a Fun quiz to geography and country stats on different things?

Yes, that could be fun. Prepare a file with questions and answers, and we'll add it to the attached template (which requires Europe.zip from the MB extras (http://masm32.com/board/index.php?topic=94.msg265#msg265)).

Here is the source (attached, with exe):

include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl MyMap, "canvas", w660      ; define a canvas control using 66% of the client rect width
  GuiControl TheManual, "richedit", res:92, x660, w340, bcol RgbCol(255, 255, 240)
  GuiControl Sbar, "statusbar"
  ArrayLoadMap 0, 90                    ; Europe.dmi and Europe.map in resources
  MapColours(0, "abcdefghiabcdefghiabcdefghiabcdefghiabcdefghiabcdefghi")      ; set colours to map 0 (a=red, i=green)
Event CanvasPaint
  ArrayPlot RgbCol(0, 240, 255)         ; init and set background colour
  PaintMap RgbCol(127, 127, 127), lines=2       ; map with grey borders 2px thick
  GuiTextBox 99.0-120, 51.0, 120, auto, "This program requires the file Europe.map", bcol LiteGreen, font -16:FW_NORMAL
  ArrayPlot exit, "Europe"
Event Message
  .if uMsg_==WM_MAPCLICKED
        .if MapRegion>=0
                SetWin$ hSbar="You clicked on "+MapRegion$      ; *** add your ideas here ***
        .else
                SetWin$ hSbar=Time$     ; user clicked into water ;-)
        .endif
  .endif
GuiEnd


If you reduce the window, then everything is well rendered, but if you enlarge the window on the left side, especially in large sections, you can see an unusual drawing line from the text container.
Title: Re: Miscellaneous snippets
Post by: daydreamer on December 15, 2019, 04:29:50 AM
is there a nice site to get updated country facts and figures with help of recall?to fill a country array of struct with different categorys
and create quiz similar to this:
http://masm32.com/board/index.php?topic=7834.15
Title: Re: Working with maps
Post by: jj2007 on December 15, 2019, 05:13:59 AM
Quote from: LiaoMi on December 14, 2019, 10:34:20 PMIf you reduce the window, then everything is well rendered, but if you enlarge the window on the left side, especially in large sections, you can see an unusual drawing line from the text container.

No such line here :rolleyes:

Does anybody else see a line in the wrong place? Which OS?
Title: Re: Working with maps
Post by: LiaoMi on December 15, 2019, 07:42:31 AM
Quote from: jj2007 on December 15, 2019, 05:13:59 AMthe picture jumps here and there, photo report can be downloaded here https://www.upload.ee/files/10847594/jj2.zip.html (https://www.upload.ee/files/10847594/jj2.zip.html)

jj2007: Thanks, now I see what you mean: the delay when updating the richedit control. There is a simple explanation for this effect: it can't be done fast enough. Even when sizing the window slowly, cpu usage goes up to 100% for the core of the process. The map is about 18k lines to draw - and this is not done via StretchBlt, it really gets completely drawn for each frame. Watch the Norwegian coastline when sizing the main window very slowly.

In theory, I could switch to StretchBlt, but 1. sizing the window frenetically is not a typical usage and 2. painting a single country to achieve the feedback effect when you click into the country would require more sophisticated code and logic.

P.S.: I just realised that instead of quoting your post, I modified it, and also deleted most of it - sorry. These are the pros and cons of being the administrator of a sub-forum :cool:
Title: Re: Miscellaneous snippets
Post by: LiaoMi on December 15, 2019, 10:08:09 PM
Changing the DC a Control paints on
Hello,

Is it possible to make a control (a richedit control for example) paint onto your own DC instead of the window DC?

http://www.asmcommunity.net/forums/topic/?id=15998 (http://www.asmcommunity.net/forums/topic/?id=15998)

WS_EX_COMPOSITED
0x02000000L
Paints all descendants of a window in bottom-to-top painting order using double-buffering. Bottom-to-top painting order allows a descendent window to have translucency (alpha) and transparency (color-key) effects, but only if the descendent window also has the WS_EX_TRANSPARENT bit set. Double-buffering allows the window and its descendents to be painted without flicker. This cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC.
Windows 2000: This style is not supported.

As an option ..
myRichCtrl.ShowWindow(SW_HIDE);
myRichCtrl.DoSomething();
myRichCtrl.ShowWindow(SW_SHOW);
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 16, 2019, 11:34:41 AM
Quote from: LiaoMi on December 15, 2019, 10:08:09 PMWS_EX_COMPOSITED

Looks interesting, thanks :thumbsup:

But when I add this style to an edit or richedit control, CreateWindowEx fails. Raymond Chen writes about another issue, though. (https://devblogs.microsoft.com/oldnewthing/20171018-00/?p=97245)

Attached another one from the life expectancy series, now comparing two countries. The red line gets chosen with the left and right arrows, the blue one by clicking into the map. Source included.
Title: Re: Miscellaneous snippets
Post by: Biterider on December 16, 2019, 05:37:45 PM
Hi
I used the WS_EX_COMPOSITED style for my own controls and it works fine if you follow the MS rules.
One problem I noticed is that the scrollbar loses the scrollbox transition effects.
It's a trifle if you get rid of the awful flicker.

Biterider
Title: Re: Miscellaneous snippets
Post by: LiaoMi on December 16, 2019, 11:22:04 PM
Quote from: Biterider on December 16, 2019, 05:37:45 PM
Hi

I used the WS_EX_COMPOSITED style for my own controls and it works fine if you follow the MS rules.
One problem I noticed is that the scrollbar loses the scrollbox transition effects.
It's a trifle if you get rid of the awful flicker.[/size]

Biterider

Hi Biterider,

:biggrin: Is the font specially size=2px small? Yes  :thumbsup:, following the recommendations of Microsoft, it should work.
Title: Re: Miscellaneous snippets
Post by: Biterider on December 17, 2019, 12:09:53 AM
Hi LiaoMi
Sorry, better now?  :biggrin:

Title: Re: Miscellaneous snippets
Post by: jj2007 on December 17, 2019, 01:13:45 AM
It should work, yes, but...

push 0                     ; ÚlParam = NULL
push dword ptr [40FA34]    ; ³hInst = 00400000
push 2A                    ; ³ID = 42.
push dword ptr [ebp+8]     ; ³hParent
push 28                    ; ³Height = 40.
push 5A                    ; ³Width = 90.
push 0A                    ; ³Y = 10.
push 0A                    ; ³X = 10.
push 54A41144              ; ³Style = WS_CHILD|WS_BORDER|WS_THICKFRAME|WS_VISIBLE|WS_CLIPSIBLINGS|WS_VSCROLL|1144
push 0                     ; ³WindowName = NULL
push offset 004101DE       ; ³ClassName = "RichEdit20W"
push 2000020               ; ³ExtStyle = WS_EX_TRANSPARENT|2000000
call <jmp.&user32.CreateWi ; ÀUSER32.CreateWindowExW


Now that I applied WS_EX_COMPOSITED to the parent window,
1. the control gets created using WS_EX_COMPOSITED = 2000000h
2. but WinID shows exstyle 0x120 for the child (and 2000100 for the parent)
3. and the flicker is as before

It certainly looks nice when dragging the edit over the map :tongue:
:sad:
Title: Mirrored squares
Post by: jj2007 on December 17, 2019, 08:27:58 PM
There are many numbers with matching "mirrored squares", like 13^2=169, 31^2=961:

matches number  mirror  square  mirror
1       11      11      121     121
2       12      21      144     441
3       13      31      169     961
4       21      12      441     144
5       22      22      484     484
6       31      13      961     169
100 numbers tested, 5.9% matches


include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals matches
  Init
  For_ ct=1 To 100000000                ; 100 million iterations
        Let esi=Str$(ct)                ; e.g. "13"
        void Val(esi)                   ; 13
        mul eax                         ; 169
        push Mirror$(Str$(eax))         ; "961"
        void Val(Mirror$(esi))          ; 31
        mul eax                         ; 961
        xchg Str$(eax), edi             ; edi: "961"
        pop ecx                         ; "961"
       .if !StringsDiffer(ecx, edi)     ; "961"=="961"
                inc matches
                PrintLine Str$(matches), Tb$, esi, Tb$, Mirror$(esi), Str$("\t%i\t", ct*ct), edi
        .endif
  Next
  Inkey Str$("%i numbers tested", ct-1), Str$(", %5f% matches", matches/ct*100)
EndOfCode
Title: Re: Working with maps
Post by: daydreamer on December 18, 2019, 07:16:30 AM
Quote from: jj2007 on December 14, 2019, 01:48:12 PM
Quote from: daydreamer on December 14, 2019, 12:00:52 PMAlso seen map drawing,why don't add a Fun quiz to geography and country stats on different things?

Yes, that could be fun. Prepare a file with questions and answers, and we'll add it to the attached template (which requires Europe.zip from the MB extras (http://masm32.com/board/index.php?topic=94.msg265#msg265)).

so far something to test with
Title: Re: Miscellaneous snippets
Post by: LiaoMi on December 18, 2019, 07:23:19 AM
Quote from: jj2007 on December 17, 2019, 01:13:45 AM
It should work, yes, but...

push 0                     ; ÚlParam = NULL
push dword ptr [40FA34]    ; ³hInst = 00400000
push 2A                    ; ³ID = 42.
push dword ptr [ebp+8]     ; ³hParent
push 28                    ; ³Height = 40.
push 5A                    ; ³Width = 90.
push 0A                    ; ³Y = 10.
push 0A                    ; ³X = 10.
push 54A41144              ; ³Style = WS_CHILD|WS_BORDER|WS_THICKFRAME|WS_VISIBLE|WS_CLIPSIBLINGS|WS_VSCROLL|1144
push 0                     ; ³WindowName = NULL
push offset 004101DE       ; ³ClassName = "RichEdit20W"
push 2000020               ; ³ExtStyle = WS_EX_TRANSPARENT|2000000
call <jmp.&user32.CreateWi ; ÀUSER32.CreateWindowExW


Now that I applied WS_EX_COMPOSITED to the parent window,
1. the control gets created using WS_EX_COMPOSITED = 2000000h
2. but WinID shows exstyle 0x120 for the child (and 2000100 for the parent)
3. and the flicker is as before

It certainly looks nice when dragging the edit over the map :tongue:
:sad:

Hi jj2007,

:sad: everything looks softer, but flicker is noticeable, frame-by-frame recording shows that the frame rate has increased, its not a solution.
Title: Re: Miscellaneous snippets
Post by: jj2007 on December 18, 2019, 10:00:04 AM
Quote from: LiaoMi on December 18, 2019, 07:23:19 AM:sad: everything looks softer, but flicker is noticeable, frame-by-frame recording shows that the frame rate has increased, its not a solution.

I can't see much difference, but in any case there is no solution because the map drawing is so slow that flicker on resize cannot be avoided.
Title: Utf-32 to Utf-16 converter
Post by: jj2007 on December 20, 2019, 01:51:02 PM
To use it, drag a file (e.g. ...FreeBasic\examples\unicode\hello_UTF32LE.bas) over the attached exe.

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=FileRead$(CL$())      ; read UTF-32 content into a buffer
  .if dword ptr [esi]!=0FEFFh   ; no BOM found!
        MsgBox 0, CL$(), "Not a UTF-32 file, sorry", MB_OK
  .else
        mov ecx, LastFileSize
        sar ecx, 1
        Let edi=New$(ecx)       ; create a buffer for UTF-16
        sar ecx, 1
        push edi
       .Repeat
                lodsd
                stosw
                dec ecx
       .Until Sign?
       pop edi
       FileWrite "test.txt", edi
       ShEx "test.txt"         ; open in your preferred editor
  .endif
EndOfCode
Title: Generate random integers and write them to a text file
Post by: jj2007 on January 16, 2020, 08:53:47 AM
Source and exe attached. This snippet generates a text file with integers.

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals total
  Init
  Dim MyDw() As DWORD
  mov ecx, Val(Input$("How many numbers: ", "1000000"))         ; suggest one Million
  mov total, ecx
  sar ecx, 4                                    ; divide by 16
  jle bye
  Open "O", #1, "numbers.txt"
  For_ ct=1 To ecx
        For_ ecx=0 To 15
                Print #1, Str$("%i ", Rand(500000)-250000)      ; generate numbers from -250000...249999
        Next
        Print #1
  Next
  Close #1
  NanoTimer()
  StringToArray FileRead$("Numbers.txt"), MyDw()        ; reload textfile and convert to numbers
  PrintLine NanoTimer$(), Str$(" for converting %i numbers", MyDw(?))
  NanoTimer()
  ArraySort MyDw()
  PrintLine NanoTimer$(), " for sorting them"
  For_ ecx=0 To 9                       ; show the smallest numbers
       PrintLine Str$("MyDw(%i)=", ecx), Str$(MyDw(ecx))
  Next
  PrintLine "..."
  For_ ecx=total-9 To total-1           ; show the biggest numbers
       PrintLine Str$("MyDw(%i)=", ecx), Str$(MyDw(ecx))
  Next
bye:
EndOfCode


Sample output (Intel Core i5):
How many numbers: 1000000
98 ms for converting 1000000 numbers
103 ms for sorting them
MyDw(0)=-250000
MyDw(1)=-249999
MyDw(2)=-249999
MyDw(3)=-249999
MyDw(4)=-249998
MyDw(5)=-249998
MyDw(6)=-249997
MyDw(7)=-249997
MyDw(8)=-249997
MyDw(9)=-249996
...
MyDw(999991)=249994
MyDw(999992)=249994
MyDw(999993)=249995
MyDw(999994)=249996
MyDw(999995)=249997
MyDw(999996)=249997
MyDw(999997)=249998
MyDw(999998)=249999
MyDw(999999)=249999
Title: Save frames of a GIF file
Post by: jj2007 on January 24, 2020, 12:08:35 PM
GuiParas equ "Save all frames of a GIF image to file", w300, h200
include \masm32\MasmBasic\Res\MbGui.asm         ; needs MasmBasic 24.1.2020 (http://masm32.com/board/index.php?topic=94.0)
GuiImageCallback MySave                         ; tell GuiImage to call MySave
Event Paint
  GuiImage wCL$(), fit                          ; load the image specified in the commandline (Unicode is allowed)
EndOfEvents
MySave: If_ Not signed eax<0 Then <SaveImageToFile Str$("frame_%i.gif", eax)>   ; saves current frame to frame_0...n.gif
  ret
GuiEnd


Project attached. Drag an animated *.gif file over the exe, then check its folder for the component files. The exe will also display jpg, bmp, png and tiff, but only multi-frame gif files will trigger the creation of the frame*.gif components. This works also with animated TIFF files, see second attachment, but the output will be *.gif components. No idea how to join them, though :cool:
Title: Image viewer
Post by: jj2007 on February 01, 2020, 03:31:52 PM
What's new?

- GuiImage (http://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1375) now respects the delays of frames in animated GIFs, and also stops looping if the GIF specifies a limit. Simple example (make sure you run it in a folder that contains images; source and exe attached):

include \masm32\MasmBasic\Res\MbGui.asm        ; MasmBasic version 1 Feb 2020 needed for building this code (http://masm32.com/board/index.php?topic=94.0)
GetFiles *.gif|*.jpg|*.png|*.jpeg              ; load the Files$() array
SortFiles                                      ; latest on top
GuiControl MyList, "listbox", Files$(), x=800, w=200   ; create a listbox to the right, 20% of width; use Files$() to fill it
GuiControl MyCanvas, "canvas", w=800, WS_THICKFRAME    ; create the canvas to paint on
GuiImageSpeed 50, 2000                         ; 50% speed, 2 seconds pause after an animation

Event CanvasPaint
  .if LbSel>=0
        GuiImage 99, fit                ; background image may be needed for animations with transparency
        GuiImage Files$(LbSel)          ; draw the selected image, use original size (or use fit as above)
  .else
        GuiTextBox 0, 0, 200, auto, "Click into the listbox to select a file", bcol RgbCol(255, 255, 255), font 40
  .endif
GuiEnd


- new CheckStackBalance macro:
include \masm32\MasmBasic\MasmBasic.inc
  Init

  CodeSize MyTest
  call MyTest
  useCsb=1 ; put 0 to see a crash

  Exit

  MyTest_s:
  MyTest proc
CheckStackBalance
PrintLine "Hello World"
pushf ; that's a word, right ;-)
pushad ; <<<<<<<<<<<<<<<< a bug! <<<<<<<<<<<
CheckStackBalance
ret
  MyTest endp
  MyTest_endp:
  CodeSize MyTest, echo
end start


If enabled via useCsb=1, it shows e.g. these lines, plus a MsgBox:

244     bytes for MyTest
Hello World
** line 16: 8 push instructions in excess - stack is 34 bytes off **


If disabled with useCsb=0, no code is generated but the output looks different:

18      bytes for MyTest
Hello World


Plus a "MsgBox" designed by Microsoft :tongue:

- the CodeSize macro may serve to calculate the size of a whole proc or a few instructions between the *_s: and *_endp: labels. In the CodeSize xx, echo variant, the size appears in the output window, and no extra code will be generated
Title: Find huge and old files on your disk
Post by: jj2007 on February 09, 2020, 07:17:03 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals backslash, pattern$
  Init
  .While 1
        PrintLine CrLf$, "Press Escape, Return to exit", CrLf$
        Let pattern$=Input$("What to search for: ", Cat$(CurDir$()+"*.*"))
        .Break .if !Len(eax)
        Cls
        Dim score() As DWORD
        GetFiles pattern$       ; .jpg|*.inc|*.pdf
       For_ ct=0 To eax-1
                xor ecx, ecx
                dec GfAgeHours(ct)
                .if !Sign?
                              shr eax, 2      ; more shifting = less importance for date
                              push eax
                              shr GfSize(ct), 7
                              pop edx
                              mul edx
                              shrd eax, edx, 12
                              xchg eax, ecx
                .endif
                mov score(ct), ecx
        Next
        ArraySort score(-), key() As DWORD, fill
        PrintLine CrLf$, "Size__", Tb$, "Date______  Time____    Path", String$(60, "_")
        fldz
        For_ ct=0 To score(?)-1
                mov ecx, key(ct)
                .if ct<=50
                                push GfSize(ecx)
                                fiadd stack
                                pop edx
               .endif
                .if ct<20
                                mov esi, Files$(ecx)
                                ; mov backslash, Rinstr(esi, "\")
                               PrintLine Str$("%_____i\t", GfSize(ecx)/1024/1024), GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Mid$(esi, backslash+1)
                .endif
        Next
        fmul FP4(1.0e-9)
        mov ecx, Cat$("\nDeleting the first 50 files in "+Left$(pattern$, Rinstr(pattern$, "\")-1)+" would free %3f GB of disk space")
        PrintLine Str$(#ecx, ST(0)v)
  .Endw
EndOfCode


Unzip the attachment to some folder and run the exe (or open the *.asc in RichMasm and hit F6). Typical output:
Size__  Date______  Time____    Path____________________________________________________________
     2  27.09.2013  02:01:00    C:\Masm32\OllyDbg\ollydbg.exe
     0  19.03.1998  07:28:18    C:\Masm32\bin\link.exe
     0  13.01.1995  05:10:00    C:\Masm32\bin\link16.exe
     1  10.01.2012  00:21:10    C:\Masm32\include\winextra.inc
     0  10.01.2012  00:21:10    C:\Masm32\include\windows.inc
     0  16.03.2000  15:20:48    C:\Masm32\bin\ml.EXE
     0  16.03.2000  15:20:48    C:\Masm32\bin\mlv615.EXE
     0  12.11.2011  08:04:41    C:\Masm32\examples\unicode_generic\diskfile\WININC.INC
     0  13.03.2004  16:30:08    C:\Masm32\examples\advanced\wrep\winequ.inc
     0  16.04.2011  19:09:37    C:\Masm32\bin\poasm.exe
     0  25.01.2010  13:18:04    C:\Masm32\bin\dumppe.exe
     0  22.12.2008  15:15:08    C:\Masm32\lib\msvcrt.000

Deleting the first 50 files in C:\Masm32 would free 0.0410 GB of disk space


So far, it just shows files, i.e. nothing will get deleted. Of course, it becomes more interesting if your \Masm32 folder is a little bit older. My message is Deleting the first 50 files in C:\Masm32 would free 16.8 GB of disk space :cool:

Here is another interesting folder:
Size__  Date______  Time____    Path____________________________________________________________
   272  23.04.2011  21:41:44    C:\Windows\Installer\21386cd2.msp
   189  28.03.2011  18:00:22    C:\Windows\Installer\42fec0e.msp
   164  28.03.2011  17:45:18    C:\Windows\Installer\42fec0d.msp
   114  27.07.2007  09:03:06    C:\Windows\Installer\21386a4c.msp
   378  01.09.2017  01:43:52    C:\Windows\Installer\30be8f0e.msi
   245  21.06.2016  05:45:27    C:\Windows\Installer\2ad6e39c.msi
   207  06.11.2015  16:00:20    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\SetupCache\v4.6.01055\NetFx_Full.mzz
    69  22.03.2010  19:36:56    C:\Windows\Installer\$PatchCache$\Managed\00004159FA0090400000000000F01FEC\14.0.4763\MSORES.DLL
    63  10.06.2009  23:02:16    C:\Windows\IME\IMESC5\DICTS\PINTLGT.IMD
    63  10.06.2009  23:02:16    C:\Windows\winsxs\amd64_microsoft-windows-i..e-trigramdictionary_31bf3856ad364e35_6.1.7600.16385_none_12d6b2e35
    55  22.07.2009  10:17:30    C:\Windows\Installer\$PatchCache$\Managed\1D763DBFF246FC747BB9B94EF83B0470\10.0.1600\ENG_RE_sqlservr_exe_64
    69  18.01.2012  02:24:38    C:\Windows\Installer\$PatchCache$\Managed\00004159FA0090400000000000F01FEC\14.0.7015\MSORES.DLL
    55  22.09.2011  21:07:34    C:\Windows\Installer\$PatchCache$\Managed\1D763DBFF246FC747BB9B94EF83B0470\10.3.5500\ENG_RE_sqlservr_exe_64
    37  17.12.2007  14:57:48    C:\Windows\Installer\27f64005.msi
    36  17.12.2007  14:57:48    C:\Windows\Installer\27f64006.msp
    43  11.06.2010  17:52:10    C:\Windows\Installer\42cdaff.msp
    96  21.06.2016  05:44:58    C:\Windows\Installer\2ad6e0ec.msp
    32  10.06.2009  22:43:23    C:\Windows\Fonts\mingliub.ttc
    32  10.06.2009  22:43:23    C:\Windows\winsxs\amd64_microsoft-windows-font-truetype-mingliub_31bf3856ad364e35_6.1.7600.16385_none_251699455
    77  20.09.2015  10:27:56    C:\Windows\Installer\$PatchCache$\Managed\00006109C10000000000000000F01FEC\16.0.4288\MSORES.DLL

Deleting the first 50 files in C:\Windows would free 3.83 GB of disk space
Title: Find *.xls but not *.xlsx files
Post by: jj2007 on March 02, 2020, 02:17:00 AM
Under the hood of GetFiles (http://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1056), FindFirstFile and FindNextFile are working. Unfortunately, for these API functions, *.xls and *.xlsx are just the same thing. Here is a workaround that filters unwanted *.xlsx files out - it sets the zero flag in a callback function thus telling GetFiles (http://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1056) not to include the file in the Files$() array:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
.code

cbGetFiles:                     ; the callback function
  .if wInstr(edi, ".xlsx")
        or ecx, -1              ; combined with the inc ecx below, this sets Zero?
  .endif
  inc ecx
  ret

  Init
  GfCallback cbGetFiles         ; define a callback function
  GetFiles *.xls
  SortFiles                     ; latest on top
  For_ ebx=0 To eax-1           ; print the results
       PrintLine Str$(GfSize(ebx)), Tb$, GfDate$(ebx), Spc2$, GfTime$(ebx), Tb$, Files$(ebx)
  Next
EndOfCode


Project attached.
Title: Adding two numbers
Post by: jj2007 on March 06, 2020, 01:47:38 AM
GuiParas equ "adding two numbers", w560, h84, icon Lens
include \masm32\MasmBasic\Res\MbGui.asm
GuiControl MyEdit, "edit", h=0+28, "1234+1000h", font -16:FW_SEMIBOLD
GuiControl MyStatusBar, "statusbar", "Change the number to see the sum in dec, hex and binary format", font -14:FW_MEDIUM
Event Command
  .if nCode==EN_CHANGE
        mov ecx, Win$(hMyEdit)          ; get the text from the edit control
        push Val(ecx)                   ; save first integer to stack
        and edx, 127                    ; get #chars used
        lea ecx, [ecx+edx+1]            ; skip the plus sign
        void Val(ecx)
        If_ edx==-127 Then xor eax, eax ; second value was invalid or empty
        pop ecx                         ; pop first value
        add ecx, eax                    ; sum
        SetWin$ hMyStatusBar=Str$("Sum is %i = ", ecx)+Hex$(ecx)+"h = "+Bin$(ecx)+"b"
  .endif
GuiEnd
Title: Factorials
Post by: jj2007 on April 07, 2020, 08:12:02 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals num:QWORD=1, num10:REAL10=1
  Init
  PrintLine "Factorials from 1!!!! to 25!!!!"
  For_ ct=1 To 25
        fild num
        fimul ct
        fistp num
        fld num10
        fimul ct
        fstp num10
        Print Str$(ct), Tb$, Str$(num)
        PrintLine At(40) Str$("%Jf", num10)
  Next
EndOfCode


Output (QWORD overflows already at n=21):
Factorials from 1! to 25!
1       1                               1.000000000000000000
2       2                               2.000000000000000000
3       6                               6.000000000000000000
4       24                              24.00000000000000000
...
18      6402373705728000                6402373705728000.000
19      121645100408832000              121645100408832000.0
20      2432902008176640000             2432902008176640000.
21      -9223372036854775808            5.109094217170944000e+19
22      -9223372036854775808            1.124000727777607680e+21
23      -9223372036854775808            2.585201673888497664e+22
24      -9223372036854775808            6.204484017332394394e+23
25      -9223372036854775808            1.551121004333098598e+25
Title: Where do my lib files sit?
Post by: jj2007 on April 23, 2020, 11:38:28 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals oldPos, ctDiff
  Init
  Cls
  GetFiles *.a
  For_ ecx=0 To eax-1
        mov esi, Files$(ecx)
        .if Rinstr(esi, "\")!=oldPos    ; take one from each folder
               mov oldPos, edx
                inc ctDiff
                PrintLine Str$(GfSize(ecx)), Tb$, GfDate$(ecx), Spc2$, GfTime$(ecx), Tb$, Files$(ecx)
        .endif
  Next
  Inkey Str$("\n%i different folders containing *.a files found", ctDiff)
EndOfCode


To test it, just run the exe in your FreeBasic folder. Sample output:
98954   16.03.2019  12:23:26    doc\Print_to_Pdf-master\version_1.1\libPrint2Pdf_32.a
45108   08.03.2019  19:51:06    doc\Print_to_Pdf-master\libPrint2Pdf32.a
647940  31.01.2016  14:47:37    Fb64\lib\freebasic\win64\libfb.a
21808   31.03.2018  17:27:29    Fb64\lib\libLinked_Lists.a
3028    11.08.2008  09:14:00    FbEdit\Projects\Addins\fbShowVars\addins\libfbshowvars.dll.a
38560   21.08.2007  12:00:04    FbEdit\Projects\Addins\fbShowVars\needed\freebasic\lib\win32\libdisasm.a
6256    21.08.2007  12:00:04    FbEdit\Projects\Addins\fbShowVars\sample\libshowvars.a
8918    05.11.2007  08:25:38    FbEdit\Projects\CustCtrl\FBEPictView\libFBEPictView.a
3890    13.05.2007  19:50:32    FbEdit\Projects\CustCtrl\FBEVideo\libFBEVideo.a
3980    13.05.2007  19:50:34    FbEdit\Projects\CustCtrl\FBEWeb\libFBEWeb.a
6256    31.12.2000  23:00:00    FbEdit\Projects\Samples\Debug\libshowvars.a
349806  22.09.2016  16:23:58    lib\pcre-839-static\win32\libpcre.a
24286   27.12.2010  17:47:09    lib\win32\Cairo\libcairo-gobject.dll.a
3658    31.01.2016  12:09:12    lib\win32\libaclui.dll.a
23214   01.04.2013  12:30:12    PngLib\libpnglib2.a
3028    16.12.2008  21:29:25    Projects\Addins\fbShowVars\addins\libfbshowvars.dll.a
38560   16.12.2008  21:29:26    Projects\Addins\fbShowVars\needed\freebasic\lib\win32\libdisasm.a
6256    16.12.2008  21:29:25    Projects\Addins\fbShowVars\sample\libshowvars.a
8918    03.11.2007  22:33:32    Projects\CustCtrl\FBEPictView\libFBEPictView.a
3890    23.08.2007  21:57:18    Projects\CustCtrl\FBEVideo\libFBEVideo.a
3980    23.08.2007  21:57:20    Projects\CustCtrl\FBEWeb\libFBEWeb.a
6256    23.08.2007  21:57:24    Projects\Samples\Debug\libshowvars.a
3658    31.01.2016  11:09:14    WinFBE_Suite\FreeBASIC-1.06.0\lib\win32\libaclui.dll.a
24456   25.03.2019  20:31:49    libminz_32.a

27 different folders containing *.a files found
Title: Draw two persons
Post by: jj2007 on May 23, 2020, 08:18:09 PM
GuiParas equ "Gdi+ is easy", w400, h300, b DarkGrey
include \masm32\MasmBasic\Res\MbGui.asm         ; *** Draw two persons - hit F6 to build & run ***
  GuiControl Sbar, "statusbar", "You can size the window"
  MakePath Head, Ellipse(150:180)      ; w:h
  MakePath Person, Polygon(180:160, 420:160, 500:400, 440:420, 380:250, 370:420, 450:750, 370:750, 300:500, 230:750, 160:750, 230:420, 220:250, 160:420, 100:400, 180:160)
  MakePen hPen, RgbCol(160, 0, 0, 255), width 9   ; semi transparent blue pen
  MakeBrush hBrushRed, RgbCol(255, 255, 0, 0)
  MakeBrush hBrushGreen, RgbCol(100, 0, 255, 0)
Event Paint
  GuiTextBox 99.9-100, 100.0-60, 98, auto, "Thanks for the inspiration, Nidud", bcol LiteYellow, font -14       ; -> post (http://masm32.com/board/index.php?topic=7000.msg93681#msg93681)
  GuiDraw Head, hPen/hBrushRed, 51.0, 13.0      ; big person
  GuiDraw Person, hPen/hBrushRed, 22.0, 6.0     ; x, y
  GuiDraw Head, hPen/hBrushGreen, 27.0, 8.0, 500, 500  ; small person
  GuiDraw Person, hPen/hBrushGreen, 0.0, 6.0, 900, 400  ; x, y, scale x, scale y
GuiEnd
Title: Start program only once
Post by: jj2007 on May 30, 2020, 09:02:06 AM
include \masm32\MasmBasic\MasmBasic.inc         ; Start a program just one time (http://masm32.com/board/index.php?topic=6483.msg93793#msg93793)
  Init
  Let esi=CL$(0)                             ; use the executable name as unique string
  .if rv(GlobalFindAtom, esi)
        MsgBox 0, Cat$(esi+" is already running"), "Sorry:", MB_OK or MB_TOPMOST
  .else
        push rv(GlobalAddAtom, esi)
        MsgBox 0, Cat$(esi+" successfully started"), "Yeah:", MB_OK or MB_TOPMOST
        call GlobalDeleteAtom
  .endif
EndOfCode
Title: Getting options from the commandline
Post by: jj2007 on October 03, 2020, 07:26:22 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  PrintLine "option 1=[", Trim$(Extract$(Cat$(CL$()+"/"), "/opt1", "/")), "]"  ; print the option
  Let esi="option 2=["+Trim$(Extract$(Cat$(CL$()+"/"), "/opt2", "/"))+"]"      ; assign to a string, then print it
  Print esi
EndOfCode

OPT_Arg1        /opt1 That's fun /opt2 No problem       ; the RichMasm way to test commandlines


Output:
option 1=[That's fun]
option 2=[No problem]
Title: Check 2MB source for a keyword
Post by: jj2007 on October 13, 2020, 09:36:12 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=FileRead$("\Masm32\include\Windows.inc")+FileRead$("\Masm32\include\WinExtra.inc")
  mov ebx, Len(esi)             ; 2045966 bytes
  PrintCpu 0
  REPEAT 3
        push 99
        xor edi, edi
        .Repeat
                NanoTimer()
                mov edx, ebx    ; FAST with mode 64 needs the size of the buffer in edx
                push Instr_(FAST, esi, "Duplicate include file winextra.inc", 64)
                add edi, NanoTimer(µs)
                pop edx
               dec stack
        .Until Sign?
        pop eax                 ; stack correction
        If_ Not edx Then Print "String not found - "
        Print Str$("average: %i µs\n", edi/100)
  ENDM
EndOfCode


Typical output:
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
average: 495 µs
average: 492 µs
average: 506 µs
Title: Context help demo
Post by: jj2007 on December 29, 2020, 04:51:42 AM
Caballero inspired this little demo (http://masm32.com/board/index.php?topic=7109.msg99369#msg99369) showing how the old-fashioned question mark next to the close box works. Source + exe attached.

GuiParas equ "Context help demo", w500, h320, icon Star, b GreenBlue, s WS_SYSMENU or WS_CAPTION or WS_THICKFRAME
GuiMenu equ @File, &Open, &Save, -, E&xit, @Edit, Undo, Copy, Paste ; define a menu (only Open is implemented)
GuiWsExMain equ WS_EX_CONTEXTHELP
include \masm32\MasmBasic\Res\MbGui.asm ; hit F6 to build this template
  GuiControl RichEdit, "richedit", wCL$(), h900, w1000-60
  GuiControl PoorEdit, "edit", "Click into the question mark in the caption, then down here", y900, h100, w1000-60
  GuiControl B1, "button", x=1000-60, h=0+30, w=0+60, "Button 1"
  GuiControl B2, "button", x=1000-60, y=0+33, h=0+30, w=0+60, "Button 2"
  GuiControl B3, "button", x=1000-60, y=0+66, h=0+30, w=0+60, "Button 3"
  GuiControl Status, "statusbar", wCat$(wDate$+", "+wTime$) ; GuiControls require Unicode
  StringToArray cfm$("richedit\nedit control\n1st button\n2nd button\n3rd button\nstatus bar\nlistbox"), help$()
  GuiControl MyList, "listbox", help$(), x=1000-60, w=0+60, y=0+100, h=1000-100
Event Message
  .if uMsg_==WM_HELP
mov ecx, lParam_
mov ecx, [ecx.HELPINFO.iCtrlId]
.if signed ecx>40
sub ecx, 41
SetWin$ hStatus="You clicked into the "+help$(ecx)
.endif
  .endif
Event Menu
  Switch_ MenuID
  Case_ 0 ; menu entries start with 0
  If_ FileOpen$("Rich sources=*.asc|All sauces=*.as?;*.inc|Resources=*.rc") Then SetWin$ hRichEdit=FileRead$(FileOpen$())
  Endsw_
GuiEnd
Title: Re: Miscellaneous snippets
Post by: Richard on January 05, 2021, 02:51:40 PM
@jj2007   re reply #2

As I have finally a workable "bare metal" (no WINDOWS whatsoever) environment - where I boot off a usb stick which is now the C:\  drive -
I wish to establish whether or not FreeBASIC DOS version can work with in-line assembly (prefer DOS version at this stage but will also consider windows version which I have used a bit).

Would you be able to supply a very simple FreeBASIC program that uses in-line assembly and I can verify if it is possible? Also advise precisely all the Command Line Switches for fbc.exe sampleprogram.exe that would be needed. I will try to compare things (code size, timings, etc) to calling an external program (that does what the in-line assembly does) via a SHELL like command from within FreeBASIC program.

My laptop is intel i7 x64 with 32 GByte RAM.
Title: Re: Miscellaneous snippets
Post by: jj2007 on January 05, 2021, 10:52:02 PM
Quote from: Richard on January 05, 2021, 02:51:40 PMI wish to establish whether or not FreeBASIC DOS version can work with in-line assembly (prefer DOS version at this stage but will also consider windows version which I have used a bit).

Would you be able to supply a very simple FreeBASIC program that uses in-line assembly

Richard,

That is a question for the FreeBasic forum (https://www.freebasic.net/forum/search.php?search_id=newposts). I have never touched FB for DOS, so I cannot give you advice on that, sorry...
Title: A 14 lines editor
Post by: jj2007 on January 15, 2021, 12:34:06 PM
Note this is the bare minimum - just a demo. No checks, no bells and whistles. Use at your own risk.
GuiParas equ "A full-fledged raw Win32 GUI", icon Ball, b Turquoise ; title, icon, background
GuiMenu equ @File, &Open, &Save, -, E&xit, @Edit, Undo, Copy, Paste ; define a menu (only Open & Save are implemented)
include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl RichEdit, "richedit", CL$() ; load what you find in the commandline
  GuiControl Status, "statusbar"
Event Menu
  Switch_ MenuID
  Case_ 0 ; Open (menu entries start with 0)
  If_ FileOpen$("FB sources=*.bas|Includes=*.bi;*.inc|Resources=*.rc|All files=*.*") Then SetWin$ hRichEdit=FileRead$(FileOpen$())
  Case_ 1 ; Save
  FileWrite CL$(), stream:hRichEdit ; save contents of the RichEdit control
  SetWin$ hStatus=CL$()+" was saved"
  Endsw_
GuiEnd
OPT_Arg1 ?:\Masm32\MasmBasic\AscUser\OpenSaveFB.asc ; for testing with RichMasm
Title: Convert tabs to spaces
Post by: jj2007 on February 19, 2021, 10:17:35 AM
Just drag the tabbish source over the attached exe.

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi=FileRead$(CL$())
  Let esi=Replace$(esi, Tb$, Space$(8)))
  FileWrite "NoMoreTabs.bas", esi
  ShEx "NoMoreTabs.bas"         ; launch it with ShellExecuteEx
EndOfCode


(I don't recommend it, though - I love my tabs and would never exchange them for spaces :badgrin:)
Title: Size of Chinese text, Utf-8 vs Utf-16
Post by: jj2007 on February 26, 2021, 08:19:46 PM
include \masm32\MasmBasic\MasmBasic.inc
  Init
  Let esi=FileRead$(99)         ; WarAndPeaceChinese.txt from resource
  Let edi=Utf8$(esi)
  deb 4, "wLen", wLen(esi)      ; Utf-16 chars
  deb 4, "uLen", uLen(edi)      ; Utf-8 chars
  deb 4, "Len", Len(edi)        ; bytes
  uMsgBox 0, edi, "Chinese text as Utf-8:", MB_OK
  wMsgBox 0, esi, "Chinese text as Utf-16:", MB_OK
EndOfCode
Rsrc
#include "resource.h"
IDI_APPLICATION ICON    "\\Masm32\\MasmBasic\\icons\\Globe.ico"         // Calc, Disk, Editor, Eye, Globe, MasmBasic, Smiley
01 RT_MANIFEST         "\\Masm32\\MasmBasic\\Res\\XpManifest.xml"
99 RCDATA      "WarAndPeaceChinese.txt"
Rsrc


wLen    eax             526
uLen    eax             525
Len     eax             1449


So that is 1449 vs 2*526 bytes, which means that Utf-8 needs 37.7% more space in memory.
When saving the Utf-8 file, and zipping both together, the packed sizes differ by only 5.5%, though.

Project attached, requires MasmBasic. (https://www.jj2007.eu/Masm32_Tips_Tricks_and_Traps.htm)
Title: Compound chars, Utf-8 vs Utf-16
Post by: jj2007 on February 26, 2021, 09:13:25 PM
Lots of people argue on the web whether Utf-16 is "harmful", and what are the pros and cons of Utf-8 vs Utf-16. As a matter of fact, both work just fine, as demonstrated below with two compound characters that are not in the Basic Multilingual Plane. For Chinese text, the space requirements are very similar, as demonstrated above, for English text, Utf-8 clearly wins, of course.

include \masm32\MasmBasic\MasmBasic.inc
  Init
  Cls
  Let edi="aaa  שָׁ  bbb  𝕥  ccc"         ; two compound characters with 6 and 4 bytes in Utf-8
  PrintLine "Utf-8:", CrLf$, HexDump$(edi, 32)
  Let esi=wRec$(edi)            ; convert to Utf-16
  PrintLine "Utf-16:", CrLf$, HexDump$(esi, 48)
  if 0  ; activate if needed
        lea ecx, [2*wLen(esi)]
        FileWrite "compound.txt", esi, ecx
  endif
  uMsgBox 0, edi, "Utf-8:", MB_OK
  wMsgBox 0, esi, "Utf-16:", MB_OK
EndOfCode


Output (20 = 32 dec are the spaces):
Utf-8:
002BD2B0  61 61 61 20 20 D7 A9 D7 81 D6 B8 20 20 62 62 62 aaa  שָׁ  bbb
002BD2C0  20 20 F0 9D 95 A5 20 20 63 63 63 00 00 00 00 00   𝕥  ccc.....

Utf-16:
0028DEF0  61 00 61 00 61 00 20 00 20 00 E9 05 C1 05 B8 05 a.a.a. . .�.�.�.
0028DF00  20 00 20 00 62 00 62 00 62 00 20 00 20 00 35 D8  . .b.b.b. . .5�
0028DF10  65 DD 20 00 20 00 63 00 63 00 63 00 00 00 00 00 e� . .c.c.c.....
Title: CoVid-19 stats
Post by: jj2007 on March 21, 2021, 01:02:49 AM
Data come from the Allgemeine Ortskrankenkasse (AOK) Berlin (https://www.aok.de/pk/nordost/inhalt/krankschreibungs-analyse-der-aok-nordost-fuer-berlin/). The graph shows how many employees went on sick leave because they tested CoVid-19 positive.

GuiParas equ "Covid by profession", w1200, h630, b Grey, icon Plot
include \masm32\MasmBasic\Res\MbGui.asm
  SetGlobals language=2 ; default is English
  GuiControl MyCanvas, "canvas"
  Recall 99, L$(), tab ; res 99 = CovidAOK.tab
Event CanvasPaint
  For_ ct=0 To L$(?)-2
sar Val(L$(ct, 0)), 2 ; /4
xchg eax, ecx
GuiTextBox 20, ct*30+12, ecx, 26, Cat$(" "+L$(ct, language+1)), fcol White, bcol Red, DT_LEFT
  Next
  GuiTextBox 800, 200, 200, auto, L$(ct, language+1), fcol Black, bcol LiteYellow, DT_WORDBREAK, font -20:FW_BOLD
Event Key
  Switch_ VKey
  Case_ VK_D: Clr language ; German
  Case_ VK_I: m2m language, 1 ; Italian
  Case_ VK_E: m2m language, 2 ; English
  Case_ VK_F: m2m language, 3 ; French
  Endsw_
  GuiRefresh
EndOfCode


(http://www.jj2007.eu/pics/CovidAOK.png)
Title: Grabbing the output of a launched program
Post by: jj2007 on March 21, 2021, 11:12:03 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  StringToArray Launch$("cmd.exe /c dir *.asm"), f$()   ; use Launch$ (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1047) to grab the output, translate into a string array
  For_ each esi in f$(): <Let f$(ForNextCounter)=Mid$(esi, 35)>  ; eliminate date, time, size, e.g. 27.08.17  23:34            16,527 SortAnIntegerArray.asm
  QSort f$()
  For_ each esi in f$(): PrintLine esi
EndOfCode


An alternative:
include \masm32\MasmBasic\MasmBasic.inc
  Init
  StringToArray Launch$("cmd.exe /c dir /O-D *.asm"), f$() ; use Launch$ to grab the output, translate into a string array
  Delete f$(0), 5 ; eliminate the five strings at the beginning of a dir command
  Delete f$(f$(?)-2), 2 ; eliminate the two trailing strings
  For_ each esi in f$(): PrintLine esi ; print all files
EndOfCode


Output:
20.03.21  18:53               873 CovidAOK.asm
19.03.21  15:53            12,246 CheckNewPosts.asm
...
29.06.13  00:59             4,687 Win64_3e.asm
25.06.11  11:03             4,276 cids.asm
Title: Put environment variables to string array
Post by: jj2007 on March 22, 2021, 10:39:01 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  GetRegArray "HKLM\SYSTEM\ControlSet001\Control\Session Manager\Environment", MyEnv$(), MyData$()
  QSortMode 1, 0, DataIndex() As DWORD  ; case-insensitive, don't skip leading spaces
  QSort MyEnv$()                        ; sort by name of key
  Open "O", #1, "Environment.tab"
  For_ each esi in MyEnv$(): <PrintLine #1, esi, Tb$, MyData$(DataIndex(ForNextCounter))>
  Close #1
  ShEx "Environment.tab"
EndOfCode


Output (shortened):
ComSpec %SystemRoot%\system32\cmd.exe
DXSDK_DIR       C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\
FP_NO_HOST_CHECK        NO
...
VS140COMNTOOLS  C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\
windir  %SystemRoot%


Attached a version that writes the variables to a tab-delimited file and opens it in your default *.tab viewer (which might be MS Excel, for example).
Title: GetFiles for batch files
Post by: jj2007 on April 03, 2021, 11:52:11 PM
The dir command is lousy (https://stackoverflow.com/questions/11215702/cmd-dir-b-s-plus-date), but fortunately we have a handy MasmBasic command: GetFiles (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1056) :thumbsup:

This little proggie should be put into a batch file e.g. as
\Masm32\bin\VS14\ml64.exe /c /Zp8 /Zi /Zd /Zf %1
echo ----------- assembly done --------------------
echo.
\Masm32\bin\VS14\link.exe /subsystem:console /entry:start /debug %~dpn1.obj /out:%~dpn164.exe
echo.
\Masm32\MasmBasic\Res\GetFiles %~dpn1* -time -age:2


Here is the (shortened) output for the source short.asm:
Microsoft (R) Macro Assembler (x64) Version 14.00.24210.0
...
----------- assembly done --------------------

Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

----- files created 14:50:18
389120  03.04.2021  14:50:18    Short64.pdb
14336   03.04.2021  14:50:18    Short64.exe
77928   03.04.2021  14:50:18    Short64.ilk
309334  03.04.2021  14:50:18    Short.obj


The arguments:
-time show the current time as ----- files created 14:50:18 (see above)
-age:2 show only files that are less than 2 seconds old (i.e. ignore older stuff)


Source & exe attached.
Title: Encrypt and decrypt an archive
Post by: jj2007 on October 11, 2021, 11:23:12 AM
*** Use at your own risk - make a copy of the zip archive before testing this; warning: doesn't work with filenames containing spaces (I still have to find out why) ***

To encrypt:
- Drag a zip archive over the attached exe
- Type a 4-letter password and hit Return

To decrypt:
- Drag the *.encrypted file over the attached exe
- Type the 4-letter password and hit Return

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let ebx=Input$("Gimme the seed: ", "abcd")
  Rand(seed:ebx)                        ; use e.g. "abcd" as seed (4 letters)
  Let esi=CL$()                             ; get file name from the commandline
  Let edi=FileRead$(esi)        ; put file content into a buffer
  .if Instr_(esi, ".zip")
        ; **** we got an archive - let's encrypt it: *******
       push edi                                ; save pointer to the buffer
       For_ ecx=0 To LastFileSize-1 Step 4
                xor [edi+ecx], Rand(-1)         ; xor buffer content with random dword
       Next
        pop edi                                 ; restore start of buffer
       Let esi=Left$(esi, Rinstr(esi, "."))+"encrypted"
        FileWrite esi, edi, LastFileSize        ; save xor'ed content
  .else
        ; **** we got an encrypted archive - let's read it back: *******
       Let edi=FileRead$(esi)
        push edi
       For_ ecx=0 To LastFileSize-1 Step 4
                xor [edi+ecx], Rand(-1)         ; reverse everything...
       Next
        pop edi
       Let esi=Left$(esi, Rinstr(esi, "."))+"zip"
        FileWrite esi, edi, LastFileSize        ; save xor'ed content
       ShEx esi                        ; open the archive with ShellExecute
  .endif
EndOfCode
Title: Re: Miscellaneous snippets
Post by: hutch-- on October 17, 2021, 05:16:34 PM
 :biggrin:

Cheat, rename the file with underscores for the spaces then rename the results to whatever you need.  :icon_idea:
Title: BigNum Ascii to Real routine
Post by: jj2007 on November 29, 2021, 04:54:19 AM
Just for fun

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Let esi="123456789012345678901234567890123456789012345678901234567890"
  push eax                              ; create a DWORD slot
  xor ecx, ecx
  or edx, -1
  fld FP10(10.0)                        ; for multiplication by 10
  fldz
  .While 1
       movzx eax, byte ptr [esi+ecx]   ; "1"
       .Break .if eax<"."
       .if Zero?
               mov edx, ecx    ; store position of the dot
       .else
               and eax, 15     ; "1"->1
               mov [esp], eax
               fiadd dword ptr [esp]   ; add 1 to current ST(0)
               fmul ST, ST(1)  ; multiply by 10
       .endif
       inc ecx                 ; advance position in string
  .Endw
  inc edx
  .if !Zero?
       sub ecx, edx
       void Exp10(ecx)         ; 10^position of dot
       fdiv                            ; result/(10^position of dot)
  .endif
  fxch
  fstp st
  Inkey Str$("Result: %Jf", ST(0)v)
  pop eax                               ; balance the stack
EndOfCode
Title: Magic numbers
Post by: jj2007 on December 07, 2021, 08:37:15 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  fld1
  fld FP10(0.00998001)
  fdiv
  PrintLine Str$("Result=%Jf", ST(0)v)
EndOfCode
Title: Scintilla editor
Post by: jj2007 on January 08, 2022, 04:23:06 AM
Just for fun, a full-fledged Scintilla editor in five lines (use at your own risk):

include \masm32\MasmBasic\Res\MbGui.asm ; OPT_Icon Editor
  GuiControl MySci, "scintilla", font 14:"Times New Roman", Cat$(FileRead$(CL$()))
Event Close
  If_ <Alert("Save file?", "bye", MB_YESNO)>==IDYES Then FileWrite CL$(), Win$(hMySci) ; save it, or don't...
GuiEnd


P.S.: ScintillaPath equ <"\Masm32\wscite\SciLexer.dll">; drag a text file over the executable.
Title: Print 1000x "Masm32" without a loop
Post by: jj2007 on January 17, 2022, 11:04:07 PM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Inkey Replace$(String$(1000, "x"), "x", cfm$("Hello Masm32\n")), "bye"
EndOfCode


That was easy, no?  :tongue:
Title: Reading doubles from an array
Post by: jj2007 on January 19, 2022, 04:40:42 AM
include \masm32\MasmBasic\MasmBasic.inc
  SetGlobals REAL8 min8, max8
  Init
  PrintCpu 0
  elements=2000000              ; two Million elements
  Dim MyReal8() As REAL8
  For_ ct=0 To 19
        .if !Exist("MyReals.dat") || ct<5       ; measure creation times for the first 5
                NanoTimer()
                For_ ecx=0 To elements-1
                    Rand(-100, 100, MyReal8(ecx))   ; create a random number between -100 and +100 (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1030)
                Next
                PrintLine Str$("Creating an array of %i random doubles took ", ecx), NanoTimer$()
                ArrayStore "MyReals.dat", MyReal8()
        .endif
        NanoTimer()
        ArrayRead MyReal8(), "MyReals.dat"      ; read array from disk
        ArrayMinMax MyReal8(), min8, max8       ; assign min+max to two variables
        PrintLine Str$("Reading and getting min=%7f", min8), Str$(" and max=%7f took ", max8), NanoTimer$()
  Next
  Inkey "hit any key"
EndOfCode


Output:
Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
Creating an array of 2000000 random doubles took 83 ms
Reading and getting min=-99.99998 and max=99.99964 took 29 ms
Creating an array of 2000000 random doubles took 37 ms
Reading and getting min=-99.99989 and max=100.00000 took 43 ms
Creating an array of 2000000 random doubles took 39 ms
Reading and getting min=-99.99983 and max=99.99999 took 31 ms
Creating an array of 2000000 random doubles took 38 ms
Reading and getting min=-99.99996 and max=99.99998 took 32 ms
Creating an array of 2000000 random doubles took 38 ms
Reading and getting min=-99.99998 and max=99.99991 took 28 ms
Reading and getting min=-99.99998 and max=99.99991 took 27 ms
Reading and getting min=-99.99998 and max=99.99991 took 26 ms
Reading and getting min=-99.99998 and max=99.99991 took 27 ms
Reading and getting min=-99.99998 and max=99.99991 took 26 ms
Reading and getting min=-99.99998 and max=99.99991 took 27 ms
Reading and getting min=-99.99998 and max=99.99991 took 28 ms
Reading and getting min=-99.99998 and max=99.99991 took 25 ms
Reading and getting min=-99.99998 and max=99.99991 took 29 ms
Reading and getting min=-99.99998 and max=99.99991 took 29 ms
Reading and getting min=-99.99998 and max=99.99991 took 27 ms
Reading and getting min=-99.99998 and max=99.99991 took 31 ms
Reading and getting min=-99.99998 and max=99.99991 took 29 ms
Reading and getting min=-99.99998 and max=99.99991 took 28 ms
Reading and getting min=-99.99998 and max=99.99991 took 30 ms
Reading and getting min=-99.99998 and max=99.99991 took 29 ms


See also GB32 forum (https://gb32.proboards.com/thread/431/fast-basic-when-compared-basics)
Title: Re: Miscellaneous snippets
Post by: jj2007 on February 02, 2022, 08:10:25 AM
Some benchmarks for GB32 (https://gb32.proboards.com/thread/431/fast-basic-when-compared-basics?page=2)
Title: Re: Miscellaneous snippets
Post by: HSE on February 02, 2022, 08:18:38 AM
Hi JJ!

Where are your benmarchs of GB32?
Title: Re: Miscellaneous snippets
Post by: jj2007 on February 02, 2022, 08:43:23 AM
Embedded in the source. The code is based on scalion's alias Nicolas Rey's tests (https://gb32.proboards.com/thread/431/fast-basic-when-compared-basics?page=2).

QuoteThe program consist in 4 test :

Test 1 "Init" - Initialisation of 10000 item of string array with a letter followed by numbers.
Test 2 "Swap" - Swap all items one time with another (not sorting) ->  49 995 000 swaps.
Test 3 "Mid" - Concat each 9999 first items with 2 parts of item+1 : mid(a(i+1),2) + mid(a(i+1),1,1)
Test 4 "Sort" - Sort ascending the array.
Title: Re: Miscellaneous snippets
Post by: HSE on February 02, 2022, 08:52:33 AM
Perfect. Thanks  :thumbsup:
Title: Get drive types
Post by: jj2007 on February 04, 2022, 04:22:41 AM
include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  SetGlobals buffer[40]:BYTE
  Init
  lea edi, buffer
  invoke GetLogicalDriveStrings, 40, edi
  ; Print HexDump$(edi, 32)
  lea esi, [edi-2]             ; to compensate leading 2*inc
  .While 1
        inc esi
        inc esi
        m2m edx, 32             ; len of buffer
        .Break .if !Instr_(FAST, esi, ":\", 2 or 64)    ; 64=len in edx, 2=ignore case of first char
        lea esi, [eax-1]        ; put esi on the drive letter
        xchg rv(GetDriveType, esi), ecx
        .if Choose(ecx, "unknown", "no root", "removable", "fixed", "remote", "cdrom", "ramdisk")==ChooseString         ; *)
                PrintLine esi, " is type ", eax         ; Str$(" (value %i)", ecx)
       .else
                PrintLine "Drive ", esi, Str$(" is type %i", ecx)
        .endif
  .Endw
EndOfCode

*):
unknown         equ 0
no root         equ 1
DRIVE_REMOVABLE equ 2
DRIVE_FIXED     equ 3
DRIVE_REMOTE    equ 4
DRIVE_CDROM     equ 5
DRIVE_RAMDISK   equ 6


C:\ is type fixed
D:\ is type cdrom
E:\ is type removable
J:\ is type fixed
Title: Convert binary file to dq 123, 456, 789...
Post by: jj2007 on April 12, 2022, 11:24:18 PM
Just for fun :biggrin:

include \masm32\MasmBasic\MasmBasic.inc         ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  MbHexDumpLen=819200           ; let's be generous (default is 8192 bytes)
  Let esi=FileRead$(CL$())      ; read the file supplied in the commandline
  FileWrite "~testTmp.asm", HexDump$(esi, LastFileSize, dq)     ; use QWORD format
  ShEx "~testTmp.asm"           ; open in your IDE
EndOfCode


Usage: drag any executable (any file, actually) over bin2dq.exe

Output:
.DATA
hdBytes=49152
hdStart LABEL BYTE
.radix 16
dq 00000000300905A4D, 00000FFFF00000004, 000000000000000B8, 00000000000000040, 00000000000000000, 00000000000000000, 00000000000000000, 00000008000000000
dq 0CD09B4000EBA1F0E, 0685421CD4C01B821, 072676F7270207369, 06F6E6E6163206D61, 06E75722065622074, 020534F44206E6920, 00A0D0D2E65646F6D, 00000000000000024
...
dq 00D3E796C626D6573, 0000000000000000A, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000
dq 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000
dq 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000, 00000000000000000
.radix 10
.code
; FileWrite "test.exe", offset hdStart, hdBytes


P.S., to test your result, you can use, for example:

include \masm32\MasmBasic\MasmBasic.inc
include ~testTmp.asm

  Init
  FileWrite "bin2test.exe", offset hdStart, hdBytes
  Launch "bin2test.exe"
EndOfCode


If you prefer pure Masm32 SDK for testing, use this:

include \masm32\include\masm32rt.inc
include ~testTmp.asm

.code
start:
  invoke write_disk_file, chr$("bin2test.exe"), offset hdStart, hdBytes  ; re-create the exe
  invoke WinExec, chr$("bin2test.exe"), SW_SHOW
  exit
end start
Title: Buttons
Post by: jj2007 on August 15, 2022, 06:22:16 AM
Attached a program I am just working on, with several different kinds of buttons.

What is interesting: It behaves differently on Win 7 and Win 10. On the latter OS, some of the buttons receive up to 8 WM_PAINT messages in a row. Something is seriously wrong, and I am trying to find out what. It might have to do with a different behaviour of the CDDS_* messages, but I am not yet sure. I will keep you posted.
Title: Re: Buttons
Post by: quarantined on August 15, 2022, 06:33:46 AM
Quote from: jj2007 on August 15, 2022, 06:22:16 AM
Something is seriously wrong, and I am trying to find out what....

Thanks, but what I posted in the Campus is not supposed to act like a button exactly. It behaves like I intended it to.  :cool:
Title: Re: Miscellaneous snippets
Post by: NoCforMe on August 15, 2022, 08:08:06 AM
Well, that's OK. There's no law that says you can't make a static control behave enough like a button to suit your purposes. You won't get a knock on your door in the middle of the night from the Coding Police.
Title: Tiny calculator
Post by: jj2007 on August 29, 2022, 07:52:26 PM
Just for fun - project attached. TinyCalcV2.zip is an advanced version with hex and binary display. It will accept most common number formats as input.

GuiParas equ "Tiny calculator", w200, h130, m4, b LiteBlueGreen ; width+height, margins, background colour
include \masm32\MasmBasic\Res\MbGui.asm
  GuiControl Calc, "Edit", bcol LiteYellow, w700, fcol Black, font -14, h0+32 ; colours & fonts have no effect with rtf files
  GuiControl Go, "button", "-!!> clipboard", x700, w300, h0+32, bcol LiteYellow
  GuiControl Status, "statusbar", "Type a formula"
  SetGlobals Result:REAL10, res$
Event Command
  .if MenuID==Go && nCode==BN_CLICKED
SetClip$=res$
invoke SendMessage, hWnd_, WM_CLOSE, 0, 0
  .elseif MenuID==Calc && nCode==EN_CHANGE
xor ecx, ecx
SetWin$ hStatus=0
mov esi, Win$(hCalc)
.if Instr_(esi, "+")
inc ecx
.else
.if Instr_(esi, "-")
inc ecx
inc ecx
.else
.if Instr_(esi, "*")
dec ecx
.else
.if Instr_(esi, "/")
dec ecx
dec ecx
.endif
.endif
.endif
.endif
.if ecx
mov byte ptr [eax], 0 ; separate left and right halves
inc eax
MovVal ST(0), eax ; right half of expression
.if edx && edx<20
MovVal ST(0), esi
Switch_ ecx
Case_ 1: fadd
Case_ 2: fsubr
Case_ -1: fmul
Case_ -2: fdivr
Endsw_
fstp Result
Let res$=Str$(Result)
xchg eax, ecx
push ecx
add ecx, Len(ecx)
.Repeat
dec ecx
.Until byte ptr [ecx]!="0"
mov byte ptr [ecx+2], 0
pop eax
SetWin$ hStatus=Cat$("Result="+res$)
.endif
.endif
  .endif
GuiEnd
Title: Tiny calculator
Post by: jj2007 on August 31, 2022, 07:59:58 PM
This grew quickly, the source is now a whopping 149 lines :biggrin:

Version 3 has a tooltip, knows about 2**3=8 and accepts PI as first parameter. Enjoy :biggrin:

(http://www.jj2007.eu/pics/TinyCalc.png)

P.S.: Binary result and bit descriptor for e.g. 123*456 look like this:

1101101100011000
5432109876543210

It can be helpful to see which bits are set.
Title: Re: Miscellaneous snippets
Post by: jj2007 on September 09, 2023, 08:43:43 PM
Kuron posted a coded message (https://masm32.com/board/index.php?msg=123620), here is how to decipher the text:
include \masm32\MasmBasic\MasmBasic.inc
  Init
  Let esi=Replace$("01010010 01001001 01010000 00100000 01001000 01110101 01110100 01100011 01101000 00101110 00100000 01011001 01101111 01110101 00100000 01110111 01101001 01101100 01101100 00100000 01000010 01100101 00100000 01001101 01101001 01110011 01110011 01100101 01100100 00100001 ", " ", Chr$("b", 13, 10))
  Let edi=""
  .While 1
    .Break .if Val(esi)==-127    ; -127 flags "invalid string"
    and edx, 15    ; isolate #characters used
    add esi, edx
    Let edi=edi+Chr$(eax)
  .Endw
  MsgBox 0, edi, "A message from Kuron:", MB_OK
EndOfCode

Let esi=Replace$ (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1079)("01010010 ... 00100001 ", " ", Chr$("b", 13, 10)) translates the string in esi to a valid format suitable for Val (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1202)():
01010010b
01001001b
01010000b
00100000b
01001000b
01110101b
01110100b
01100011b
01101000b
00101110b
00100000b
01011001b
01101111b
01110101b
00100000b
01110111b
01101001b
01101100b
01101100b
00100000b
01000010b
01100101b
00100000b
01001101b
01101001b
01110011b
01110011b
01100101b
01100100b
00100001b
Title: Large colourful icons
Post by: jj2007 on September 15, 2023, 07:53:42 AM
Here is an example of a badly documented MasmBasic function:

include \masm32\MasmBasic\MasmBasic.inc
  Init
  DlgDefine "Ida is cute", 0, 0, 60, 62
  DlgControl dcStatic, "Ida.ico", SS_ICON, 0, 0
  DlgShow
EndOfCode

Project attached - extract all files to a folder, then run the exe (or build it with RichMasm).
Title: Re: Miscellaneous snippets
Post by: Caché GB on September 15, 2023, 08:30:34 AM
Hi JJ

I am always willing to learn. As I have told you a few times, I have learnt to much from you.
However it would be quicker for me to drop your .exe into IDA to try and find out what is giong
on then to waddle through a billion lines of MasmBasic's macros.

So maybe a pure MASM demo would be nice.

Thanks.
Title: Re: Miscellaneous snippets
Post by: jj2007 on September 15, 2023, 08:42:37 AM
Quote from: Caché GB on September 15, 2023, 08:30:34 AMHi JJ

I am always willing to learn. As I have told you a few times, I have learnt to much from you.
However it would be quicker for me to drop your .exe into IDA to try and find out what is giong
on then to waddle through a billion lines of MasmBasic's macros.

So maybe a pure MASM demo would be nice.

Thanks.

I would probably have shown how it's done in Win32, but an overly zealous moderator killed my desire to be kind, sorry.

Maybe tomorrow.

Quote from: jj2007 on September 15, 2023, 06:17:00 AM
Quote from: NoCforMe on September 15, 2023, 06:10:01 AMThe two are identical. But Jochen, these are 16x16 icons.

Yes and no. It's a 128x128 icon, but Windows scales it down to 16x16 to let it fit into the caption. And it scales it down to 32x32 if you use Alt Tab.

I'd like to see one example where Windows uses the full 128x128. And don't come up with an icon editor, because I would consider that cheating. I mean an actual use of this icon beyond 32x32.

#EDIT# This kind of squabbling is not helpful to the OP. Not in the Campus, please.
Title: Re: Miscellaneous snippets
Post by: Caché GB on September 15, 2023, 09:50:00 AM
Hi JJ

No worries.

Incidentally, how do we get the icons of the two apps on the right to behave
like the four on the left when Explorer is in Extra Large Icons View.


(https://i.postimg.cc/9wTm5CLX/Large-Icons.jpg) (https://postimg.cc/9wTm5CLX)
Title: Re: Miscellaneous snippets
Post by: jj2007 on September 15, 2023, 10:34:57 PM
Good question :thumbsup:

WinMain, wc is WNDCLASSEX:
    mov wc.hIcon, rv(LoadImage, eax, IDI_APPLICATION, IMAGE_ICON, 0, 0, 0)
    mov wc.hIcon, rv(LoadIcon, eax, IDI_APPLICATION)

Both work, but they yield the same result. In contrast, as mentioned here (https://masm32.com/board/index.php?msg=123898), LoadImage behaves much better with a static control. Demo attached - you can actually size it!
Title: Re: Miscellaneous snippets
Post by: Caché GB on September 17, 2023, 10:26:04 PM
Hi JJ

The only way I've bean able to achieve a solution to this Extra Large Icons View quetion.

1. The icon must be a 256x256 bmp or png. (To reduce binary bloatware, use png),
2. If this 256x256 icon is in an ICON GROUP, it mush be the first icon in the group.
3  This icon / icon group's Resource ID must be the lowest value (numeral) in the
   Resource File's (*.rc) ICON listings.

What makes testing cumbersome is that Windows Explorer builds an icon caché. Therefore even if you
change the icon that Windows Explorer uses to display your app's Icon, the first icon you weiwed
that *.exe file with is the one that will be displayed. Until you, a) restart your PC, b) restart
Windows Explorer or delete Windows Explorer's icon caché file (Not recomended).

To avoid doing any of the above, for testing this icon qustion, you could create a head folder called "TEST ICON".
Within this folder "TEST ICON" create a bunch of folders calling them say "AA", "AB", ->, "AZ". Now each time you
reassemle your *.exe file, you copy this file and past it in a new ABC folder to veiw. When done testing new icon
arangments, remove all ABC folders.

The two runtime icons set in wc.hIcon and  wc.hIconSm of your window class (WNDCLASSEX) are not affected by the Windows
Explorer's icon caché.

If you have two separate icon files, the one you set in the .hIcon member of WNDCLASSEX is the icon that will be displayed
in the Desktop's Taskbar at runtime. The icon file you set in .hIconSm, will be displayed in the your app's Window Title Bar.

Note:
Testing was performed using the Resource Compiler supplied by Visual Studio.
Title: Re: Miscellaneous snippets
Post by: jj2007 on September 17, 2023, 10:51:40 PM
Quote from: Caché GB on September 17, 2023, 10:26:04 PMHi JJ

The only way I've bean able to achieve a solution to this Extra Large Icons View quetion.

1. The icon must be a 256x256 bmp or png. (To reduce binary bloatware, use png),
2. If this 256x256 icon is in an ICON GROUP, it mush be the first icon in the group.
3  This icon / icon group's Resource ID must be the lowest value (numeral) in the
   Resource File's (*.rc) ICON listings...

Thanks, Caché - interesting stuff :thumbsup:

I don't normally use Explorer for file operations (I use FreeCommander XE (https://freecommander.com/en/downloads/)). If I use it, it's with the details view, i.e. with the smallest possible icons. But it's good to know how to display one's icons in the XXL view, thanks :thup:
Title: Re: Miscellaneous snippets
Post by: TimoVJL on September 18, 2023, 07:19:46 AM
Not so small ?
With Setup program
FreeCommanderXE-32-public_setup.zip 16.12.2022 14.36 MB 9330AED7FA563A76C489FB0445905153CAE93CC591DE3B98B30C84DD468E75E4
Title: Re: Miscellaneous snippets
Post by: jj2007 on September 18, 2023, 07:41:03 AM
Yes, Timo, it's a bit bloated. But it offers ten times as many functions as the SASM "IDE" at 20% of its size. Ok for me. If you have a better alternative, please let me know.
Title: Re: Miscellaneous snippets
Post by: TimoVJL on September 18, 2023, 08:21:41 AM
I am Pelles C user, so i poide have been best for me.
I am now retired from all work, so now i just try keep nature around me in good condition.
I just spend my time with lawnmower and grass trimmers, and shovel and scythe before a scythe man release me from this ugly world  :biggrin:
Title: Get the size of a disk sector
Post by: jj2007 on February 07, 2024, 06:38:39 AM
How to get the size of a sector on disk:

include \masm32\MasmBasic\MasmBasic.inc
SectorSize MACRO drv, inx:=<2>
  StringToArray Launch$(Cat$("fsutil fsInfo sectorInfo "+repargA(drv))), SecInfo$()
  .if Instr_(SecInfo$(inx), ":")
    inc eax
    void Val(eax)
  .endif
  EXITM <eax>
ENDM
Enum #SECINFO_, 0:LOGBYTES, PHYSBYTESA, PHYSBYTESP, PHYSBYTESV
  Init
  PrintLine Str$("Drive C: has %i logical bytes per sector", SectorSize("C:", SECINFO_LOGBYTES))
  PrintLine Str$("Drive C: has %i physical bytes per sector", SectorSize("C:", SECINFO_PHYSBYTESA))
EndOfCode

Output:
Drive C: has 512 logical bytes per sector
Drive C: has 4096 physical bytes per sector

StringToArray (https://www.jj2007.eu/MasmBasicQuickReference.htm#Mb1130) graps fsutil output to create the SecInfo$() array; the rest is easy. You must run the exe as admin to see the result.

Just for fun - forget it immediately, it's only useful to demonstrate the use of some MasmBasic macros :biggrin:
Title: Re: Miscellaneous snippets
Post by: jj2007 on February 16, 2024, 11:29:14 PM
CISDLs:
CSIDL_ALTSTARTUP              C:\Users\Jochen\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
CSIDL_APPDATA                 C:\Users\Jochen\AppData\Roaming
Error   x:eax           80004005
CSIDL_BITBUCKET
CSIDL_CDBURN_AREA             C:\Users\Jochen\AppData\Local\Microsoft\Windows\Burn\Burn
CSIDL_COMMON_ADMINTOOLS       C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools
CSIDL_COMMON_ALTSTARTUP       C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
CSIDL_COMMON_APPDATA          C:\ProgramData
CSIDL_COMMON_DESKTOPDIRECTOR  C:\Users\Public\Desktop
CSIDL_COMMON_DOCUMENTS        C:\Users\Public\Documents
...
CSIDL_SYSTEM                  C:\Windows\system32
CSIDL_SYSTEMX86               C:\Windows\SysWOW64
CSIDL_TEMPLATES               C:\Users\Jochen\AppData\Roaming\Microsoft\Windows\Templates
CSIDL_WINDOWS                 C:\Windows
63 values displayed - hit any key

Full project attached. Latest list is here (https://learn.microsoft.com/en-us/windows/win32/shell/csidl), but WinExtra.inc seems pretty up-to-date :thumbsup:
Title: Re: Miscellaneous snippets
Post by: jj2007 on March 18, 2024, 12:52:44 PM
MasmBasic 17 March 2024 is online (http://masm32.com/board/index.php?topic=94.0). Plus a collection of miscellaneous non-essential files that don't fit into the main archive any more: check reply #1 (https://masm32.com/board/index.php?msg=265) for SetupMbExtras.zip.