Jump to content

Mat

MVPs
  • Posts

    5,140
  • Joined

  • Last visited

  • Days Won

    21

Mat last won the day on June 8 2014

Mat had the most liked content!

2 Followers

About Mat

  • Birthday 12/13/1993

Profile Information

  • Member Title
    Attendre et espérer!
  • Location
    Where the sun don't shine (England)
  • WWW
    http://ma.ttdiesel.co.uk
  • Interests
    Hockey and cricket mostly. I play a fair bit of sports, but if its raining then a computer is naturally my bestest friend.

Recent Profile Visitors

2,736 profile views

Mat's Achievements

  1. @toto22, There's a mistake in my previous post. The bit operations only work on 32 bit integers in AutoIt (no idea why). The below code shows a method using concatenation to build the hex string instead: ; Simulate the program $t = DllStructCreate("DOUBLE") DllStructSetData($t, 1, 123.456) $p = DllStructGetPtr($t) MsgBox(0, "Address", $p) ; This is what _MemoryRead($p) does the equivalent of $tRead = DllStructCreate("DWORD", $p) $hi = DllStructGetData($tRead, 1) ; This is what _MemoryRead($p+4) does the equivalent of $tRead = DllStructCreate("DWORD", $p+4) $lo = DllStructGetData($tRead, 1) ; Combine back into an 8byte integer: $full = Hex($lo,8) & Hex($hi,8) MsgBox(0, "Read from memory", "Two dwords:" & @CRLF & Hex($hi,8) & @CRLF & Hex($lo,8) & @CRLF & $full) ; Conversion to double: $sMemHex = String($full) $nNum = Dec($sMemHex, 3) MsgBox(0, $full, $nNum) I don't have NomadMemory installed, so instead I've shown the equivalent using structs (this method only works within one process).
  2. That depends on the range of the outputs. The way to analyse this properly is to look at extremes. For each variable, look at what the largest and smallest possible value is (the domain of the equation). Then from there you can work out what combination of values get you the largest and smallest result (and which intermediate steps are likely to overflow). If the range of possible outputs exceeds 2^64 (i.e. the range of answers ends up as zero to 2^80 or something), then the options are either a bignum UDF (with reduced performance), or a loss of accuracy (either floating point, or fixed point with a smaller factor). If the range of outputs is less than 2^64, but just happens to be at the top end of that, then you can work on offsetting it back into range. There is also clever stuff you can do with the numbers to stop you from going in and out of range during intermediate steps, just by forcing the order of operations. For example, lets say we were working on unsigned 8 bit values to try and do the sum "17x-15y" and we know the answer will fit into an 8 bit value. It's obvious that certain values of x and y will cause the operation to overflow on 17x, then come back into range when we subtract 15y. If we know that x>y rewrite the operation as "15(x-y)+2x". It's a trivial example. but that's the kind of way you have to approach the problem. Like I said, first step is looking at the domain of the equation. With that information, look at where you're overflowing and then we can look at how to correct that.
  3. If _MemoryRead is returning 4 byte values (which I think it does, but I haven't used it in a long time) then to combine you should use BitShift and BitOr. For example: BitOr(BitShift(_MemoryRead(...), 32), _MemoryRead(...)) So this shifts the more significant dword up and combines it with the lower dword. You'll have to do some reading on endianness to work out what addresses each would be. Once you have that value, then you can convert it to floating point using the method above.
  4. @Simpel - your maths is squiffy. You were dividing everything by 1e28 (which should have been 1e14) including the terms that weren't scaled up. The two possible ways to do it are to scale everything up to be 14 orders of magnitude higher, or to only divide the parts that have been scaled up. I'd actually suggest using the 3rd version below, which leaves the value as an integer, scaled up by 1e14, as then no precision is lost in the conversion back to floating point. This style of calculation is termed "fixed point" as we keep all the values scaled up by a fixed amount. This gives you a smaller range than floating point calculations, but greater precision (as we don't need to use bits to store the exponent). Local $xn = 32767, $xn_1 = 3276, $xn_2 = 327, $yn_1 = 3276, $yn_2 = 327 Local $yn = $xn - 2 * $xn_1 + $xn_2 + 1.99004745483398 * $yn_1 - 0.99007225036621 * $yn_2 ConsoleWrite($yn & @CRLF) $yn = ( ($xn - 2 * $xn_1)*100000000000000 + $xn_2 + 199004745483398 * $yn_1 - 99007225036621 * $yn_2) / 100000000000000 ConsoleWrite($yn & @CRLF) $yn = $xn - 2 * $xn_1 + ($xn_2 + 199004745483398 * $yn_1 - 99007225036621 * $yn_2) / 100000000000000 ConsoleWrite($yn & @CRLF) $yn = ($xn - 2 * $xn_1)*100000000000000 + ($xn_2 + 199004745483398 * $yn_1 - 99007225036621 * $yn_2) ConsoleWrite($yn & @CRLF) ConsoleWrite(Log($yn)/Log(2) & @LF) You aren't that far away from the limits in this case, about 62 bits of precision (the last line of code above is the bit calculation). The limit will be hit depending on the value of $yn_1, if it was 2x higher then you might be in trouble. Tbh, I'm surprised to see such a big error in the floating point calculation.
  5. I don't think Number(###, 3) will work in this case, as it will still treat the integer value at that memory location as a number, rather than an IEEE754 encoded value. The Dec function does do this conversion though, if you give it a string value. $xMem = 0x40151CAC083126E9 $sMemHex = String(Hex($xMem, 16)) $nNum = Dec($sMemHex, 3) MsgBox(0, $xMem, $nNum) In this case, the expected answer is 5.278. For completeness, to go the other way you can just use the Hex function on a double value.
  6. Hi argumentum, Still around, sort of... Only 2 weeks response time. That script evolved into a generic library for creating icons with context menus on the deskop, which can be found here, that various others then worked on as well. I have no idea what was in that particular script, and it's not in any of my old archives. Cheers, Mat
  7. To be honest, I think you're better off changing language and doing the timed part in a lower level language. You can use PostMessage with a user message code to communicate significant events back to the UI thread.
  8. Msdn recv (the actual function AutoIt uses could be one of a few within winsock, assuming they use winsock, but recv is the simplest and they'd hopefully all behave the same here): In short, MSDN says the data is saved by the service provider, and there is no limit to the buffer in the function AutoIt (is probably) calling. The default service provider is mswsock.dll, and that's as far as I've got. I can't seem to find any reference to the buffer size for mswsock.dll. React OS (a free os designed to be able to execute windows executables) possibly uses 512 bytes according to a patch. I haven't seen any indication that the buffer expands dynamically, but it could do. Just keep sending data and see if your memory usage grows I guess. Test sending loads of data and see if any is lost.
  9. I tried to get it doing a bit less by using DllCallAddress: #include <Array.au3> #include <WinAPI.au3> Local $sum, $loops = 10000 Local $hDll_ntdll = _WinAPI_LoadLibrary("ntdll.dll") Local $pNtDelayExecution = _WinAPI_GetProcAddress($hDll_ntdll, "NtDelayExecution") Local $prev = 0 Local $i = 1, $diff $hTimer = TimerInit() $loopcount=0 While 1 Do DllCallAddress("dword", $pNtDelayExecution, "int", 0, "int64*", -1) $diff = TimerDiff($hTimer) $loopcount+=1 Until $diff > $i ; 1ms loop $sum += $diff - $prev $prev = $diff If $i >= $loops Then ExitLoop $i += 1 WEnd MsgBox(0, "Finished.", "Mean loop time: " & ($sum / $loops)) MsgBox(0, "", "Loop Count : " & $loopcount) _WinAPI_FreeLibrary($hDll_ntdll) Very minor improvement. It's also not going to get much better without writing the whole loop another way. Loop Count: 17562
  10. On my laptop at home so different results from work PC: DllCall - Loop Count: 16608 Sans-DllCall  - Loop Count: 12234691
  11. I get 19836, so roughly twice per iteration. Whilst not ideal, it's better than your result. As Jchd mentioned, the OS will chooses who gets execution time or not, so it's difficult to get repeatable results. There's not much you can do to improve the overheads in that loop. About the only thing I could think to do would be to save one call to GetProcAddress and store it. It didn't make that much of a difference (19910 loops). Interestingly I see no difference at all between 32 and 64 bit versions. Only other thing I can think to try is to write a small routine to do the same thing in a compiled language, load it into memory and DllCallAddress it. That would minimise the time spent executing code in that loop. It's a fair bit of effort to get working though.
  12. Yep, seems even a 100ns sleep is enough to reduce the cpu usage to pretty much zero. It doesn't seem to impact too badly on the accuracy of the loop. #include <Array.au3> Local $sum, $loops = 10000 Local $hDll_ntdll = DllOpen("ntdll.dll") Local $prev = 0 Local $i = 1, $diff $hTimer = TimerInit() While 1 Do DllCall($hDll_ntdll, "dword", "NtDelayExecution", "int", 0, "int64*", -1) $diff = TimerDiff($hTimer) Until $diff > $i ; 1ms loop $sum += $diff - $prev $prev = $diff If $i >= $loops Then ExitLoop $i += 1 WEnd MsgBox(0, "Finished.", "Mean loop time: " & ($sum / $loops))
  13. Here is an example of using a timer to fix your loop time manually. You might find your cpu usage is very high if you run this constantly. This example stores the timer in an array for 100 iterations, and it was sometimes out by 10% but was usually pretty close. #include <Array.au3> Local $a[100] Local $i = 1 $hTimer = TimerInit() While 1 Do Until TimerDiff($hTimer) > $i ; 1ms loop $a[$i] = TimerDiff($hTimer) If $i >= 99 Then ExitLoop $i += 1 WEnd _ArrayDisplay($a) Mat
  14. Characters don't use just the colour table, each character also has attributes. By default these are set to be white text on black background (see here). I wrote a function to set the colour table, and another to set attributes. Try playing around with combinations. With setting the colortable, everything is blue (as you'd expect with all the colours being the same). #include <Array.au3> #include '..\Console.au3' _Console_Alloc() Local $ColorTable[16] = [0xFFFFFF, 0xFF0000, 0xFF0000, 0xFF0000, _ 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, _ 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, _ 0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000] $aOldColors = _Console_GetScreenBufferColorTable() ;~ _ArrayDisplay($aOldColors, 0xFF0000) ;~ $fSuccess = _Console_SetScreenBufferColorTable(-1, $ColorTable) ;~ If Not $fSuccess Then MsgBox(0, "Error (ColorTable)", @error & @CRLF & @extended) $fSuccess = _Console_SetScreenBufferAttributes(-1, BitOR($FOREGROUND_BLUE, $FOREGROUND_GREEN, $FOREGROUND_INTENSITY, $BACKGROUND_BLUE)) If Not $fSuccess Then MsgBox(0, "Error (Attributes)", @error & @CRLF & @extended) ;~ $aNewColors = _Console_GetScreenBufferColorTable() ;~ _ArrayDisplay($aNewColors, 0xFF0000) _Console_SetTitle("Hey look =P") _Console_Write("Hello, World!" & @LF) _Console_Pause() _Console_SetScreenBufferColorTable(-1, $aOldColors) _Console_Free() Func _Console_SetScreenBufferAttributes($hConsoleOutput, $iAttributes, $hDll = -1) If $hConsoleOutput = -1 Then $hConsoleOutput = _Console_GetStdHandle($STD_OUTPUT_HANDLE, $hDll) If $iAttributes = Default Then $iAttributes = 0 ; Get current buffer info $tConsoleScreenBufferInfoEx = _Console_GetScreenBufferInfoEx($hConsoleOutput, $hDll) If @error Then Return SetError(1, @error, False) ; Modify attributes $tConsoleScreenBufferInfoEx.Attributes = $iAttributes ; Set new buffer info $fSuccess = _Console_SetScreenBufferInfoExEx($hConsoleOutput, DllStructGetPtr($tConsoleScreenBufferInfoEx), $hDll) If Not $fSuccess Then Return SetError(2, @error, False) Return True EndFunc ;==>_Console_SetScreenBufferAttributes Func _Console_SetScreenBufferColorTable($hConsoleOutput, $aiColorTable, $hDll = -1) If $hConsoleOutput = -1 Then $hConsoleOutput = _Console_GetStdHandle($STD_OUTPUT_HANDLE, $hDll) If Not IsArray($aiColorTable) Then Return False If UBound($aiColorTable, 0) <> 1 Then Return False If UBound($aiColorTable, 1) < 16 Then Return False ; Get current buffer info $tConsoleScreenBufferInfoEx = _Console_GetScreenBufferInfoEx($hConsoleOutput, $hDll) If @error Then Return SetError(1, @error, False) $tConsoleScreenBufferInfoEx.Attributes = BitOR($FOREGROUND_RED, $FOREGROUND_BLUE, $FOREGROUND_GREEN, $BACKGROUND_RED, $BACKGROUND_BLUE, $BACKGROUND_GREEN) ; Modify color table For $i = 0 To 15 DllStructSetData($tConsoleScreenBufferInfoEx, "ColorTable", $aiColorTable[$i], $i + 1) Next ; Set new buffer info $fSuccess = _Console_SetScreenBufferInfoExEx($hConsoleOutput, DllStructGetPtr($tConsoleScreenBufferInfoEx), $hDll) If Not $fSuccess Then Return SetError(2, @error, False) Return True EndFunc ;==>_Console_SetScreenBufferColorTable Regards, Mat To clarify since it's not apparent from MSDN, the index in the colour table is with the bits of the attribute in the order IBGR.
  15. Another method that doesn't rely on execute trickery, using a function I wrote for using callbacks with regex. Local $sInput = "This is a test." & @CRLF & "Line 2" & @CRLF & "Line 3" & @CRLF & "Line 4" & @CRLF & "Line 5" & @CRLF & "Line 6" Local $sTest = "1: " & StringRegExpReplaceCallback($sInput, "\R", _Callback) MsgBox(0, "Test", $sTest) Func _Callback($aRes) Local Static $iCount = 1 $iCount += 1 Return @CRLF & $iCount & ": " EndFunc Func StringRegExpReplaceCallback($sString, $sPattern, $sFunc, $iLimit = 0) Local $iOffset = 1, $iDone = 0, $iMatchOffset While True $aRes = StringRegExp($sString, $sPattern, 2, $iOffset) If @error Then ExitLoop $sRet = Call($sFunc, $aRes) If @error Then Return SetError(@error, $iDone, $sString) $iOffset = StringInStr($sString, $aRes[0], 1, 1, $iOffset) $sString = StringLeft($sString, $iOffset - 1) & $sRet & StringMid($sString, $iOffset + StringLen($aRes[0])) $iOffset += StringLen($sRet) $iDone += 1 If $iDone = $iLimit Then ExitLoop WEnd Return SetExtended($iDone, $sString) EndFunc ;==>StringRegExpReplaceCallback
×
×
  • Create New...