flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > Macroinstructions > rsrc directory macro with named resources support & strcmp

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 88
Location: Russian Federation, Sochi
rsrc directory macro with named resources support & strcmp

Code:
;with support for named resources, not only ID`ed
macro directory definitions&
  local epyt; epyt is type vice versa
        iterate <type,label>, definitions
                root@resource dd 0,%t,0

                local total,current,next,len,nms,ids
                total = %%
                len=0
                nms=0
                ids=0
                repeat total
                  indx %
                  if type eqtype ""
                    if len<lengthof(type)
                      len =lengthof(type)
                    end if
                    nms=nms+1
                    local type#%; prev ver of my macro haven`t local for each iteration - fixed
                  else
                    ids=ids+1
                  end if
                end repeat

                dw nms,ids

                repeat total
                  indx %
                  if type eqtype ""
                    epyt=string((+(type bswap (lengthof(type)))) shl ((len-lengthof(type))*8))
                    ;epyt is integer representation of string type in current string set, integer comparison of epyt equivalent to string comparison of type
                end repeat

                current = -1
                next = 0
                while current < next
                        current = next
                        repeat total
                                indx %
                                if type eqtype ""
                                if (+epyt) = current
                                        dd 80000000h+type#%-root@resource,80000000h+label-root@resource
                                else if (+epyt) > current & ( next = current | next > (+epyt) )
                                        next = (+epyt)
                                end if
                                end if
                        end repeat
                end while
                current = -1
                next = 0
                while current < next
                        current = next
                        repeat total
                                indx %
                                if ~type eqtype ""
                                if type = current
                                        dd type,80000000h+label-root@resource
                                else if type > current & ( next = current | next > type )
                                        next = type
                                end if
                                end if
                        end repeat
                end while
                while current < next
                        current = next
                        repeat total
                                indx %
                                if type eqtype ""
                                  align 4
                                  type#% dw lengthof(type; bug find: was "type#% dw lengthof(type), type,0" - there`re no req for ending that with 0 - 0 - removed
                                                               ; dw makes not exactly that du does - fixed du type instead of dw type
                                                  du type
                                end if
                        end repeat
                end while
                break
        end iterate
end macro





Code:

