ACNews #68
30 августа 2017

Работа с глобальными переменными в Evo SDK - сегодня мы снова будем расширять возможности Evo SDK

<b>Работа с глобальными переменными в Evo SDK</b> - сегодня мы снова будем расширять возможности
Evo SDK
           Работа с глобальными переменными в Evo SDK
                         by Hippiman

Итак, ребята, сегодня мы снова будем расширять возможности
Evo SDK. Изначально SDK имел довольно ограниченные возможности 
и по функционалу был близок к популярным редакторам на
ZX Spectrum. Тут и невозможность работы с диском и расширенной
памятью, и ужасное ограничение на размер кода в 32K.

В своих предыдущих статьях я описал способы обхождения этих
ограничений. Однако способ увеличения объёма кода путём
разделения его на модули был не очень удобен из-за невозможности
работы с глобальными переменными из модулей. Приходилось
городить монструозные функции-менеджеры, которые передавали
необходимые параметры в модуль или записывали их в расширенную
память. В принципе, с этим можно было жить, однако необходимость
лишних телодвижений сильно снижала скорость вызова модуля, а
значит, и ограничивала варианты их применения. В этой статье я
расскажу, как можно подружить модули и глобальные
(и статические) переменные основной программы.

                             * * *

Первым делом идём в подпапку_temp_ в директории нашего проекта
(если её нет, читай ACNews #59 ) и открываем файлout.map.
Листаем примерно до середины файла и ищем там вот такие строки:

Area  Addr     Size     Decimal Bytes (Attributes)
---------------------------------------------------------------
_DATA 00005322 000007C9 = 1993. bytes (REL,CON)

Где 00005322 - это начало области данных. (Естественно, в разных
проектах адрес может меняться.)
Закрываемout.map, нам он больше не интересен, и открываем
out.asm.
В начале этого файла идёт список функций, его пролистываем. Ищем

;--------------------------------------------------------
; ram data
;--------------------------------------------------------
.area _DATA

После этих строк идёт список глобальных и статических переменных
такого вида:

_curtime:
  .ds 2
_nexttime:
  .ds 2
_nextid:
  .ds 2
_nextglobid:
  .ds 2
_bullet1:
  .ds 1
_roadpos:
  .ds 1

Как видно, никаких адресов тут нет, что сначала сбивает с толку.
Зато есть вот это:.ds 2.
Эти строки есть не что иное, как смещение в байтах между
переменными.
Путём простых вычислений получаем адреса:

_curtime 0x00005322 (начало области данных)
_nexttime 0x00005322+0x2 = 0x00005324
_nextid 0x00005324+0x2 = 0x00005326
_nextglobid 0x00005326+0x2 = 0x00005328
_bullet1 0x00005328+0x2 = 0x0000532A
_roadpos 0x0000532A+0x1 = 0x0000532B и т.д.

Теперь мы знаем адреса всех глобальных переменных. Осталось
добавить их в модуль.
Например, так:

static u8 *maxhealth;
maxhealth=(u8*)_plmaxhealth;
*maxhealth=15;

На всякий случай напомню, что после любого изменения в основном
модуле и его перекомпиляции все адреса могут поменяться.
Следовательно, каждый раз вручную высчитывать все ссылки - дело
неблагодарное, и лучше его поручить скрипту. Далее я приведу
полный листинг своего perl скрипта, который обрабатывает
исходники основного модуля и генерирует два хедера:

pointers.h - с указателями на функции;
variables.h - с указателями на переменные.

┌──────────────────────────────────────────────────────────────┐
#!/usr/bin/perl
use strict;

my $flag;
my $str;
my @arr;
my $databegin;
my $tmp;
open FIL,"_temp_\out.map";
open OUT,">pointers.h";
open VAR,">variables.h";
$databegin=0;
while($str=<FIL>)
{
  chomp $str;
  $str=~s/s*//;
  if(length($str)>0)
  {
    @arr=split(/ /,$str);
    if(substr($arr[2],0,1) eq "_")
    {
      print "#define " .$arr[2]." 0x". $arr[0]."n";
      print OUT "#define " .$arr[2]." 0x". $arr[0]."n";
    }
    if($arr[0]eq"_DATA" && $databegin==0)
    {
      $databegin= hex($arr[31]);#вот тут мы получаем адрес
        #области данных и конвертируем его в десятичную систему
        #счисления.
    }
  }
}

close FIL;
open FIL,"_temp_\out.asm"; #открываем основной исходник.
$flag=0;
while($flag==0) #пролистываем до начала описания переменных
{
  if(!($str=<FIL>))
  {
    $flag=1;
  }
  chomp $str;
  #print $str."n";
  if($str eq "; ram data")
  {
    $flag=1;
  }
}
$str=<FIL>;
$str=<FIL>;

$flag=0;
while($flag==0)#обрабатываем область с переменными
{
  if(!($str=<FIL>))
  {
    $flag=1;
  }
  chomp $str;
  if($str eq
";--------------------------------------------------------")
#это конец области, дальше нам ничего не нужно.
  {
    $flag=1;
  }
  else
  {
    $str=~s/t//g;#уберём всякий мусор
    $str=~s/://g;
    $tmp="#define ".$str." ".sprintf ("0x%x",$databegin)."n";
    $str=<FIL>;#читаем ещё одну строку, в которой записано
               #смещение
    chomp $str;
    $str=~s/t//g;
    @arr=split(/ /,$str);
    $databegin+=$arr[1];#получим новое смещение
    print $tmp;
    print VAR $tmp; #выведем результат в хедер
  }
}
└──────────────────────────────────────────────────────────────┘

Вот и всё. Теперь можно добавить вызов этого скрипта к bat-файлу 
компиляции основного модуля, и у вас всегда будут верные 
сведения об адресах функций и переменных. 



Другие статьи номера:

Новости - Изменения в пакете NedoLang, Hippiman сменил квартиру, после чего начал писать игровой движок на NedoLang, John Silver купил студийные колонки-мониторы, венгерские хакеры портировали Wolfenstein 2004 на компьютер Enterprise 128.

News - Hippiman changed his residence, then started to make a game, John Silver bought studio speakers, first ATM 8.00 board was finally

Работа с глобальными переменными в Evo SDK - сегодня мы снова будем расширять возможности Evo SDK

Handling global variables in Evo SDK - we shall expand Evo SDK possibilities again

irc.forestnet.org #mhm о демопатях - какието там ЦЦ-Дихальты, это чисто русские такие тусовки-бухаловки с чисто русским таким менталитетом

irc.forestnet.org #mhm about demoparties - about russian parties

О светодиодных лампах - Началось всё с покупки настенного светильника в магазине IKEA в октябре 2016 года...


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Программирование - процедура печати сообщений в нижних строках экрана.
Железо - Глюки TR-DOS.
Специальный выпуск - Третий международный фестиваль компьютерного искусства "ENLIGHT'97".
Иной - скеси-ссака (2).
БАЙК-ШOУ report - Зaключeние...

В этот день...   25 апреля