30 августа 2017

              Handling global variables in Evo SDK
                         by Hippiman

So, guys, we shall expand Evo SDK possibilities again. Initially
SDK had very limited possibilities and was close by
functionality to popular ZX Spectrum native editors. There was
no disk access and high memory addressing, and the terrible code
limitation to 32KB.

I described means of overcoming that in my previous
publications. However, growing code by dividing it in modules
was uncomfortable because of no access to global variables from
modules. We needed monstrous manager functions to pass needed
parameters in module or write them in high memory. In fact, we
could live with that, but the need for extra effort slowed down
module calls and their uses. Here I'll tell how to make friends
with global (and static) variables of main program from a
module.

                             * * *

First we go to_temp_ subdirectory in our project (if you don't
have it, read ACNews #59 ) and open fileout.map. Scroll to the
middle of the file, searching for lines like this:

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

Where 00005322 is a beginning of data area. (Of course, it
varies for different projects.)
Let's closeout.map, we don't need it any more. Open out.asm.
It starts with function list, skip it. Find the following:

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

After that, a list of global and static variables follows like
this:

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

As we see, there are no addresses, and that's confusing.
Although we have this:.ds 2.
These are nothing but byte sizes of variables.
Using simple computations, we produce the addresses:

_curtime 0x00005322 (beginning of data area)
_nexttime 0x00005322+0x2 = 0x00005324
_nextid 0x00005324+0x2 = 0x00005326
_nextglobid 0x00005326+0x2 = 0x00005328
_bullet1 0x00005328+0x2 = 0x0000532A
_roadpos 0x0000532A+0x1 = 0x0000532B etc.

So we know all the addresses of global variables. We just need
adding then in a module.
For example, this way:

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

Make sure that addresses can change after every change and
recompilation of main module. So hand counting all links is bad
idea, we better write a script for this. Here is the listing of
perl script that processes main module sources and generates two
headers:

pointers.h - with function pointers;
variables.h - with variable pointers.

┌──────────────────────────────────────────────────────────────┐
#!/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]);#we obtained data area address
                                #and convert it in decimal.
    }
  }
}

close FIL;
open FIL,"_temp_\out.asm"; #open main source.
$flag=0;
while($flag==0) #scroll to beginning of variable descriptions
{
  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)#process variable area
{
  if(!($str=<FIL>))
  {
    $flag=1;
  }
  chomp $str;
  if($str eq
";--------------------------------------------------------")
#end of area, we don't need anything after it.
  {
    $flag=1;
  }
  else
  {
    $str=~s/t//g;#remove various trash
    $str=~s/://g;
    $tmp="#define ".$str." ".sprintf ("0x%x",$databegin)."n";
    $str=<FIL>;#read one more line containing shift
    chomp $str;
    $str=~s/t//g;
    @arr=split(/ /,$str);
    $databegin+=$arr[1];#we obtained new shift
    print $tmp;
    print VAR $tmp; #output the result in header
  }
}
└──────────────────────────────────────────────────────────────┘

That's all. Now we can call this script from .bat file that 
compiles the main module, and we shall always have fresh data 
about addresses of functions and variables. 



Other articles:


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

Similar articles:
authoring program - Description of the System Program "Uinversal Sprite Cracker v1.01".
about different - Organism'a letter about the plight of Spektrumistov outback.
INTERNET & FIDO - On the teleconference on the Spectrum.
A Tangled Web - the creation of obschebelorusskoy ZX-Net

В этот день...   3 December