flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [fasmg] ICO file image directory display:

Author
Thread Post new topic Reply to topic
bitRAKE



Joined: 21 Jul 2003
Posts: 4249
Location: vpcmpistri
bitRAKE 01 Sep 2021, 10:49
Code:
; fasmg.exe -n -i "ico equ 'RamXP.ico'" ICO_dir.asm

; List/Audit ICO File Image Characteristics:

; First Support Version for Various Features:
;       + Win95/WinNT4 image size of 256x256 (stored as zero)
;       + WinXP auto-corrects bColorCount of zero
;       + WinXP ARGB format 32bpp images
;       + WinXP down-sampling of 256x256 images
;       + Vista PNG format, but not .ICL icon libraries
;
; Many ICO tools don't correctly store the image directory - which is
; important for default icon selection in several API functions.

match _,DISPLAY 10 ; just lazy typing
virtual ; create address space with file data
ICO:: file ico
.sizeof := $

; ICONHEADER
load type:dword from 0
assert type = 0x10000 ; only .ICO file for now
;assert type = 0x20000 ; .CUR
load images:word from 4

_,      'file name: ',ico
_,      '       type:   .ICO'

iterate f,STAR,95,XP,VISTA
        FLAG.f := 1 shl %
end iterate

repeat images
if % = 1 ; initialize
NOTES = 0
_,      '       images: ',`%%,10
_,      'ICONDIRENTRY(s):'
_,      '         W x H   |colors|planes| BPP|  bytes  |  offset'
;       '       256 x 256 | 2^32 |    0 | 32 | 9999999 | 99999999 9XV*
end if
        notes = 1 ; just to avoid an 'if', bit 0 is not used
        load bWidth             : byte from (% shl 4)-10 + 0
        load bHeight            : byte from (% shl 4)-10 + 1
        load bColorCount        : byte from (% shl 4)-10 + 2
        load bReserved          : byte from (% shl 4)-10 + 3
        load wPlanes            : word from (% shl 4)-10 + 4
        load wBitCount          : word from (% shl 4)-10 + 6
        load dwBytesInRes       :dword from (% shl 4)-10 + 8
        load dwImageOffset      :dword from (% shl 4)-10 + 12

        ; check if image is PNG
        load png:qword from dwImageOffset
        if png = $0A1A0A0D'474E50'89
                notes = notes or FLAG.VISTA
        else
                ; documentation states member use of BITMAPINFOHEADER as:
                ; biSize, biWidth, biHeight, biPlanes, biBitCount, biSizeImage

                ; calculate actual color use from BITMAPINFOHEADER
        end if

        if bWidth = 0
                bWidth = 256
                notes = notes or FLAG.95
        end if
        if bHeight = 0
                bHeight = 256
                notes = notes or FLAG.95
        end if
        if wBitCount = 32
                notes = notes or FLAG.XP
        end if

        _,9
        FIELD bWidth,3
        display ' x '
        FIELD bHeight,-3

        ; XP will calculate value, but not during search
        if bColorCount = 0
                bColorCount = wBitCount * wPlanes
                if bColorCount < 8
                        notes = notes or FLAG.XP or FLAG.STAR
                        display ' |  '
                        if bColorCount
                                bColorCount = 1 shl bColorCount
                        else
                                bColorCount = 256
                        end if
                        FIELD bColorCount,3
                else if bColorCount > 9
                        display ' | 2^'
                        FIELD bColorCount,2
                else
                        display ' |  '
                        bColorCount = 1 shl bColorCount
                        FIELD bColorCount,3
                end if
        else
                display ' |  '
                FIELD bColorCount,3
        end if

        display ' |'
        FIELD wPlanes,5
        display ' |'
        FIELD wBitCount,3
        display ' |'
        FIELD dwBytesInRes,8
        display ' |'
        FIELD dwImageOffset,8
        display ' '

        ; only keep most significant OS flag and bit 1 (FLAG_!)
        notes = ((1 shl (bsr notes)) or (notes and 2)) and -2
        NOTES = NOTES or notes
        iterate n,'*','9','X','V'
                while notes > 0
                        indx bsr notes
                        notes = notes xor (1 shl (bsr notes))
                        display n
                end while
                break
        end iterate
end repeat
_
iterate n,\
        '* note: incorrect color count',\
        '9 note: requires Windows 95/NT4 or greater',\
        'X note: requires Windows XP or greater',\
        'V note: PNG requires Windows Vista or greater'
        while NOTES > 0
                indx bsr NOTES
                NOTES = NOTES xor (1 shl (bsr NOTES))
                _,n
        end while
        break
end iterate
end virtual
end match


macro FIELD value*,width:0,fill:' '
        local text
        virtual at 0
                if width > 0 ; right-justify
                        db width dup (fill)
                end if

                if value < 0
                        db '-'
                        repeat 1,N:-value
                                db `N
                        end repeat
                else
                        repeat 1,N:value
                                db `N
                        end repeat
                end if

                if width = 0 ; raw output
                        load text:$ from 0
                else if width < 0 ; left-justify
                        ; don't show a fragment
                        if $ > -width
                                db '?'
                                db -width dup (fill)
                                load text:-width from $+width-1
                        else
                                db -width dup (fill)
                                load text:-width from 0
                        end if
                else ; right-justify
                        ; don't show a fragment
                        if $ > width shl 1
                                db width dup (fill)
                                db '?'
                        end if
                        load text:width from $ - width
                end if
        end virtual
        display text
end macro    
When there is missing data windows takes longer to find the correct icon - if it finds it (output sample):
Code:
file name: RamXP.ico
        type:   .ICO
        images: 6

ICONDIRENTRY(s):
          W x H   |Colors|Planes|BPP |  bytes  |  offset
         32 x 32  |   16 |    0 |  0 |     744 |     102
         16 x 16  |   16 |    0 |  0 |     296 |     846
         48 x 48  |   16 |    0 |  0 |    1640 |    1142
         32 x 32  |  256 |    0 |  0 |    2216 |    2782 X*
         48 x 48  |  256 |    0 |  0 |    3752 |    4998 X*
         16 x 16  |  256 |    0 |  0 |    1384 |    8750 X*

X note: requires Windows XP or greater
* note: incorrect color count    

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup


Last edited by bitRAKE on 01 Sep 2021, 19:34; edited 1 time in total
Post 01 Sep 2021, 10:49
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8427
Location: Kraków, Poland
Tomasz Grysztar 01 Sep 2021, 16:37
bitRAKE wrote:
Code:
        while notes > 0
                iterate n,'*','9','X','V'
                        indx bsr notes
                        display n
                        break
                end iterate
                notes = notes xor (1 shl (bsr notes))
        end while    
That's a nice little pattern! You could also save a bit of processing by swapping the order of WHILE with ITERATE (not really important here, but perhaps worth keeping in mind):
Code:
iterate n,'*','9','X','V'
        while notes > 0
                indx bsr notes
                display n
                notes = notes xor (1 shl (bsr notes))
        end while
        break
end iterate    
Post 01 Sep 2021, 16:37
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4249
Location: vpcmpistri
bitRAKE 01 Sep 2021, 19:27
Thank you. Was thinking towards creating a tool to audit my ICO/CUR archive. First, I need to correctly reverse engineer the directory entries from the BITMAPINFOHEADER and grok all the broken values from the ICO files collected from various sources. The later part is probably more cumbersome. I might discover some rules unpublished. This is a start.

The PNG decoder in Windows is actually quite fast (beats open source implementations in tests). So, for new projects in Vista+ there should be no other choice, imho.

This ICO file has a complete directory and is probably compatible with Win9x+:
Code:
file name: FloppyDisk.ico
        type:   .ICO
        images: 16

ICONDIRENTRY(s):
          W x H   |colors|planes| BPP|  bytes  |  offset
         48 x 48  |   16 |    1 |  4 |    1640 |     262
         32 x 32  |   16 |    1 |  4 |     744 |    1902
         24 x 24  |   16 |    1 |  4 |     488 |    2646
         20 x 20  |   16 |    1 |  4 |     424 |    3134
         16 x 16  |   16 |    1 |  4 |     296 |    3558
         48 x 48  |  256 |    1 |  8 |    3752 |    3854
         32 x 32  |  256 |    1 |  8 |    2216 |    7606
         24 x 24  |  256 |    1 |  8 |    1736 |    9822
         20 x 20  |  256 |    1 |  8 |    1544 |   11558
         16 x 16  |  256 |    1 |  8 |    1384 |   13102
        256 x 256 | 2^32 |    1 | 32 |  270376 |   14486 X
         48 x 48  | 2^32 |    1 | 32 |    9640 |  284862 X
         32 x 32  | 2^32 |    1 | 32 |    4264 |  294502 X
         24 x 24  | 2^32 |    1 | 32 |    2440 |  298766 X
         20 x 20  | 2^32 |    1 | 32 |    1720 |  301206 X
         16 x 16  | 2^32 |    1 | 32 |    1128 |  302926 X

X note: requires Windows XP or greater    
Don't know why the images are sorted in reverse. Maybe to stop search on versions of windows before WinXP at the 256x256 image. This appears to be common though.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 01 Sep 2021, 19:27
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


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.