BlitzExtensions - Really Extending Blitz

Blitz3D Forums/Blitz3D Userlibs/BlitzExtensions - Really Extending Blitz

Xaymar(Posted 2015) [#1]
BlitzExtensions
BlitzExtensions is a collection of User Libraries for the Blitz language, allowing you to do many additional things previously locked away from you.

License: Lesser GPL v3
Links: Project Source

Library: BlitzPointer
BlitzPointer allows you to get the pointers of a Blitz function and use these to your advantage. Ever wanted to call a DLL function that requires a callback but didn't know C++? BlitzPointer can help you there, as Blitz functions are __stdcall-able!

License: Lesser GPL v3
Links: Binary Releases | Library Source

Library: BlitzSteam
BlitzSteam brings the Steamworks API to the Blitz language or any other language unable to call __cdecl functions. Integrate your game with Steam by using the Workshop, HTMLSurface or Steam Networking - everything the Steamworks API offers is at your disposal.

In order to use or compile this library you need to be a registered Steamworks developer. Steamworks restrictions will still apply.

License: Lesser GPL v3
Links: Binary Releases | Library Source

Library: BlitzUtility
BlitzUtility gives you access to many extra 'Utility' functionality: ObjectList, TypeList, SQLite3, LongLong, Double, DisplayEnumerator, Indexers, WindowMessageHandler. For exact descriptions of what each does, check out README.md in the library source.

License: Lesser GPL v3
Links: Binary Releases | Library Source


Hotshot2005(Posted 2015) [#2]
Excellent work there :)


Ploppy(Posted 2015) [#3]
Yes, smart stuff.


Xaymar(Posted 2015) [#4]
@Ploppy:
May I ask you something? I've figured out some things in Blitz (Variables, Functions, Types) but I can't wrap my head around strings. It just doesn't make sense to me, as Blitz functions recieve a pointer to a structure with a pointer to a cstring inside, or that's what I think it does. Is this actually what happens?


Ploppy(Posted 2015) [#5]
In c++, strings in Blitz3d are handled by the BBStr class, I think it is the same in B+. Here is the class declaration in all it's beauty for example..

struct BBStr : public std::string{
	BBStr *next,*prev;

	BBStr();
	BBStr( const char *s );
	BBStr( const char *s,int n );
	BBStr( const BBStr &s );
	BBStr( const std::string &s );
	BBStr &operator=( const char *s );
	BBStr &operator=( const BBStr &s );
	BBStr &operator=( const std::string &s );
	~BBStr();

	void *operator new( size_t size );
	void operator delete( void *q );

	void *operator new( size_t size,const char *file,int line ){ return operator new( size ); }
	void operator delete( void *q,const char *file,int line ){ operator delete( q ); }
};


As you can see, the class is a derivative of the std::string class, the actual string itself can be retrieved with the class's c_str() function, and the string length by the length() function.

The internal workings of blitz process strings by passing pointers between functions. However, for userlibs, the char * method is used to pass strings, conversion happens between 'char *' and 'BBStr *' before and after calling a userlib function if needed.


Xaymar(Posted 2015) [#6]
That means I have to temporarily create a BBStr object to pass the string to a blitz function, allowing even strings to be passed. Alright, thanks for clearing that up.

Edit 1: Or retrieve the one that contains the original.
Edit 2: On second thought, it might be better to just disable string return and passing until I found a proper way to handle it.
Edit 3: I'm surprised my solution even worked like it did.
Edit 4: I have no idea how to pass strings to a blitz function. It either crashes or ends up being empty (which is better than a crash though).


Ploppy(Posted 2015) [#7]
You'll need a bit of c++ code to convert it, something like

#include <string>
using namespace std;

string * ConvertToBBStr(char * input)
{
    string * output=new string(input);
    return output;
}


This code for example will convert a char * string to a std::string type.

To convert it back to char * try something like

#include <windows.h>
#include <string>
using namespace std;

char * ConvertToChar(string * input)
{
    char * output= new char[input->length()];
    memcpy (output,input->c_str(),input->length());
    return output;
}



Xaymar(Posted 2015) [#8]
@Ploppy:

If only that worked, that was one of the first things I tried. Sibly's BBStr is simply too different to be cast to a std::string:

        | 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
--------+------------------------------------------------
00000000| 65 00 00 00 ?? ?? ?? ?? 0B 00 00 00 1F 00 00 00
00000010| <varying>

Offset 0 is always the same 0x65 (0x00000065), after that there's a int32_t/intptr_t to a c-style string and then we have the weird 0x0B and 0x1F. This can't be directly casted to a std::string.
If I substract 8 from the returned pointer, I can cast it to a std::string, though it seems to cause Blitz to go back a few instructions in memory and repeat it over and over. Edit: forgot to mention that the casted std::string is wrong.

Edit: Here's a better view of the memory around the returned pointer:

0x004BB5F0 is the returned pointer.

Edit: Upon further investigation, it seems that using BlitzPointer near the end of the program causes the repeat. Probably because I was using __cdecl instead of __stdcall by accident.
Edit 2: I'll just take out those functions until further notice.


Xaymar(Posted 2015) [#9]
I uploaded version 1.1 of the DLL just now, changelog
1.1 - 15/05/2015
- [New] Added and updated Examples
- [New] Added functions for Direct Memory Access (DMA)
- [Fix] Fixed memory leak when returning strings by removing the functions for now. (It was a bug anyway, should never have worked.)
- [Fix] Hopefully fixed the backwards instruction jump caused by using BlitzPointer by using __stdcall.

If I figure out how to properly do strings, I'll probably add additional functions to pass them as pointers with manual cleanup.


eNano(Posted 2015) [#10]
Hi!
I don't know much about coding so I post this just in case is useful
This is how I've got the content of a string field based on other posts, I understood that is read only data

;Create the object
Type testType
	Field FirstField%
	Field SecondField$
End Type

testInstance.testType = New testType
testInstance\FirstField = 10
testInstance\SecondField = "FieldContent"


;Get the Type Pointer:
instancePTR = Int(testInstance)

;Get First Field Pointer: (just as an example)
firstFieldPTR = ( instancePTR + 20 )

;Get Second Field Pointer:
secondFieldPTR = ( instancePTR + 20 ) + 4

;Get Pointer from second Field Pointer:
stringPTR = MemoryPeekInt(secondFieldPTR)
;Get length of string:
stringLength = MemoryPeekInt( stringPTR + 8 )
;Get location of the characters:
CharsPTR = MemoryPeekInt(stringPTR + 4)

;Get each character:
For n = 0 To ( stringLength - 1 )
	theString$ = theString$ + Chr( MemoryPeekByte( CharsPTR + n  ) )
Next

Print theString

I hope this help


Xaymar(Posted 2015) [#11]
So, some news. The pointers retrieved by BlitzPointer should be directly callable as __stdcall functions, requiring no intermediate functions. No guarantee that it works though, haven't been able to test it due to an odd bug (Blitz3D won't load DLLs from the /userlibs/ folder anymore).

Edit: __stdcall Test successful:


Xaymar(Posted 2015) [#12]
BlitzPointer just received a much needed update and is now at version 1.4.0, featuring Variable-pointers and a few fixes.

Changelog:
* Upgraded to Visual Studio 2015
* Fixed broken .Decls file (missing parameter).
* Implemented Variable-pointers (BP_GetVariablePointerInt, BP_GetVariablePointerFloat, BP_GetVariablePointerType)
* Fixed BP_GetReturnAddress returning the wrong address.
* Fixed BP_GetFunctionPointer being unstable by using a more intelligent design.
* Reduced overall usage of raw asm instruction to just reading the BasePointer.
* Added Example 8 - Variable-pointers.

Binaries & Source Code: Here

Screenshot:



PSY(Posted 2016) [#13]
@Xaymar

I just stumbled on your BlitzSteam Library.

Some time ago, I wrote a game in B3B and sold a handful of copies, winning a bet in the process. 2014, I uploaded it on Steam Greenlight, just to get some experience with the Steam system.
2 days ago, I received an eMail from Valve, saying the game has been greenlit.

Now I want to add some achievements to the game.
My knowledge of C is literally ZERO, but I understand I can implement achievements in a B3D project with your library?

That would be really awesome...

Thanks in advance,
PSY

P.S. I tried to contact you by your website, but it seems to be down/emtpy...


Xaymar(Posted 2016) [#14]
@PSY

Indeed, almost all Steam Interfaces are available to you. Achievements, Statistics, Leaderboards, Networking, etc. I've included some examples for the APIs I understand, the rest is almost pure native C wrapper.

You can reach me via michael.fabian.dirks@..., I'm currently moving servers.


PSY(Posted 2016) [#15]
@Xaymar

Awesome, thanks alot.

I really appreciate that!!