Page 1 of 3

IrrLicht without wrapper DLL

Posted: Wed May 11, 2005 4:19 pm
by traumatic
By the first look at the Irrlicht engine I was convinced it was possible
to use the original DLL from PureBasic even without writing a wrapper
DLL beforehand (Hey Dracflamloc!:)).

I tried using interfaces but failed.

Yet there had to be a way...


Here's something I came up with by accident:

Code: Select all

;
;
; "Es werde Licht!" - "Let there be light!" - Irrlicht in PB ?
;
;


;
Procedure.l L(string.s)
  *out = AllocateMemory(lstrlen_(string)*4)
  MultiByteToWideChar_(#CP_ACP, 0, string, -1, *out, lstrlen_(string))
  ProcedureReturn *out
EndProcedure

;
Procedure.l Irr_Device_setWindowCaption(device.l, caption.l)
  !MOV esi, dword [esp]
  !MOV edx, [esi]
  !MOV eax, dword [edx+44]
  !MOV ecx, esi  
  !PUSH dword [esp+4]
  !CALL eax
EndProcedure

;
Procedure.l Irr_Device_isWindowActive(device.l)
  !MOV esi, dword [esp]
  !MOV edx, [esi]
  !MOV eax, dword [edx+48]
  !MOV ecx, esi  
  !CALL eax
  ProcedureReturn
EndProcedure

;
Procedure.l Irr_Device_run(device.l)
  !MOV esi, dword [esp]
  !MOV edx, dword [esi]
  !MOV eax, dword [edx+4]
  !MOV ecx, esi 
  !CALL eax
  ProcedureReturn
EndProcedure

;
Procedure.l Irr_Device_getVideoDriver(device.l)
  !MOV esi, dword [esp]
  !MOV edx, dword [esi]
  !MOV eax, dword [edx+8]
  !MOV ecx, esi 
  !CALL eax
  ProcedureReturn
EndProcedure

;
Procedure.l Irr_Device_getGUIEnvironment(device.l)
  !MOV esi, dword [esp]
  !MOV edx, dword [esi]
  !MOV eax, dword [edx+16]
  !MOV ecx, esi 
  !CALL eax
  ProcedureReturn
EndProcedure

;
Procedure.l Irr_Driver_beginScene(driver.l, backBuffer.l, zBuffer.l, color.l)
  !MOV esi, dword [esp]
  !MOV edx, dword [esi]
  !MOV eax, dword [edx+4]
  !MOV ecx, esi
  !PUSH dword [esp+12]
  !PUSH dword [esp+8]
  !PUSH dword [esp+4]
  !CALL eax
  ProcedureReturn
EndProcedure

;
Procedure.l Irr_Driver_endScene(driver.l)
  !MOV esi, dword [esp]
  !MOV edx, dword [esi]
  !MOV eax, dword [edx+8]
  !MOV ecx, esi
  !CALL eax
  ProcedureReturn
EndProcedure


;
;
;

IrrDLL.l = OpenLibrary(#PB_Any, "Irrlicht.dll")

d.POINT
d\x = 640
d\y = 480
*device = CallFunction(IrrDLL, "createDevice", 2, d, 16, #False, #False, #False, 0)

*driver = Irr_Device_getVideoDriver(*device)
*guienv = Irr_Device_getGUIEnvironment(*device)

Irr_Device_setWindowCaption(*device, L("Wello Horld!"))


;
While Irr_Device_run(*device)
  If Irr_Device_isWindowActive(*device)
    Irr_Driver_beginScene(*driver, 0, 0, $00000070)
    ;
    ; render something here
    ;
    Irr_Driver_endScene(*driver)
  EndIf
  
  Sleep_(10)
Wend


CloseLibrary(IrrDLL)
End
Maybe someone will find this useful, I have no real clue about
what I'm doing here - it just works... ;)

I'd be glad if someone could tell me what has to be done in order
to make it work with PB's interfaces. Thanks in advance.

Posted: Wed May 11, 2005 7:18 pm
by dracflamloc
You couldn't get interfaces to work? Hm... thats sad I was gonna try that...

Posted: Thu May 12, 2005 8:21 am
by dige
Nice work, but only a blank screen and a window title? ;-)
I believe the master of 3D can do much more, isn't it?

Posted: Thu May 12, 2005 8:38 am
by traumatic
dracflamloc wrote:You couldn't get interfaces to work? Hm... thats sad I was gonna try that...
Well, I still don't know what I did wrong.
I must have interpreted the classes wrong or something.
The only way I got this working was how I showed above.
Everything else just crashed.

It would be cool if someone else could take a look this.
Accessing Irrlicht directly from PB without any wrapper-DLL
would be the best way to work with that engine IMHO.

Maybe a good chance for a real community project?

dige wrote:I believe the master of 3D can do much more, isn't it?
Master of 3D? Who's that?
In case you're refering to me, thanks for the flattery :D

lol, it's no fun to code like this. ;)

Posted: Thu May 12, 2005 10:54 am
by El_Choni
PB pushes the Interface pointer when calling methods, whilst this dll, from what I see in your code, puts that pointer in ecx instead. So, when returning, the stack is unbalanced by 4. Also, the called method will be using the wrong arguments.

I suggest that you recompile this dll, if it's open source, using PB scheme. Or wait for PB to handle macros.

Posted: Thu May 12, 2005 7:37 pm
by traumatic
Thanks for the explanation, El_Choni!
Recompiling the DLL however is no real option IMHO.

Posted: Thu May 12, 2005 9:14 pm
by El_Choni
You can solve this problem using Fasm macros right now. I'll have a look to see if I can get the proper macro code.

Posted: Thu May 12, 2005 10:40 pm
by Fred
That's a strange convention to use ecx as object handler (not bad, but why doing something different than COM ?). May be it's possible to switch a compiler option when building the DLL to generate COM interfaces ?

Posted: Fri May 13, 2005 4:06 pm
by traumatic
I don't know how they translate to asm but could it be it's because
of the heavy usage of namespaces?

Posted: Fri May 13, 2005 4:38 pm
by El_Choni
The code with PB Interfaces would look like this (as you may already have tried):

NOTE: this code won't work as it is.

Code: Select all

XIncludeFile "Macros.pb"

Interface IrrlichtDevice
  IrrlichtDevice()
  run()
  getVideoDriver()
  getFileSystem()
  getGUIEnvironment()
  getSceneManager()
  getCursorControl()
  getLogger()
  getVideoModeList()
  getOSOperator()
  getTimer()
  setWindowCaption(text)
  isWindowActive()
  closeDevice()
  getVersion()
  setEventReceiver(receiver)
  getEventReceiver()
  setResizeAble(resize)
EndInterface

Interface IVideoDriver
  IVideoDriver()
  beginScene(backBuffer, zBuffer, color)
  endScene()
EndInterface ; We don't need the rest of the members in this example

Procedure.l L(string.s)
  *out = AllocateMemory(lstrlen_(string)*4)
  MultiByteToWideChar_(#CP_ACP, 0, string, -1, *out, lstrlen_(string))
  ProcedureReturn *out
EndProcedure

IrrDLL.l = OpenLibrary(#PB_Any, "Irrlicht.dll")
If IrrDLL
  d.POINT
  d\x = 640
  d\y = 480
  *device.IrrlichtDevice = CallFunction(IrrDLL, "createDevice", 2, d, 16, #False, #False, #False, 0)
  If *device
    *driver.IVideoDriver = *device\getVideoDriver()
    *guienv = *device\getGUIEnvironment()
    *device\setWindowCaption(L("Wello Horld!"))
    If *driver
      While *device\run()
        If *device\isWindowActive()
          *driver\beginScene(1, 0, $00000070)
          ;
          ; render something here
          ;
          *driver\endScene()
        EndIf
        Sleep_(10)
      Wend
    EndIf
  EndIf
  CloseLibrary(IrrDLL)
EndIf
End 
Purebasic generates this ASM for the methid calls:

Code: Select all

  PUSH   eax
  MOV    eax, [eax]
  CALL   dword [eax+?] ; method offset
So you need a Fasm macro that translates every ocurrence of the above to:

Code: Select all

  MOV   ecx, eax
  MOV    eax, [eax]
  CALL   dword [eax+?] ; method offset
I know this can be done with Fasm macros, but I don't know how.

Posted: Sat May 14, 2005 2:14 pm
by traumatic
El_Choni: Yes, that looks exactly like my interface approach ;)

I don't understand what you mean by utlizing macros as I don't see how
that could change the way PB generates its asm-output. Are you thinking
about a macro simulating the actual interface behaviour (but using different
calls) ?


Thanks for looking into this. It's not that I personally can't live without
Irrlicht but IMHO it would be good to prove it's possible to have it working
straight from PB.

Your help is very much appreciated, thank you!

Posted: Sat May 14, 2005 4:49 pm
by Fred
It should be possible to do a quick ASM post processor to detect this pattern and change it, right (in place) ?

Posted: Sat May 14, 2005 6:41 pm
by El_Choni
@traumatic: the PB compiler generates ASM output that is fed into Fasm.exe. If you insert a Fasm macro escaped with '!', Fasm will apply it.

Fasm does several passes when needed, and you can change the ASM source using Fasm macros.

Anyway, as Fred says, this would be very easy to handle for the PB compiler, so better wait to see if Fred implements it, if there's not a hurry (doesn't seem so ;).

Posted: Sat May 14, 2005 11:42 pm
by Fred
I probably won't implement it in PB as it seems to be only for this purpose..

Posted: Mon May 16, 2005 2:08 pm
by traumatic
Thanks El_Choni! I works the way you suggested (of course ;)).

Image