Автокликер Clickermann :: Форум
Основной раздел => Общие вопросы => Topic started by: ya12 on January 13, 2018, 06:36:06 PM
-
Считываю координаты из процесса игрушки. READMEM возвращает целые числа. Как пересчитать в 4 байта с точкой.
Для примера:
в игре y=-5000.00 получаю -979615744, бегу на север(т.е. x не изменяется)
в игре y=-6000.00 получаю -977567744.
-
мои наработки по переводу из 4 байт, полученных как целое число, в float. пока так и не понял откуда взять то, что после точки :( . но целую часть расчитывает вроде правильно. буду рад за инфу по определению циферак после точки.
конвертеры тут http://www.binaryconvert.com + калькулятор в помощь
брал инфу отсюль http://www.softelectro.ru/ieee754.html https://blog2k.ru/archives/3321
SUB(toBIN, $DEC)
$BIN = ""
IF($DEC > 0)
WHILE($DEC > 0)
$DEC = $DEC/2
IF($DEC > int($DEC))
$BIN = STRCONCAT("1", $BIN)
else
$BIN = STRCONCAT("0", $BIN)
END_IF
$DEC = int($DEC)
END_CYC
WHILE(STRLEN ($BIN) < 32) //4 байта
$BIN = STRCONCAT("0", $BIN)
END_CYC
ELSE
$DEC = abs($DEC+1)
WHILE($DEC > 0)
$DEC = $DEC/2
IF($DEC > int($DEC))
$BIN = STRCONCAT("0", $BIN)
else
$BIN = STRCONCAT("1", $BIN)
END_IF
$DEC = int($DEC)
END_CYC
WHILE(STRLEN ($BIN) < 32) //4 байта
$BIN = STRCONCAT("1", $BIN)
END_CYC
END_IF
END_SUB
SUB(toDEC, $BIN_str)
$DEC = 0
IF(ARRSIZE ($arr) = 0)
$num_arr = 1
FOR($i=0,$i<32)
arrpush($arr, $num_arr)
$num_arr = $num_arr*2
END_CYC
END_IF
FOR($i=0,$i < STRLEN($BIN_str))
$DEC = $DEC + ($arr[$i]*int(STRCUT($BIN_str, STRLEN($BIN_str)-$i, 1)))
END_CYC
END_SUB
////////////////////////////////////////////////////////////////////////////
toBIN(-979615744) // твои 4 байта без точки
//toBIN(-977567744) // -6000
//print($BIN)
toDEC(STRCUT ($BIN,2, 8))
$exp = $DEC - 127
//print($exp)
toDEC(STRCONCAT("1",STRCUT ($BIN,10, $exp)))
IF(STRCUT ($BIN,1,1) = 1)
$DEC = $DEC*-1
END_IF
print($DEC) // твое число с точкой, но только целая часть -5000
halt
на сегодня итак перегруз :P
-
Огромное спасибо.
Пойду допилю автопилот.
-
все оказалось намного проще. вчера не дочитал до самого главного, есть готовая формула перевода из бинарного кода в число с точкой.
пример:
число - 01000011000110111010000000000000 , в целочисленном десятичном = 1125883904 (проверяем в калькуляторе)
S- бит знака (31-й бит) - 0
E- смещенная экспонента (30-23 биты) - 10000110
M - остаток от мантиссы (22-0 биты) - 00110111010000000000000
формула:
(http://www.softelectro.ru/ieee754_f1.gif)
для кликера это будет выглядеть так:
//$exp - экспонента в десятичном виде
//$mant - мантиса в десятичном виде
//$BIN = вся двоичная строка
POW(-1,int(STRCUT ($BIN,1,1))) * pow(2,$exp-127) * (1+($mant/POW(2,23)))
после расчетов получаем 155.625, как и в примере http://www.softelectro.ru/ieee754.html §4.
код:
//перевод числа в двоичную строку $BIN (строка выйдет длиной в 32бит)
SUB(dec_to_BIN, $DEC)
$BIN = ""
IF($DEC > 0) //если положительное
WHILE($DEC > 0)
$DEC = $DEC/2
IF($DEC > int($DEC))
$BIN = STRCONCAT("1", $BIN)
else
$BIN = STRCONCAT("0", $BIN)
END_IF
$DEC = int($DEC)
END_CYC
WHILE(STRLEN ($BIN) < 32) //4 байта
$BIN = STRCONCAT("0", $BIN)
END_CYC
ELSE //если отрицательное
$DEC = abs($DEC+1)
WHILE($DEC > 0)
$DEC = $DEC/2
IF($DEC > int($DEC))
$BIN = STRCONCAT("0", $BIN)
else
$BIN = STRCONCAT("1", $BIN)
END_IF
$DEC = int($DEC)
END_CYC
WHILE(STRLEN ($BIN) < 32) //4 байта
$BIN = STRCONCAT("1", $BIN)
END_CYC
END_IF
END_SUB
//перевод из двоичной строки в десятичное число $DEC
SUB(bin_to_DEC, $BIN_str)
$DEC = 0
IF(ARRSIZE ($arr) = 0)
$num_arr = 1
FOR($i=0,$i<32)
arrpush($arr, $num_arr)
$num_arr = $num_arr*2
END_CYC
END_IF
FOR($i=0,$i < STRLEN($BIN_str))
$DEC = $DEC + ($arr[$i]*int(STRCUT($BIN_str, STRLEN($BIN_str)-$i, 1)))
END_CYC
END_SUB
//перевод из целочисленного в дробное $float. целочисленное 4 байт - long (Signed int) от -2147483648 до 2147483647
SUB(int_to_Float, $int_in)
dec_to_BIN($int_in)
bin_to_DEC(STRCUT ($BIN,2, 8))
$exp = $DEC //экспонента в десятичном
bin_to_DEC(STRCUT ($BIN,10, 32))
$mant = $DEC //мантиса в десятичном
$float = POW(-1,int(STRCUT ($BIN,1,1))) * pow(2,$exp-127) * (1+($mant/POW(2,23)))
END_SUB
///////////////////////////////////////////////////////////////////////////////
//основной код
int_to_Float(-979615744)
print($float) // -5000
int_to_Float(1125883904)
print($float) // 155.625
halt
-
Перекодирование 4 байтного числа с плавающей точкой (в СЕ тип Float; в Delphi тип Single), полученного функцией READMEM, в целое число.
Поскольку CALL("Plugin.DLL", ...) передает в DLL и принимает числа в диапазоне от
-2 147 483 648 до 2 147 483 647, а READMEM считывает беззнаковое число в диапазоне от
0 до 4294967295, то READMEM должен считывать это число не 1 раз по 4, а 2 раза по 2 байта с шагом в 2 байта.
CALL("float_int".dll, x0, x1)
x0 - старшие байты
x1 - младшие байты
CALL("float_int.dll", 0xC67b, 0xd000)
print($_return1)
halt
Код float_int.dll на DELPHI
library float_int;
uses
SysUtils;
//------------------------------------------------------------------------------
// Основное тело функции, идет на экспорт, вызывается из кликера
function execute( _mas: pInteger; _size: Integer): Integer; export; stdcall;
type
pIntArr = array[0..0] of Integer;
var
tmp, tmp0, tmp1: Integer;
sum: Int64;
float: Single;
begin
// _mas - указатель на начало массива параметров integer
// _size - размер массива (число параметров)
tmp0:= pIntArr(_mas^)[0];
tmp1:= pIntArr(_mas^)[_size-1];
sum:= tmp0*65536 + tmp1;
Move(sum, float, 4);
tmp:= Round(float);
result:= tmp // присваиваем возвращаемое значение
end;
//------------------------------------------------------------------------------
// список экспорта
exports execute;
begin
// тело пусто
end.
-
Перекодирование 4 байтного числа с плавающей точкой (в СЕ тип Float; в Delphi тип Single), полученного функцией READMEM, в целое число.
Поскольку CALL("Plugin.DLL", ...) передает в DLL и принимает числа в диапазоне от
-2 147 483 648 до 2 147 483 647, а READMEM считывает беззнаковое число в диапазоне от
0 до 4294967295, то READMEM должен считывать это число не 1 раз по 4, а 2 раза по 2 байта с шагом в 2 байта.
Странно это как то. по сути то какая разница что там передается в длл если это по сути тупо 4 байта. Может кликер че там делает, что они 8байтными в какойто момент становятся :-\ ;D
как вариант:
print(0xC67bd000) // 3330002944
print((0xC67bd000-2147483648)xor(-2147483648)) // -964964352
//в бинарном одно и тоже 11000110011110111101000000000000
halt
-
все оказалось намного проще. вчера не дочитал до самого главного, есть готовая формула перевода из бинарного кода в число с точкой.
пример:
число - 01000011000110111010000000000000 , в целочисленном десятичном = 1125883904 (проверяем в калькуляторе)
S- бит знака (31-й бит) - 0
E- смещенная экспонента (30-23 биты) - 10000110
M - остаток от мантиссы (22-0 биты) - 00110111010000000000000
...
...
Вспомнил случайно эту тему сегодня и понял, что сильно намудрил с переводами в бинарную строку и прочими махинациями. Можно было проще - сдвигами бит и математикой.
$s = int($int/2147483648) //бит знака (31-й бит)
$exp = int($int/8388608) - $s*256 //смещенная экспонента (30-23 биты)
$mant = $int - $exp*8388608 - $s*2147483648 //остаток от мантиссы (22-0 биты)
Теперь можно переводить из int во float одной строкой, только она уж очень длинная :D:
$float = POW(-1,int($int/2147483648)) * pow(2,int($int/8388608) - int($int/2147483648)*256-127) * (1+(($int - (int($int/8388608) - int($int/2147483648)*256)*8388608 - int($int/2147483648)*2147483648)/POW(2,23)))
Но данная формула работает только с беззнаковыми числами в диапазоне от 0 до 4294967295. Поэтому, если на входе отрицательное число, то переводим его в беззнаковое:
//перевод в беззнаковое число
IF($int < 0)
$int = ($int xor (-2147483648)) + 2147483648
END_IF
Вместе перевод из целого числа в число с точкой выглядит так:
$int = -979615744 // входящее число, целое
//перевод в беззнаковое число, если оно отрицательное
IF($int < 0)
$int = ($int xor (-2147483648)) + 2147483648
END_IF
$float = POW(-1,int($int/2147483648)) * pow(2,int($int/8388608) - int($int/2147483648)*256-127) * (1+(($int - (int($int/8388608) - int($int/2147483648)*256)*8388608 - int($int/2147483648)*2147483648)/POW(2,23))) //расчет
print($float) // -5000.00
halt
Добавлено:
Черт возьми, с чего я вообще взял, что нужны такие сложности для перевода отрицательного числа в беззнаковое :o , ума не приложу. Взял тогда из предыдущего поста и немого изменил. А ведь достаточно просто прибавить или отнять 4294967296 :-\
//перевод в беззнаковое число, если оно отрицательное
IF($int < 0)
$int = $int + 4294967296
END_IF
Исправленный код:
$int = -1021599744 // входящее число, целое
//перевод в беззнаковое число, если оно отрицательное
IF($int < 0)
$int = $int + 4294967296
END_IF
$float = POW(-1,int($int/2147483648)) * pow(2,int($int/8388608) - int($int/2147483648)*256-127) * (1+(($int - (int($int/8388608) - int($int/2147483648)*256)*8388608 - int($int/2147483648)*2147483648)/POW(2,23))) //расчет
print($float) // -155.625
halt