1. Blank Window (Tile Engine)
- Posted by Icy_Viking Apr 22, 2023
- 827 views
Hello,
I'm wondering if anyone could help with this. When I tried making an example using my Tile Engine wrapper. The image/background that is supposed to appear doesn't show up. The window comes up with just a blank screen. I have what I have written so far bundled in zip file. The wrapper isn't finished just yet, but very close. Other things that might help I'm using the 32-bit DLL and using Windows 11 Pro and Euphoria 4.1.0 Beta 2 32-Bit.
https://katfile.com/9ie8g3zj4l8t/te.zip.html - Wrapped so far
https://github.com/megamarc/Tilengine - In case it is needed.
// Simple C Example, converted to Eu code below #include "Tilengine.h" void main(void) { TLN_Tilemap foreground; TLN_Init (400, 240, 1, 0, 0); foreground = TLN_LoadTilemap ("assets/sonic/Sonic_md_fg1.tmx", NULL); TLN_SetLayerTilemap (0, foreground); TLN_CreateWindow (NULL, 0); while (TLN_ProcessWindow()) { TLN_DrawFrame (0); } TLN_DeleteTilemap (foreground); TLN_Deinit (); }
include std/ffi.e include tilengine.e TLN_Init(400,240,1,0,0) atom fg = TLN_LoadTilemap("Sonic_md_fg1.tmx","") ? fg TLN_SetLayerTilemap(0,fg) TLN_CreateWindow("",0) while TLN_ProcessWindow() do TLN_DrawFrame(0) end while TLN_DeleteTilemap(fg) TLN_Deinit()
2. Re: Blank Window (Tile Engine)
- Posted by irv Apr 22, 2023
- 743 views
I don't think "" is a NULL in Euporia.
3. Re: Blank Window (Tile Engine)
- Posted by Icy_Viking Apr 22, 2023
- 768 views
I don't think "" is a NULL in Euporia.
In the C code it is declared as a string and I wrapped using the C_STRING keyword.
4. Re: Blank Window (Tile Engine)
- Posted by jimcbrown (admin) Apr 23, 2023
- 729 views
I don't think "" is a NULL in Euporia.
Agreed, these are different things. The formmer is an array of one length, basically ['\-0'] while the latter is .. well, null.
In the C code it is declared as a string
NULL can be passed into strings (I guess you are referring to char pointers actually, I don't believe C has an actual string type).
and I wrapped using the C_STRING keyword.
Which works fine with NULL as well.
Perhaps the empty string would work also, perhaps not, but the important point is that they are, and look, different to the C code that gets called.
5. Re: Blank Window (Tile Engine)
- Posted by irv Apr 23, 2023
- 717 views
What is this C_STRING keyword?
I thought we had to use allocate_string() for that.
6. Re: Blank Window (Tile Engine)
- Posted by Icy_Viking Apr 23, 2023
- 720 views
What is this C_STRING keyword?
I thought we had to use allocate_string() for that.
I'm using Greg's FFI library for it. It allows for supports of structs and a C_STRING Greg made that takes of string allocation for you. So if you use the FFI library you don't need to use the allocate_string() command.
FFI Library: https://github.com/ghaberek/libffi-euphoria
See this wrapper for examples of structs being wrapped: https://github.com/gAndy50/EuRayLib4/blob/main/Include/raylib.e
7. Re: Blank Window (Tile Engine)
- Posted by ghaberek (admin) Apr 24, 2023
- 697 views
As Irv pointed out there is absolutely a distinction between NULL and a pointer to an empty string. The latter has a value while the former does not. Unfortunately some C libraries will double-check if strings are NULL or empty but just as many will accept an empty string as a valid string (because it is) and the resulting behavior may be different or altogether broken. Typically, C string parameter that can accept NULL should be specified as an object parameter in the Euphoria wrapper, so that it can accept NULL when necessary and treat empty strings separately.
I'm working on baking C_STRING (and C_WSTRING) into std/ffi.e so we can avoid a bunch of repetitive boilerplate code like this:
constant _wrapper_func = define_c_func( lib, "wrapper_func", {C_POINTER,C_POINTER}, C_POINTER ) public function wrapper_func( object required_string, object optional_string=NULL ) if sequence( required_string ) then required_string = allocate_string( required_string, TRUE ) end if if sequence( optional_string ) then optional_string = allocate_string( optional_string, TRUE ) end if return c_func( _wrapper_func, {required_string,optional_string} ) end function
And instead just pass the values and let c_func() handle the allocate/free as necessary:
constant _wrapper_func = define_c_func( lib, "wrapper_func", {C_STRING,C_STRING}, C_POINTER ) public function wrapper_func( object required_string, object optional_string=NULL ) return c_func( _wrapper_func, {required_string,optional_string} ) end function
However, this feature will gladly ignore any atom it receives and pass it along verbatim, which will respect NULL as NULL and also so you can allocate your own strings and pass them along. This would be useful for pre-allocating strings, such as preloading resources from a file or to avoid the overhead of repetitive memory allocation. I will be notating all of this in my documentation for std/ffi.e as well as adding a "mini-guide" to the docs for tips on wrapping C libraries and structures. The guide is mostly going to be written by way of collecting these recent conversations into a more concise format.
-Greg
8. Re: Blank Window (Tile Engine)
- Posted by Icy_Viking Apr 24, 2023
- 675 views
OK I changed the wrapper code to objects and the example code to objects. Still the background image does not appear. Everything else appears to work fine.
Wrapper
public atom tile = 0 ifdef WINDOWS then tile = open_dll("Tilengine.dll") elsifdef LINUX or FREEBSD then tile = open_dll("libTilengine.so") end ifdef export constant xTLN_Init = define_c_func(tile,"+TLN_Init",{C_INT,C_INT,C_INT,C_INT,C_INT},C_POINTER) public function TLN_Init(atom hres,atom vres,atom numlayers,atom numsprites,atom numani) return c_func(xTLN_Init,{hres,vres,numlayers,numsprites,numani}) end function export constant xTLN_Deinit = define_c_proc(tile,"+TLN_Deinit",{}) public procedure TLN_Deinit() c_proc(xTLN_Deinit,{}) end procedure export constant xTLN_CreateWindow = define_c_func(tile,"+TLN_CreateWindow",{C_STRING,C_INT},C_BOOL) public function TLN_CreateWindow(object overlay,atom flags) return c_func(xTLN_CreateWindow,{overlay,flags}) end function export constant xTLN_LoadTilemap = define_c_func(tile,"+TLN_LoadTilemap",{C_STRING,C_STRING},C_POINTER) public function TLN_LoadTilemap(sequence fname,object lname) return c_func(xTLN_LoadTilemap,{fname,lname}) end function export constant xTLN_SetLayerTilemap = define_c_func(tile,"+TLN_SetLayerTilemap",{C_INT,C_POINTER},C_BOOL) public function TLN_SetLayerTilemap(atom l,object tm) return c_func(xTLN_SetLayerTilemap,{l,tm}) end function
Example
without warning without type_check include std/ffi.e include tilengine.e TLN_Init(400,240,1,0,0) object fg = TLN_LoadTilemap("Sonic_md_fg1.tmx",NULL) ? fg TLN_SetLayerTilemap(0,fg) TLN_CreateWindow(NULL,0) while TLN_ProcessWindow() do TLN_DrawFrame(0) end while TLN_DeleteTilemap(fg) TLN_DeleteWindow() TLN_Deinit()
9. Re: Blank Window (Tile Engine)
- Posted by ghaberek (admin) Apr 25, 2023
- 660 views
As a test, I ported Tutorial.c to Euphoria and got the same problem. When I checked the result of TLN_SetLayerTilemap() it was returning zero, so I grabbed the last error and printed it out:
atom tilemap = TLN_LoadTilemap( "assets/sonic/Sonic_md_fg1.tmx" ) if not TLN_SetLayerTilemap( 0, tilemap ) then integer errno = TLN_GetLastError() sequence errmsg = TLN_GetErrorString( errno ) printf( 2, "Error %d: %s\n", {errno,errmsg} ) end if
Tilengine v2.14.0 64-bit built Feb 1 2023 19:08:33 Error 6: Invalid Tileset reference
I think you need to all of the assets as they seem to reference each other. You'd probably have to open them with Tiled to see what-references-what since the content is all base64/zlib encoded.
Once I extracted the entire assets directory and updated the path to "assets/sonic/Sonic_md_fg1.tmx" your demo worked correctly. At the very least, you probably need the contents of the sonic folder.
-Greg
10. Re: Blank Window (Tile Engine)
- Posted by Icy_Viking Apr 25, 2023
- 660 views
As a test, I ported Tutorial.c to Euphoria and got the same problem. When I checked the result of TLN_SetLayerTilemap() it was returning zero, so I grabbed the last error and printed it out:
atom tilemap = TLN_LoadTilemap( "assets/sonic/Sonic_md_fg1.tmx" ) if not TLN_SetLayerTilemap( 0, tilemap ) then integer errno = TLN_GetLastError() sequence errmsg = TLN_GetErrorString( errno ) printf( 2, "Error %d: %s\n", {errno,errmsg} ) end if
Tilengine v2.14.0 64-bit built Feb 1 2023 19:08:33 Error 6: Invalid Tileset reference
I think you need to all of the assets as they seem to reference each other. You'd probably have to open them with Tiled to see what-references-what since the content is all base64/zlib encoded.
Once I extracted the entire assets directory and updated the path to "assets/sonic/Sonic_md_fg1.tmx" your demo worked correctly. At the very least, you probably need the contents of the sonic folder.
-Greg
You were right Greg. At the very least I needed the sonic folder and it showed up.
Updated example
without warning without type_check include std/ffi.e include tilengine.e TLN_Init(400,240,1,0,0) object fg = TLN_LoadTilemap("sonic/Sonic_md_fg1.tmx",NULL) ? fg if fg = -1 then puts(1,"Failed to load background!\n") abort(0) end if TLN_SetLayerTilemap(0,fg) TLN_CreateWindow(NULL,0) while TLN_ProcessWindow() do TLN_DrawFrame(0) end while TLN_DeleteTilemap(fg) TLN_DeleteWindow() TLN_Deinit()