flat assembler
Message board for the users of flat assembler.

Index > Windows > [solved] COM IAudioEndpointVolume

Author
Thread Post new topic Reply to topic
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 09 May 2021, 20:51
Hi
I have trouble with this interface. All methods works except any of SetVolume. If it's scalar the volume drops to zero, if dB to max. I do try to migrate volume level from one device to another.
Code:
.data
IID_IAudioEndpointVolume        GUID 5CDF2C82-841E-4546-9722-0CF74078229A

interface           IAudioEndpointVolume,\
                    QueryInterface,\
                    AddRef,\
                    Release,\
                    RegisterControlChangeNotify,\
                    UnregisterControlChangeNotify,\
                    GetChannelCount,\
                    SetMasterVolumeLevel,\
                    SetMasterVolumeLevelScalar,\
                    GetMasterVolumeLevel,\
                    GetMasterVolumeLevelScalar,\
                    SetChannelVolumeLevel,\
                    SetChannelVolumeLevelScalar,\
                    GetChannelVolumeLevel,\
                    GetChannelVolumeLevelScalar,\
                    SetMute,\
                    GetMute,\
                    GetVolumeStepInfo,\
                    VolumeStepUp,\
                    VolumeStepDown,\
                    QueryHardwareSupport,\
                    GetVolumeRange,\
                    GetVolumeRangeChannel

MasterVolume dd 0.5f    ;for example

.code
cominvk pAudioVolumeOut,SetMasterVolumeLevelScalar,\
                [MasterVolume],0
    

I tried to use separate enumerator/pDevice from other parts of project by Factory, tried to set the value manually, tried to set it from GetVolume methods, tried to use different devices even by GetDefaultAudioEndpoint, tried to use different CLSCTX, tried to use ISimpleAudioVolume it drops it's sessin volume exactly the same way. If it's Volume per channel then it drops the volume of current channel.

I have one temporary solution to change the volume by VolumeStepUp/VolumeStepDown where it's different between two devices:
Code:
.data
        pEnumeratorVolume               IMMDeviceEnumerator
        pDeviceVolumeIn                 IMMDevice
        pDeviceVolumeOut                IMMDevice
        pAudioVolumeIn                  IAudioEndpointVolume
        pAudioVolumeOut                 IAudioEndpointVolume
        pVolumeNotify                   IAudioEndpointVolumeCallback
        MasterMute                      db ?
        MasterMuteIn                    db ?
        ;MasterVolume                   dd ?
        MasterVolumeIn                  dd ?
        MasterVolumeOut                 dd ?
        fMultiplier                     dd 100
.code
proc VolumeProc,lpParam
        local   MasterVolume:DWORD
        invoke  CoInitializeEx,0,0
        invoke  CoCreateInstance,CLASS_MMDeviceEnumerator,0,CLSCTX_ALL,\
                IID_IMMDeviceEnumerator,pEnumeratorVolume
        cominvk pEnumeratorVolume,GetDevice,RegKeyCaptureID,\
                pDeviceVolumeIn
        cominvk pEnumeratorVolume,GetDevice,RegKeyRenderID,\
                pDeviceVolumeOut
        cominvk pDeviceVolumeIn,Activate,IID_IAudioEndpointVolume,\
                CLSCTX_ALL,0,pAudioVolumeIn
        cominvk pDeviceVolumeOut,Activate,IID_IAudioEndpointVolume,\
                CLSCTX_ALL,0,pAudioVolumeOut
LoopVolume:
        cominvk pAudioVolumeIn,GetMasterVolumeLevelScalar,\
                MasterVolumeIn
        fld     [MasterVolumeIn]
        fimul   [fMultiplier]
        fistp   [MasterVolumeIn]
        mov     eax,[MasterVolumeIn]
        cmp     [MasterVolume],eax
        je      @F3
        mov     [MasterVolume],eax
        cominvk pAudioVolumeOut,GetMasterVolumeLevelScalar,\
                MasterVolumeOut
        fld     [MasterVolumeOut]
        fimul   [fMultiplier]
        fistp   [MasterVolumeOut]
        mov     eax,[MasterVolumeOut]
        cmp     eax,[MasterVolumeIn]
        ja      @F1
        jb      @F2
        je      @F3
        @@@:
                cominvk pAudioVolumeOut,VolumeStepDown,0
                cominvk pAudioVolumeOut,GetMasterVolumeLevelScalar,\
                        MasterVolumeOut
                fld     [MasterVolumeOut]
                fimul   [fMultiplier]
                fistp   [MasterVolumeOut]
                mov     eax,[MasterVolumeOut]
                cmp     eax,[MasterVolumeIn]
                ja      @B1
                jmp     @F2
        @@@:
                cominvk pAudioVolumeOut,VolumeStepUp,0
                cominvk pAudioVolumeOut,GetMasterVolumeLevelScalar,\
                        MasterVolumeOut
                fld     [MasterVolumeOut]
                fimul   [fMultiplier]
                fistp   [MasterVolumeOut]
                mov     eax,[MasterVolumeOut]
                cmp     eax,[MasterVolumeIn]
                jb      @B1
        @@@:
        cominvk pAudioVolumeIn,GetMute,MasterMuteIn
        mov     al,[MasterMuteIn]
        cmp     al,[MasterMute]
        je      @F1
                mov     [MasterMute],al
                cominvk pAudioVolumeOut,SetMute,[MasterMute],0
        @@@:
        cmp     [RegKeyEngineOrder],ENGINE_ORDER_ON
        jne     TerminatorVolume
        invoke  Sleep,100
        jmp     LoopVolume
