Working with global variables in the Evo SDK - today we will again expand the capabilities of the Evo SDK

Working with global variables in the Evo SDK
 by Hippiman

So guys, today we're going to be empowering again.
Evo SDK. Initially, the SDK had rather limited capabilities 
and was close in functionality to popular editors on
ZX Spectrum. Here is the impossibility of working with the disk and extended
memory, and a terrible code size limit of 32K.

In my previous articles I described ways to get around these
restrictions. However, a way to increase the amount of code by
dividing it into modules was not very convenient due to the impossibility
working with global variables from modules. I had to
to fence off the monstrous functions-managers who transferred
the necessary parameters into the module or wrote them into the extended
memory. In principle, one could live with this, but the need
unnecessary body movements greatly reduced the speed of calling the module, and
This means that it limited the options for their use. In this article I
I’ll tell you how you can make friends between modules and global ones
(and static) variables of the main program.

                             * * *

First of all, go to the_temp_ subfolder in our project directory
(if it is not there, read ACNews #59) and open the fileout.map.
Scroll to approximatelymiddle of the file and look for the following lines there:

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

Where 00005322 is the beginning of the data area. (Of course, in different
Address may change on projects.)
Closeout.map, we are no longer interested in it, and open
out.asm.
At the beginning of this file there is a list of functions, let's scroll through it. Looking for

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

After these lines there is a list of global and static variables
this type:

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

As you can see, there are no addresses here, which is confusing at first.
But there is this:.ds 2.
These lines are nothing more than the byte offset between
variables.
By simple calculations we get the addresses:

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

Now we know the addresses of all global variables. Remaining
add themto the module.
For example, like this:

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

Just in case, let me remind you that after any change, basically
module and its recompilation, all addresses may change.
Therefore, manually calculating all the links every time is a task
thankless, and it’s better to entrust it to the script. Next I will give
full listing of your perl script that processes
sources of the main module and generates two headers:

pointers.h - with pointers to functions;
variables.h - with pointers to variables.

┌───────────────────────────────────── ─────────────────────────┐
#!/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=)
{
  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]);#here we get the address
        #data areas and convert it to decimal system
        #reckoning.
    }
  }
}

close FIL;
open FIL,"_temp_\out.asm"; #open the main source.
$flag=0;
while($flag==0) #scroll to the beginning of the variable description
{
  if(!($str=))
  {
    $flag=1;
  }
  chomp $str;
  #print $str."n";
  if($str eq "; ram data")
  {
    $flag=1;
  }
}
$str=;
$str=;

$flag=0;
while($flag==0)#process the area with variables
{
  if(!($str=))
  {
    $flag=1;
  }
  chomp $str;
  if($str eq
";------------------------------------------")
#this is the end of the area, we don't need anything further.
  {
    $flag=1;
  }
  else
  {
    $str=~s/t//g;#let's remove all trash
    $str=~s/://g;
    $tmp="#define ".$str." ".sprintf ("0x%x",$databegin)."n";
    $str=;#read another line containing
               #offset
    chomp $str;
    $str=~s/t//g;
    @arr=split(/ /,$str);
    $databegin+=$arr[1];#get new offset
    print $tmp;
    print VAR $tmp; # display the result in the header
  }
}
└───────────────────────────────────── ─────────────────────────┘

That's it. Now you can add a call to this script to the bat file 
compilation of the main module, and you always havewill be faithful 
information about the addresses of functions and variables. 

Share your thoughts about the article