Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Using compressed resources

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

Previous topic - Next topic


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, 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.

% include &ObjMemPath&Common\

; ——————————————————————————————————————————————————————————————————————————————————————————————————
; 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.

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
  invoke DecompressFileFromRes, hInst, xResourceID
  invoke DecompressFileFromRes, rcx, rdx
  .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
        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
      MemFree pFileData
  mov xax, hCursor
CreateCursorFromCompressedFileInRes endp

For the ObjMem library, a shared .inc file called 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