flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > rsrc directory macro with named resources support & strcmp |
Author |
|
ProMiNick 11 May 2017, 16:06
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 |
|||
11 May 2017, 16:06 |
|
Tomasz Grysztar 11 May 2017, 18:44
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.
|
|||
11 May 2017, 18:44 |
|
ProMiNick 11 May 2017, 23:06
I don`t mind new syntax. I can join to think under realization, but I no idea about how new syntax should looks like.
|
|||
11 May 2017, 23:06 |
|
Tomasz Grysztar 12 May 2017, 13:30
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. |
|||
12 May 2017, 13:30 |
|
Tomasz Grysztar 12 May 2017, 18:20
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.
|
|||
12 May 2017, 18:20 |
|
Tomasz Grysztar 13 May 2017, 23:47
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 Resource: rb 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 1, i:Resource_root.counter Resource_root.entry#i = type Resource_root.offset#i = (Resource_#%type - Resource) or 80000000h end repeat Resource_root.counter = Resource_root.counter + 1 match list, RESOURCE_DIRECTORIES_LIST define RESOURCE_DIRECTORIES_LIST list,Resource_#%type end match Resource_#%type.counter = 0 end if repeat 1, i:Resource_#%type.counter Resource_#%type.entry#i = id Resource_#%type.offset#i = (Resource_#%type#_#%id - Resource) or 80000000h end repeat Resource_#%type.counter = Resource_#%type.counter + 1 match list, RESOURCE_DIRECTORIES_LIST define RESOURCE_DIRECTORIES_LIST list,Resource_#%type#_#%id end match Resource_#%type#_#%id.counter = 0 end if repeat 1, i: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 1, i: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 1, i: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 list, RESOURCE_DIRECTORIES_LIST iterate dir, list 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 1, i:z, j: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 dir, list store %t : 4 at dir + 4 dir.names_counter = 0 repeat dir.counter, i: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 - Resource) or 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.counter, i: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 Code: resource_directory resource_data RT_BITMAP,1,LANG_NEUTRAL file 'assign.bmp':0Eh end resource_data end resource_directory 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 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 |
|||
13 May 2017, 23:47 |
|
Grom PE 15 May 2017, 18:26
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 Code: resource_directory resource_icon "my.ico",10 end resource_directory |
|||
15 May 2017, 18:26 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.