News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Using compressed resources

Started by Biterider, November 04, 2023, 10:56:25 PM

Previous topic - Next topic

Biterider

Hi
Based on the excellent work of fearless, who wrote a compressor/decompressor using onboard algorithms of the operating system, I wrote some procedures for the ObjMem library to extract them from the resource section.
One of these has been explained here https://masm32.com/board/index.php?topic=11371.msg124825#msg124825, which is used to extract compressed icons.

Large cursor resources are not used that often, but when they are, a similar approach can be taken. Some minor changes had to be made to handle the cursor API calls and the hotspot coordinates.

.code
% include &ObjMemPath&Common\CursorIconStructs.inc

; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Procedure:  CreateCursorFromCompressedFileInRes
; Purpose:    Create an cursor from a compressed cursor file stored as RCDATA resource.
;             Compression should be done using a Microsoft compression algorithm: XPRESS, XPRESS
;             with Huffman encoding, MSZIP or LZMS.
; Arguments:  Arg1: hInstance.
;             Arg2: Resource ID.
;             Arg3: Desired cursor width.
;             Arg3: Desired cursor height.
; Return:     xax = Cursor HANDLE.

align ALIGN_CODE
CreateCursorFromCompressedFileInRes proc uses xbx xdi xsi hInst:HINSTANCE, xResourceID:XWORD, \
                                                          dDesiredCx:DWORD, dDesiredCy:DWORD
  local pFileData:POINTER, dFileDataSize:DWORD
  local hCursor:HCURSOR, pRsrcDirectory:PGRP_HEADER

  mov hCursor, 0
if TARGET_BITNESS eq 32
  invoke DecompressFileFromRes, hInst, xResourceID
else
  invoke DecompressFileFromRes, rcx, rdx
endif
  .if xax != NULL
    mov pFileData, xax
    mov xsi, xax
    mov dFileDataSize, ecx
    .if WORD ptr [xsi].GRP_HEADER.wResType == RES_CURSOR
      ;Replicate in memory the structure created by the resource compiler
      movzx edi, [xsi].GRP_HEADER.wResCount
      mov eax, sizeof(GRP_RSRC_ENTRY)
      mul edi
      add eax, sizeof(GRP_HEADER)
      MemAlloc eax
      .if xax != NULL
        mov pRsrcDirectory, xax
        s2s GRP_HEADER ptr [xax], GRP_HEADER ptr [xsi], xcx, xdx
        add xax, sizeof(GRP_HEADER)
        add xsi, sizeof(GRP_HEADER)
        xor ebx, ebx
        .while ebx < edi
          s2s GRP_ENTRY_BEG ptr [xax], GRP_ENTRY_BEG ptr [xsi], xcx, xdx, xmm0, xmm1
          mov [xax].GRP_RSRC_ENTRY.nIconCursorId, bx
          add xax, sizeof(GRP_RSRC_ENTRY)
          add xsi, sizeof(GRP_FILE_ENTRY)
          inc ebx
        .endw
        invoke LookupIconIdFromDirectoryEx, pRsrcDirectory, FALSE, \
                                            dDesiredCx, dDesiredCy, LR_DEFAULTCOLOR
        mov ecx, sizeof(GRP_FILE_ENTRY)
        mul xcx
        add xax, pFileData
        add xax, sizeof(GRP_HEADER)
        mov ecx, [xax].GRP_FILE_ENTRY.dOffset
        add xcx, pFileData
        ;Prepend LOCALHEADER to the cursor data & adjust the data size
        sub xcx, sizeof LOCALHEADER
        m2m [xcx].LOCALHEADER.wHotSpotX, [xax].GRP_FILE_ENTRY.wHotSpotX, dx
        m2m [xcx].LOCALHEADER.wHotSpotY, [xax].GRP_FILE_ENTRY.wHotSpotY, dx
        mov edx, [xax].GRP_FILE_ENTRY.dwBytesInRes
        add edx, sizeof LOCALHEADER
        invoke CreateIconFromResourceEx, xcx, edx, FALSE, 30000h, \
                                         dDesiredCx, dDesiredCy, LR_DEFAULTCOLOR or LR_SHARED
        mov hCursor, xax
        MemFree pRsrcDirectory
      .endif
      MemFree pFileData
    .endif
  .endif
  mov xax, hCursor
  ret
CreateCursorFromCompressedFileInRes endp

For the ObjMem library, a shared .inc file called CursorIconStructs.inc has been introduced to avoid multiple and possibly inconsistent definitions across other files.

Extracting bitmaps is much easier thanks to the use of the code template of fearless CD project.

Attached you will find a demo binary that shows how the cursor can be changed, in this case with the mouse wheel, whereby the shape of the cursor changes slightly when switching from one resource cursor to the next.

Regards, Biterider