TerminatorVolume:
        cominvk pAudioVolumeIn,Release
        cominvk pAudioVolumeOut,Release
        cominvk pDeviceVolumeIn,Release
        cominvk pDeviceVolumeOut,Release
        cominvk pEnumeratorVolume,Release
        invoke  CoUninitialize
        invoke  ExitThread,0
ret
endp    


Last edited by Overclick on 11 May 2021, 17:13; edited 1 time in total
Post 09 May 2021, 20:51
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 May 2021, 11:17
It need a null GUID - which is a pointer to 16 zero bytes.
(Or rather the working example I built needed that.)

This line in the documentation appears to be wrong:
Quote:
If the caller supplies a NULL pointer for this parameter, the notification routine receives the context GUID value GUID_NULL.
Caller should supply pointer to GUID_NULL.
Post 10 May 2021, 11:17
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 12:58
I did it with GUID_NULL, no difference. Look at SetMute one, it works just fine.
As I understand, when caller sets NULL it automatically implements to GUID_NULL
...
Just checked again to clear up any doubts


Description:
Filesize: 5.81 KB
Viewed: 11828 Time(s)

Capture.PNG


Post 10 May 2021, 12:58
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 May 2021, 13:38
Does this work on your machine?
Maybe you see some difference?


Description: Volume Control
Download
Filename: Epvolume.zip
Filesize: 10.54 KB
Downloaded: 430 Time(s)


_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 10 May 2021, 13:38
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 13:39
I tried to run that thread as only COM stuff of entire process. Everything else was disabled. Just virgin Volume control. GetVolume --> SetVolume --> Breakpoint
The result all the same.
Post 10 May 2021, 13:39
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 13:41
bitRAKE wrote:
Does this work on your machine?
Maybe you see some difference?

Your example works fine.
Post 10 May 2021, 13:41
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 May 2021, 13:46
COM doesn't return an error? I tend to step through with a debugger, verify vtbl offsets (to insure interface is defined correctly), etc.
Post 10 May 2021, 13:46
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 13:47
hr = g_pEndptVol->RegisterControlChangeNotify(
(IAudioEndpointVolumeCallback*)&EPVolEvents);
Maybe it needs bloody callback?
Post 10 May 2021, 13:47
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 13:49
No errors, I check it hundreds times. Everything seems to be working.
Post 10 May 2021, 13:49
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 May 2021, 13:51
The callback looks trivial - only one method beyond IUnknown interface. Definitely worth a try.

Edit: It looks like the local pointer for GUID_NULL is being used to identify local notifications in the event loop. S_OK is sent as long as the notification is not null. Nice, so there is two-way communication with the callback. Definitely required.
Post 10 May 2021, 13:51
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 15:43
I have no experience for callback. It drops application to deadend when I try to register it.
Code:
cominvk pAudioVolumeOut,RegisterControlChangeNotify,pVolumeNotify
    

Could you translate it to assembly please?
Post 10 May 2021, 15:43
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 May 2021, 17:46
It should look something like this (untested):
Code:
define MyCallback
namespace MyCallback

; this also needs to be in your address space and writeable
; wrapped in namespace to isolate it

object:
        pvtbl           dq vtbl
        refCount        dd ?,?

vtbl:
        QueryInterface  dq ?
        AddRef          dq ?
        Release         dq ?
        OnNotify        dq ?



