Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в эту темуОткрыть новую тему
> Readmem, Чтение Single/float Из Памяти, ArtMoney->DWORD->Float->Int
Zeleax
сообщение 1.12.2011, 7:52
Сообщение #1


*********

ex-Moderator UOPilot
Сообщений: 2.440
Регистрация: 8.10.2010
Группа: Пользователи
Наличность: 0
Из: Киев
Пользователь №: 13.093



Иногда в играх значения параметров хранятся в памяти не в целых, а в дробных величинах.
Программа ArtMoney в этом случае найдет значение типа DWORD (4 байта), которое при считывании пилотом из памяти выглядит как целое и совсем не похоже на нужное нам значение.

Скрипт был написан с целью помочь с решением проблемы в этой теме, чтобы показать- как можно это "неправильное целое" преобразовать в нужное нам 4-хбайтовое вещественное число с плавающей запятой (SINGLE/FLOAT).

Данный скрипт оставляет только целую часть числа, отбрасывая дробную.
Теоретическая информация для алгоритма взята отсюда.

З.Ы.: Протестировал не нескольких различных дробных числах - работает правильно.

Просьба при обнаружении в результатах работы скрипта ошибок - отписываться в теме, указывая целое число DWORD на входе скрипта, неверный результат на выходе, ожидаемое число (которое скрипт должен был вернуть).

Скрипт
Код

// (c) Zeleax
// В этом примере пилотом из памяти было считано DWORD равное 3305405440, которое подразумевает SINGLE(FLOAT) число -2119.75
// readmem #sdw_DWORD 0х12C30770 DWORD
set #sdw_DWORD 3305405440
gosub DWord2Single

// результат будет равен  -2119
msg Целая часть дробного числа равна #sdw_result

end_script


// Процедура преобразует  DWORD в соответствующее вещественное число, оставляя только целую часть
// Перед вызовом в #sdw_DWORD записываем исходные данные.
// Результат возвращается в #sdw_result
:DWord2Single

set linedelay 0 // Устанавливаем задержку между строк в 0
set #sdw_dww #sdw_DWORD // Исходное число DWORD считанное из памяти
if #sdw_dww = 0
   set #sdw_result 0
   return
end_if

set #sdw_dww_size 32 // разрядность числа, бит

set #sdw_dw #sdw_dww
if #sdw_dw < 0
   set #sdw_dw #sdw_dw * (-1)
   set #sdw_priznak -1 // придется далее инвертировать часть битов числа #sdw_dww
else
   set #sdw_priznak 1
end_if

// Раскладываем число #sdw_dw на отдельные биты в массив %sdw_bit
set #sdw_i #sdw_dww_size
while #sdw_i > 0
   set %sdw_bit[#sdw_i] #sdw_dw - #sdw_dw / 2 * 2 // bit № i (при нумерации битов слева направо с 1 по 32)
   set #sdw_dw #sdw_dw / 2
   set #sdw_i #sdw_i - 1
end_while

if #sdw_priznak < 0 // придется заморачиваться с частичной инверсией битов
   // Ищем крайнюю правую "1"
   set #sdw_i #sdw_dww_size
   while #sdw_i > 1
      if %sdw_bit[#sdw_i] = 1
         break
      end_if
      set #sdw_i #sdw_i - 1
   end_while

   // всё что левее последней "1" - инвертируем
   while #sdw_i > 2
      set #sdw_i #sdw_i - 1
      if %sdw_bit[#sdw_i] = 1
         set %sdw_bit[#sdw_i] 0
      else
         set %sdw_bit[#sdw_i] 1
      end_if
   end_while
  
   set %sdw_bit[1] 1 // устанавливаем старший бит, из-за которого и начался "сыр-бор" )
end_if

// *** Выделяем знак, порядок числа, мантиссу ***
// Знак числа
if %sdw_bit[1] = 0
   set #sdw_znak 1 // +
else
   set #sdw_znak -1 // -
end_if

// Порядок
set #sdw_por 0
for #sdw_i 2 9
   set #sdw_por (#sdw_por * 2) + %sdw_bit[#sdw_i]
end_for
set #sdw_por #sdw_por - 127

// Выделяем целую часть числа
set #sdw_mant 1
set #sdw_j 10 + #sdw_por - 1
for #sdw_i 10 #sdw_j
   set #sdw_mant (#sdw_mant * 2) + %sdw_bit[#sdw_i]
end_for

set #sdw_result #sdw_znak * #sdw_mant // Получаем результат
return


--------------------
Полезные советы - читать всем! UOWiki
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения

Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия | Версия для КПК Сейчас: 8.7.2025, 0:46
Designed by Nickostyle