macro cmpstr str1,str2
  local tmp1,tmp2,x
  tmp1=str1 bswap (lengthof(str1)) 
  tmp2=str2 bswap (lengthof(str2))
  x=lengthof(tmp1)-lengthof(tmp2)
  if x>0
    tmp1=string((+tmp1shr (x*8)) ; in case of 2 string comparison it is more compact in memory form than its analog: tmp2=string((+tmp2) shl ((x)*8 ))
  end if
  if x<0
    tmp2=string((+tmp2shr ((-x)*8)) ; in case of 2 string comparison it is more compact in memory form than its analog: tmp1=string((+tmp1) shl ((-x)*8 ))
  end if
  if tmp1>tmp2
    display str1,">",str2,13,10
  else
    if tmp1<tmp2
      display str1,"<=",str2,13,10
    else
      if x>0
        display str1,">",str2,13,10
      else
        display str1,"<=",str2,13,10
      end if
    end if
end macro

cmpstr "atrtygyihilh","bdfuy"
cmpstr "atrtygyihilh","atrty"
cmpstr "atrty","atrtygyihilh"
cmpstr "atrty","atrty"
cmpstr "a","bdfuy"
cmpstr "a","b"




post edited (fixes added & commented since 1st & 2nd post) - macro tested & worked

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 11 May 2017, 05:03
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 88
Location: Russian Federation, Sochi
v dogonku (in addition)

Code:

macro resource dir,definitions&
        iterate <id,lang,label>, definitions
                dir dd 0,%t,0;,%% shl 16
                local total,current,next,counter,nm,len,nms,ids
                total = %%
                len=0
                nms=0
                ids=0

                repeat total
                  indx %
                  if id eqtype ""
                    if len<lengthof(id)
                      len =lengthof(id)
                    end if
                    nms=nms+1
                    local id#%
                  else
                    ids=ids+1
                  end if
                end repeat

                dw nms,ids ; instead of dd %% shl 16

                repeat total
                  indx %
                  if id eqtype ""
                    nm=string((+(id bswap (lengthof(id)))) shl ((len-lengthof(id))*8))
                  end if
                end repeat

                current = -1
                next = 0
                while current < next
                        current = next
                        counter = 0
                        repeat total
                                indx %
                                if id eqtype ""
                                if (+nm) = current
                                        if counter = 0
                                                dd 80000000h+id#%-root@resource,80000000h+label-root@resource
                                        end if
                                        counter = counter + 1
                                        label.count = counter
                                else if (+nm) > current & ( next = current | next > (+nm) )
                                        next = (+nm)
                                end if
                                end if
                        end repeat
                end while

                current = -1
                next = 0
                while current < next
                        current = next
                        counter = 0
                        repeat total
                                indx %
                                if ~id eqtype ""
                                if id = current
                                        if counter = 0
                                                dd id,80000000h+label.directory-root@resource
                                        end if
                                        counter = counter + 1
                                        label.count = counter
                                else if id > current & ( next = current | next > id )
                                        next = id
                                end if
                                end if
                        end repeat
                end while

                current = -1
                next = 0
                while current < next
                        current = next
                        counter = 0
                        repeat total
                                indx %
                                if ~id eqtype ""
                                if id = current
                                        if counter = 0
                                                label.directory dd 0,%t,0,label.count shl 16
                                                dd lang,label-root@resource
                                                label.resid = id
                                                started = 1
                                        else
                                                dd lang,label-root@resource
                                        end if
                                        counter = counter + 1
                                else if id > current & ( next = current | next > id )
                                        next = id
                                end if
                                end if
                        end repeat
                end while

                current = -1
                next = 0
                while current < next
                        current = next
                        counter = 0
                        repeat total
                                indx %
                                if id eqtype ""
                                if (+nm) = current
                                        if counter = 0
                                                label.directory dd 0,%t,0,label.count shl 16
                                                dd lang,label-root@resource
                                                label.resid = (+nm)
                                                started = 1
                                        else
                                                dd lang,label-root@resource
                                        end if
                                        counter = counter + 1
                                else if (+nm) > current & ( next = current | next > (+nm) )
                                        next = (+nm)
                                end if
                                end if
                        end repeat
                end while

                current = -1
                next = 0
                while current < next
                        current = next
                        repeat total
                                indx %
                                if id eqtype ""
                                  align 4
                                  id#% dw lengthof(id)
                                  du id
                                end if
                        end repeat
                end while

                break
        end iterate
end macro


Post 11 May 2017, 16:06
View user's profile Send private message Send e-mail Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6628
Location: Kraków, Poland
Have you considered designing an entirely new syntax for resource definitions? The syntax of old fasm 1 macros is a legacy that feels a bit outdated.
Post 11 May 2017, 18:44
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 88
Location: Russian Federation, Sochi
I don`t mind new syntax. I can join to think under realization, but I no idea about how new syntax should looks like.
Post 11 May 2017, 23:06
View user's profile Send private message Send e-mail Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6628
Location: Kraków, Poland

ProMiNick wrote:
I don`t mind new syntax. I can join to think under realization, but I no idea about how new syntax should looks like.

The old syntax is as it is because there was no other choice at the time, it was the only syntax possible with fasm's macros back then (around 2001-2002). With fasmg we have so much more flexibility, that we could start with thinking of a syntax first and then how to implement it with macros. We could make something like "begin resource" and "end resource" macro pair that would allow to put resource definitions inside, perhaps even with a syntax mimicking the .RC script.
Post 12 May 2017, 13:30
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6628
Location: Kraków, Poland
Actually, I should write the RESOURCE FROM '*.RES' implementation for PE.INC first (it's the only feature of fasm's PE formatter that these macros still lack), because it could serve as a framework for any resource macros with simplified syntax. The .RES file has a linear structure that has to be converted to a tree in the PE format, and a similar conversion would be needed when collecting a simple list of resource definitions through macros.
Post 12 May 2017, 18:20
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6628
Location: Kraków, Poland
Inspired by your tweaks I have finally prepared a generic PE resource directory formatting macros which can be used as a base for constructing resource directories with more specialized ones. The general framework looks like this:

Code:
macro resource_directory?
        namespace PE
                Resourcerb RESOURCE_HEADERS_LENGTH
                Resource.counter = 0
                define RESOURCE_DIRECTORIES_LIST Resource_root
                Resource_root.counter = 0
        end namespace
end macro

macro resource_data? type*,id*,lang*,codepage:0
        namespace PE
                local _type,_id,_lang
                _type = type
                _id = id
                _lang = lang
                if ~ type eqtype 0
                        _type = _type shl 32
                end if
                if ~ id eqtype 0
                        _id = id shl 32
                end if
                if ~ lang eqtype 0
                        _lang = lang shl 32
                end if
                repeat 1%type:_type%id:_id%lang:_lang
                        if ~ defined Resource_#%type#_#%id.counter
                                if ~ defined Resource_#%type.counter
                                        repeat 1i:Resource_root.counter
                                                Resource_root.entry#i = type
                                                Resource_root.offset#i =  (Resource_#%type - Resourceor 80000000h
                                        end repeat
                                        Resource_root.counter = Resource_root.counter + 1
                                        match listRESOURCE_DIRECTORIES_LIST
                                                define RESOURCE_DIRECTORIES_LIST list,Resource_#%type
                                        end match
                                        Resource_#%type.counter = 0
                                end if
                                repeat 1i:Resource_#%type.counter
                                        Resource_#%type.entry#i = id
                                        Resource_#%type.offset#i =  (Resource_#%type#_#%id - Resourceor 80000000h
                                end repeat
                                Resource_#%type.counter = Resource_#%type.counter + 1

                                match listRESOURCE_DIRECTORIES_LIST
                                        define RESOURCE_DIRECTORIES_LIST list,Resource_#%type#_#%id
                                end match
                                Resource_#%type#_#%id.counter = 0
                        end if
                        repeat 1i:Resource_#%type#_#%id.counter
                                Resource_#%type#_#%id.entry#i = lang
                                Resource_#%type#_#%id.offset#i = Resource_#%type#_#%id#_#%lang - Resource
                        end repeat
                        Resource_#%type#_#%id.counter = Resource_#%type#_#%id.counter + 1
                        repeat 1i:Resource.counter
                                Resource_#%type#_#%id#_#%lang := Resource.entry#i
                                Resource.cp#i := codepage
                                Resource.data#i:
                        end repeat
                end repeat
        end namespace
end macro

macro end?.resource_data?
        namespace PE
                repeat 1i:Resource.counter
                        Resource.size#i := $ - Resource.data#i
                end repeat
                Resource.counter = Resource.counter + 1
                align 4
        end namespace
end macro

macro end?.resource_directory?
       namespace PE
                RESOURCE_HEADERS_POINTER = 0

                match listRESOURCE_DIRECTORIES_LIST
                        iterate dirlist
                                dir := Resource + RESOURCE_HEADERS_POINTER
                                RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 16 + dir.counter * 8
                                local x,y,z,a,b
                                x = dir.counter shr 1
                                while x > 0
                                        y = x
                                        while y < dir.counter
                                                z = y
                                                while z-x >= 0
                                                        repeat 1i:zj:z-x
                                                                if dir.entry#i eqtype 0
                                                                        if ~ dir.entry#j eqtype 0 | dir.entry#i >= dir.entry#j
                                                                                z = 0
                                                                        end if
                                                                else if ~ dir.entry#j eqtype 0
                                                                        a = dir.entry#i bswap lengthof dir.entry#i
                                                                        b = dir.entry#j bswap lengthof dir.entry#j
                                                                        if ( lengthof a >= lengthof b & a shr ((lengthof a - lengthof b)*8) >= b ) | ( lengthof a < lengthof b & a > b shr ((lengthof b - lengthof a)*8) )
                                                                                z = 0
                                                                        end if
                                                                end if
                                                                if z > 0
                                                                        a = dir.entry#i
                                                                        b = dir.offset#i
                                                                        dir.entry#i = dir.entry#j
                                                                        dir.offset#i = dir.offset#j
                                                                        dir.entry#j = a
                                                                        dir.offset#j = b
                                                                        z = z - x
                                                                end if
                                                        end repeat
                                                end while
                                                y = y + 1
                                        end while
                                        x = x shr 1
                                end while
                        end iterate
                        iterate dirlist
                                store %t : 4 at dir + 4
                                dir.names_counter = 0
                                repeat dir.counteri:0
                                        if dir.entry#i eqtype 0
                                                store dir.entry#i : 4 at dir + 16 + i * 8
                                        else
                                                dir.names_counter = dir.names_counter + 1
                                                repeat 1%id:dir.entry#i
                                                        if ~ defined Resource_string#%id
                                                                restore Resource_string#%id
                                                                Resource_string#%id = Resource + RESOURCE_HEADERS_POINTER
                                                                if lengthof dir.entry#i and 1
                                                                        err 'a word-aligned string is expected as a name'
                                                                end if
                                                                RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + lengthof dir.entry#i + 2
                                                                store (lengthof dir.entry#i)/2 : 2 at Resource_string#%id
                                                                store dir.entry#i : lengthof dir.entry#i at Resource_string#%id + 2
                                                        end if
                                                        store (Resource_string#%id - Resourceor 80000000h : 4 at dir + 16 + i * 8
                                                end repeat
                                        end if
                                        store dir.offset#i : 4 at dir + 16 + i * 8 + 4
                                end repeat
                                store dir.names_counter : 2 at dir + 12
                                store dir.counter - dir.names_counter : 2 at dir + 14
                        end iterate
                end match

                if RESOURCE_HEADERS_POINTER and 11b
                        RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 4 - RESOURCE_HEADERS_POINTER and 11b
                end if

                repeat Resource.counteri:0
                        Resource.entry#i := Resource + RESOURCE_HEADERS_POINTER
                        RESOURCE_HEADERS_POINTER = RESOURCE_HEADERS_POINTER + 16
                        store RVA(Resource.data#i) : 4 at Resource.entry#i
                        store Resource.size#i : 4 at Resource.entry#i + 4
                        store Resource.cp#i : 4 at Resource.entry#i + 8
                end repeat

                RESOURCE_HEADERS_LENGTH = RESOURCE_HEADERS_POINTER
        end namespace
end macro

And it can be used to construct resource directory this way:

Code:
resource_directory

        resource_data RT_BITMAP,1,LANG_NEUTRAL
                file 'assign.bmp':0Eh
        end resource_data

end resource_directory

A multiple "resource_data" definitions may be put there in any order and they are going to be placed in the appropriate leaves of PE resource tree.

I have used this framework to write a macro that reproduces "resource from" feature of fasm 1. It loads resources sequentially from the .RES file and converts them into "resource_data" blocks:

Code:
macro PE.resource_from path*

        local res_file,res_size,res_header_size,res_data_size,res_data
        local offset,char,type,id,lang

        virtual at 0
                res_file:: file path
                res_size := $
        end virtual

        resource_directory

                offset = 0
                while offset < res_size
                        load res_header_size : 4 from res_file : offset + 4
                        load res_data_size : 4 from res_file : offset + 0

                        if res_data_size > 0

                                offset =: offset + 8
                                load char : 2 from res_file : offset
                                if char = 0FFFFh
                                        load char : 2 from res_file : offset + 2
                                        type = +char
                                        offset = offset + 4
                                else
                                        while 1
                                                if char = 0
                                                        load type : (%-1)*2 from res_file : offset
                                                        offset = offset + (% + % and 1)*2
                                                        break
                                                end if
                                                load char : 2 from res_file : offset + %*2
                                        end while
                                end if
                                load char : 2 from res_file : offset
                                if char = 0FFFFh
                                        load char : 2 from res_file : offset + 2
                                        id = +char
                                        offset = offset + 4
                                else
                                        while 1
                                                if char = 0
                                                        load id : (%-1)*2 from res_file : offset
                                                        offset = offset + (% + % and 1)*2
                                                        break
                                                end if
                                                load char : 2 from res_file : offset + %*2
                                        end while
                                end if
                                load char : 2 from res_file : offset + 6
                                lang = +char

                                restore offset

                                resource_data type,id,lang
                                        load res_data : res_data_size from res_file : offset + res_header_size
                                        db res_data
                                end resource_data

                        end if

                        offset = offset + res_header_size + res_data_size
                        if offset and 11b
                                offset = offset + 4 - offset and 11b
                        end if
                end while

        end resource_directory

end macro

And I have placed these macros in PE.INC that comes with fasmg examples.

Note that it is possible to pass name in place of id to "resource_data" macro, but this name is expected to be Unicode string. If you want to use an ANSI or UTF-8 string there, you need to write an additional wrapper that would do something like:

Code:
        virtual at 0
                du 'ASSIGN'
                load name:$ from 0
        end virtual

        resource_data RT_BITMAP,name,LANG_NEUTRAL
                file 'assign.bmp':0Eh
        end resource_data

Post 13 May 2017, 23:47
View user's profile Send private message Visit poster's website Reply with quote
Grom PE



Joined: 13 Mar 2008
Posts: 113
Location: i@grompe.org.ru
Wrote a macro for fasmg to load .ico or .cur files. IDs of the icons start from the specified one and up. Make sure not to include multiple-icon files with sequential IDs, or there will be a conflict.

Code:
macro resource_icon path*,id*,lang:0
  local icon_file,group_type,icon_count,icon_group,type
  local icon,icon_size,icon_offs

  virtual at 0
    icon_file:: file path
  end virtual

  load group_type:2 from icon_file:2
  load icon_count:2 from icon_file:4
  if group_type = 2
    type = 1 ; RT_CURSOR
  else
    type = 3 ; RT_ICON
  end if

  resource_data type+11,id,lang ; RT_... + 11 = RT_GROUP_...
    dw 0,group_type,icon_count
    repeat icon_count
      load icon_group:12 from icon_file:(%-1)*16+6
      db icon_group
      dw id+(%-1)
    end repeat
  end resource_data

  repeat icon_count
    load icon_size:4 from icon_file:(%-1)*16+6+8
    load icon_offs:4 from icon_file:(%-1)*16+6+12
    resource_data type,id+(%-1),lang
      load icon:icon_size from icon_file:icon_offs
      db icon
    end resource_data
  end repeat
end macro

Usage:

Code:
resource_directory
  resource_icon "my.ico",10
end resource_directory

Post 15 May 2017, 18:26
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.