QueryInterface:
        test rdx,rdx
        jz .E_INVALIDARG
        push rcx

        ; compare IID to all extended interfaces

        mov rax,[rdx]
        mov rcx,[rdx+8]
        iterate iid, IUnknown,IAudioEndpointVolumeCallback
                cmp [IID_#iid],rax
                jnz @f
                cmp [IID_#iid+8],rcx
                jz .found
        @@:
        end iterate
        pop rcx
        and qword [r8],0
        mov eax,E_NOINTERFACE
        retn
.E_INVALIDARG:
        and qword [r8],0
        mov eax,E_INVALIDARG
        retn
.found:
        pop rcx
        mov [r8],rcx
        call AddRef
        xor eax,eax
        retn


AddRef:
        push 1
        pop rax
        lock xadd [rcx - MyCallback.object + MyCallback.object.refCount],eax
@@:     add eax,1
        retn


Release:
        push -1
        pop rax
        lock xadd [rcx - MyCallback.object + MyCallback.object.refCount],eax
        jnz @f

        ; TODO: delete memory used by object

        xor eax,eax
        retn

@@:     sub eax,1
        retn


OnNotify:
        test rdx,rdx ; AUDIO_VOLUME_NOTIFICATION_DATA
        jz .E_INVALIDARG
        mov rax,[MyContext]
        cmp [rdx],rax
        jnz .other
        mov rax,[MyContext+8]
        cmp [rdx+8],rax
        jz .self
.other:
        ; process our messages

.self:  xor eax,eax ; S_OK
        retn

.E_INVALIDARG:
        mov eax,E_INVALIDARG
        retn

end namespace



; put this somewhere in your address space and send it instead of null
MyContext rb 16 ; GUID_NULL
; could cheat and use an easy GUID for callback, lol
MyContext dq 1,2    
There is only one callback so we create it statically, and access it like this:

cominvk pAudioVolumeOut,RegisterControlChangeNotify,ADDR MyCallback.object

edit: there are some errors because I adapted my dynamic object template. maybe I have fixed most of them? my logic was reversed - it's messages from other's we need to respond to in callback.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 10 May 2021, 17:46
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 19:52
Oh, I think I understand. Just need to reconstruct your example little bit for fasm1. Thanks a lot.
Post 10 May 2021, 19:52
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 10 May 2021, 20:50
Obviously you need to put your functions in the vector table.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 10 May 2021, 20:50
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 10 May 2021, 21:34
I'm working on it
Code:
.data
        struct OBJECT
                pvtbl                   dq $+16
                refCount                dd ?,?
                vtbl                    = $
                QueryInterface  dq VolumeCallBackQueryInterface
                AddRef          dq VolumeCallBackAddRef
                Release         dq VolumeCallBackRelease
                OnNotify        dq VolumeCallBackOnNotify
        ends
        VolumeCallBack          OBJECT
        IID_VolumeCallBack      GUID A1ECF000-FEEE-0000-0000-CA11BAC0BDEC
.code
        VolumeCallBackQueryInterface:
                        test rdx,rdx
                        jz .E_INVALIDARG
                        push rcx
                        irp IID,IID_IUnknown,\
                                IID_IAudioEndpointVolumeCallback
                        {       cmp [IID],rax
                                jne @f
                                cmp [IID+8],rcx
                                je .found  }
                        pop rcx
                        and qword [r8],0
                        mov eax,E_NOINTERFACE
                        ret 0           
                
                .E_INVALIDARG:
                        and qword [r8],0
                        mov eax,0x80070057
                        ret 0
                .found:
                        pop rcx
                        mov [r8],rcx
                        call VolumeCallBackAddRef
                        xor eax,eax
                        ret 0
        VolumeCallBackAddRef:
                        push 1
                        pop rax
                        lock xadd [rcx-VolumeCallBack+VolumeCallBack.refCount],eax
                @@:     add eax,1
                        ret 0
        VolumeCallBackRelease:
                        push -1
                        pop rax
                        lock xadd [rcx-VolumeCallBack+VolumeCallBack.refCount],eax
                        jnz @f
                        
                        ; TODO: delete memory used by object
                        
                        xor eax,eax
                        ret 0
                @@:     sub eax,1
                        ret 0
        VolumeCallBackOnNotify:
                        test rdx,rdx ; AUDIO_VOLUME_NOTIFICATION_DATA
                        jz .E_INVALIDARG
                        mov rax,[IID_VolumeCallBack]
                        cmp [rdx],rax
                        jnz .other
                        mov rax,[IID_VolumeCallBack+8]
                        cmp [rdx+8],rax
                        jz .self
                .other:
                        ; process our messages
                .self:  
                        xor eax,eax ; S_OK
                        ret 0
                .E_INVALIDARG:
                        mov eax,0x80070057
                        ret 0    


Could you check this code? No errors form calls, but the problem still the same.
Code:
cominvk pAudioVolumeOut,RegisterControlChangeNotify,VolumeCallBack
;S_OK
cominvk pAudioVolumeOut,SetMasterVolumeLevelScalar,[MasterVolumeIn],IID_VolumeCallBack
;S_OK
    

I checked Notifications. It's working when other application changes the volume. So callback is ok or almost ok. But volume still drop down at Set methods.
Post 10 May 2021, 21:34
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 11 May 2021, 13:36
Makes me think the float conversion is off. Maybe the fasm macro is converting it to double and the function wants float?

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 11 May 2021, 13:36
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 11 May 2021, 15:43
I think about it
Code:
macro cominvk object,proc,[arg]
 { common
    assert defined object#.com.object ; must be a COM object
    macro call dummy
    \{ mov rax,[rcx]
       call [rax+object#.#proc] \}
    fastcall ,[object],arg
    purge call }    

Code:
macro fastcall proc,[arg]
 { common local stackspace,argscount,counter
    if argscount < 4
     stackspace = 4*8
    else if argscount and 1
     stackspace = (argscount+1)*8
    else
     stackspace = argscount*8
    end if
    counter = 0
    if stackspace
     if defined current@frame
      if current@frame<stackspace
       current@frame = stackspace
      end if
     else
      if stackspace
       sub rsp,stackspace
      end if
     end if
    end if
   forward
    counter = counter + 1
    define type@param
    define definition@param arg
    match =float value,definition@param
    \{ define definition@param value
       define type@param float \}
    match =addr value,definition@param
    \{ define definition@param value
       define type@param addr \}
    match any=,any,definition@param
    \{ \local ..string,..continue
       jmp ..continue
       align sizeof.TCHAR
       ..string TCHAR definition@param,0
       ..continue:
       define definition@param ..string
       define type@param addr \}
    match any,definition@param
    \{ match \`any,any
       \\{ \\local ..string,..continue
           jmp ..continue
           align sizeof.TCHAR
           ..string TCHAR definition@param,0
           ..continue:
           define definition@param ..string
           define type@param addr \\} \}
    match param,definition@param
    \{ local opcode,origin
       size@param = 0
       if param eqtype 0 | param eqtype 0f | type@param eq addr
        size@param = 8
       else if param eqtype byte 0 | param eqtype byte 0f
        match prefix value,definition@param
         \\{ if prefix eq qword
              size@param = 8
             else if prefix eq dword
              size@param = 4
             else if prefix eq word
              size@param = 2
             else if prefix eq byte
              size@param = 1
             end if \\}
       else if ~ param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
        virtual
         origin = $
         inc param
         load opcode byte from origin
         if opcode = 67h | opcode = 41h
          load opcode byte from origin+1
         end if
         if opcode and 0F8h = 48h
          size@param = 8
         else if opcode = 66h
          size@param = 2
         else if opcode = 0FFh
          size@param = 4
         else
          size@param = 1
         end if
        end virtual
       end if
       if counter = 1
        if type@param eq float
         if ~ param eq xmm0
          if size@param = 4
           if param eqtype byte 0 | param eqtype byte 0f
            mov eax,param
            movd xmm0,eax
           else
            movd xmm0,param
           end if
          else
           if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
            mov rax,param
            movq xmm0,rax
           else
            movq xmm0,param
           end if
          end if
         end if
         if vararg@fastcall & ~ param eq rcx
           movq rcx,xmm0
         end if
        else if type@param eq addr
         if ~ param eq rcx
          lea rcx,[param]
         end if
        else if size@param = 8
         if ~ param eq rcx
          mov rcx,param
         end if
        else if size@param = 4
         if ~ param eq ecx
          xor rcx,rcx
          mov ecx,param
         end if
        else if size@param = 2
         if ~ param eq cx
          xor rcx,rcx
          mov cx,param
         end if
        else if size@param = 1
         if ~ param eq cl
          xor rcx,rcx
          mov cl,param
         end if
        end if
       else if counter = 2
        if type@param eq float
         if ~ param eq xmm1
          if size@param = 4
           if param eqtype byte 0 | param eqtype byte 0f
            mov eax,param
            movd xmm1,eax
           else
            movd xmm1,param
           end if
          else
           if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
            mov rax,param
            movq xmm1,rax
           else
            movq xmm1,param
           end if
          end if
         end if
         if vararg@fastcall & ~ param eq rdx
           movq rdx,xmm1
         end if
        else if type@param eq addr
         if ~ param eq rdx
          lea rdx,[param]
         end if
        else if size@param = 8
         if ~ param eq rdx
          mov rdx,param
         end if
        else if size@param = 4
         if ~ param eq edx
          xor rdx,rdx
          mov edx,param
         end if
        else if size@param = 2
         if ~ param eq dx
          xor rdx,rdx
          mov dx,param
         end if
        else if size@param = 1
         if ~ param eq dl
          xor rdx,rdx
          mov dl,param
         end if
        end if
       else if counter = 3
        if type@param eq float
         if ~ param eq xmm2
          if size@param = 4
           if param eqtype byte 0 | param eqtype byte 0f
            mov eax,param
            movd xmm2,eax
           else
            movd xmm2,param
           end if
          else
           if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
            mov rax,param
            movq xmm2,rax
           else
            movq xmm2,param
           end if
          end if
         end if
         if vararg@fastcall & ~ param eq r8
           movq r8,xmm2
         end if
        else if type@param eq addr
         if ~ param eq r8
          lea r8,[param]
         end if
        else if size@param = 8
         if ~ param eq r8
          mov r8,param
         end if
        else if size@param = 4
         if ~ param eq r8d
          xor r8,r8
          mov r8d,param
         end if
        else if size@param = 2
         if ~ param eq r8w
          xor r8,r8
          mov r8w,param
         end if
        else if size@param = 1
         if ~ param eq r8b
          xor r8,r8
          mov r8b,param
         end if
        end if
       else if counter = 4
        if type@param eq float
         if ~ param eq xmm3
          if size@param = 4
           if param eqtype byte 0 | param eqtype byte 0f
            mov eax,param
            movd xmm3,eax
           else
            movd xmm3,param
           end if
          else
           if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
            mov rax,param
            movq xmm3,rax
           else
            movq xmm3,param
           end if
          end if
         end if
         if vararg@fastcall & ~ param eq r9
           movq r9,xmm3
         end if
        else if type@param eq addr
         if ~ param eq r9
          lea r9,[param]
         end if
        else if size@param = 8
         if ~ param eq r9
          mov r9,param
         end if
        else if size@param = 4
         if ~ param eq r9d
          xor r9,r9
          mov r9d,param
         end if
        else if size@param = 2
         if ~ param eq r9w
          xor r9,r9
          mov r9w,param
         end if
        else if size@param = 1
         if ~ param eq r9b
          xor r9,r9
          mov r9b,param
         end if
        end if
       else
         if type@param eq addr
          lea rax,[param]
          mov [rsp+(counter-1)*8],rax
         else if param eqtype [0] | param eqtype byte [0]
          if size@param = 8
           mov rax,param
           mov [rsp+(counter-1)*8],rax
          else if size@param = 4
           mov eax,param
           mov [rsp+(counter-1)*8],eax
          else if size@param = 2
           mov ax,param
           mov [rsp+(counter-1)*8],ax
          else
           mov al,param
           mov [rsp+(counter-1)*8],al
          end if
         else if size@param = 8
          virtual
           origin = $
           mov rax,param
           load opcode byte from origin+1
          end virtual
          if opcode = 0B8h
           mov rax,param
           mov [rsp+(counter-1)*8],rax
          else
           mov qword [rsp+(counter-1)*8],param
          end if
         else if param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
          movq [rsp+(counter-1)*8],param
         else
          mov [rsp+(counter-1)*8],param
         end if
       end if \}
   common
    argscount = counter
    call proc
    if stackspace & ~defined current@frame
     add rsp,stackspace
    end if }    

Have to check it up
Post 11 May 2021, 15:43
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 669
Location: Ukraine
Overclick 11 May 2021, 15:49
Finally I fixed my interface calls by 'float' mark
Code:
cominvk pAudioVolumeOut,SetMasterVolumeLevelScalar,\
                        float [MasterVolumeIn],IID_VolumeCallBack
    

But have it be like that? Is it fasm bug?
Post 11 May 2021, 15:49
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4060
Location: vpcmpistri
bitRAKE 11 May 2021, 20:32
You just didn't realize default parameter size in 64-bit is 64-bit - and that applies to float/double. In 32-bit it would have been float and worked, lol. You will know next time though. And you have the callback now, and play nice with other applications.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 11 May 2021, 20:32
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 11 May 2021, 20:41
bitRAKE wrote:
You just didn't realize default parameter size in 64-bit is 64-bit - and that applies to float/double. In 32-bit it would have been float and worked, lol.
It would have worked, but for a different reason - with 64-bit fastcall the "float" keyword changes the register that is used to pass the parameter. For float values the XMM0/XMM1/XMM2/XMM3 registers are used instead of RCX/RDX/R8/R9 respectively. The keyword is therefore required in 64-bit case (see the documentation), to let the macro know that it should pass the given value as a float, using an SSE register instead of general-purpose one.
Post 11 May 2021, 20:41
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.