PDA

View Full Version : My Native Library



Brandon
02-27-2014, 01:47 AM
UPDATE:
Added Garbage cleanup debug to demonstrate that there are no leaks!
Also made images export the pixel functions in the BGRA format: NOT RGBA!
Images should NOT throw exceptions anymore, make sure to get if their handle is valid or their width and height are greater than 0.


I call it the Riddler library..

Here are 80+ functions to spice up your scripting life and interact directly with the OS and do things natively..

Windows: 26676
Linux: 23257


Function ReleaseGC(const ptr: Pointer): Boolean;
Function ReleaseGC(const str: String): Boolean; overload;
Function ErrorMessage(Error: UInt32; Throw: Boolean = False): PChar;
Function QuickHammingDistance(const First, Second: String): UInt32;
Function HammingDistance(const First, Second: String): UInt32;
Function LevenshteinDistance(const First, Second: String): UInt32;
Function UTF8ToUTF16(const utf8: AnsiString): PWChar;
Function UTF16ToUTF8(const utf16: UnicodeString): PChar;
Function GetProcessModuleInfo(const ProcessName: String): PChar;
Function EncodeBase64(const Data: String): PChar;
Function DecodeBase64(const Data: String): PChar;
Function CRCGenerateTable: PtrUInt;
Function CRCLookUpTable: PtrUInt;
Function Adler32(const Data: Byte; Size: UInt32): UInt32;
Function CRC32Checksum(const Data: Byte; Size, InitialValue: UInt32 = $EDB88320): UInt32;
Function GetWindowHandle(const WindowName, WindowClass: String): PtrUInt;
Function GetChildWindowHandle(Parent, Child: PtrUInt; const WindowName, ClassName: String): PtrUInt;
Function GetDesktopWindowHandle: PtrUInt;
Procedure GetWindowSize(WindowHandle: PtrUInt; var Width, Height: Integer);
Function GetPID: Integer;
Procedure AppendWindowText(WindowHandle: PtrUInt; const Text: String);
Function WindowHandleFromPoint(p: TPoint): PtrUInt;
Function ChildWindowHandleFromPoint(Parent: PtrUInt; p: TPoint): PtrUInt;
Function FindMainWindow(PID: UInt32): PtrUInt;
Function GetWindowParent(Child: PtrUInt): PtrUInt;
Function SetWindowParent(Parent, Child: PtrUInt): PtrUInt;
Function GetPreviousWindow(WindowHandle: PtrUInt): PtrUInt;
Function GetNextWindow(WindowHandle: PtrUInt): PtrUInt;
Function GetDisplayDevices: PChar;
Function GetPrimaryDisplayDevice: DISPLAY_DEVICE;
Function GetDisplaySettings(Index: Integer): PChar;
Procedure SetDefaultDisplaySettings;
Function SetDisplayResolution(Width, Heignt: Integer): Boolean;
Function CreateMemoryMap(const MapName: String; Size: UInt32): Pointer;
Function OpenMemoryMap(const MapName: String; Size: UInt32): Pointer;
Function CreateNewEvent(lpEventAttributes: ^SECURITY_ATTRIBUTES; bManualReset, bInitialState: Boolean; const EventName: String): PtrUInt;
Function OpenSingleEvent(const EventName: String; InheritHandle: Boolean; dwDesiredAccess: UInt32 = EVENT_ALL_ACCESS; dwMilliseconds: UInt32 = INFINITE): UInt32;
Function SetEventSignal(const EventName: String; Signaled: Boolean): Boolean;
Function DeleteEvent(const EventName: String): Boolean;
Procedure FlipImage(InPtr: Pointer; var OutPtr: Pointer; Width, Height: Integer; BitsPerPixel: UInt32);
Function MessageBoxTimeOut(Parent: PtrUInt; const lpText, lpCaption: String; uType, dwMilliseconds: UInt32; wLanguageID: Word = 0): Integer;
Function ReverseNumber(Number: Int64): Int64;
Function GetEnvironmentVariable(const Variable: String): PChar;
Function SetEnvironmentVariable(const VariableName, VariableValue: String): Boolean;
Function QSort(Base: Pointer; Num, Size: UInt32; Compar: Function(const a, b: Pointer): Integer): Integer;
Procedure SetWindowTransparency(Window: PtrUInt; Transparency: Byte);
Function GetProcessInfo(const ProcessName: String): PROCESSENTRY32;
Function IsProcessRunning(const ProcessName: String): Boolean;
Function ProcessInfoToString(Proc32: PROCESSENTRY32): PChar;
Function GetModulesInfo(ProcessID: UInt32): Array Of MODULEENTRY32;
Function GetModuleInfo(ProcessID: UInt32; const ModuleName: String): MODULEENTRY32;
Function ModuleInfoToString(Mod32: MODULEENTRY32): PChar;
Function RunApplication(const ApplicationName, ApplicationArguments: String; WaitInputIdle: Boolean): Boolean;
Function StartService(const szServiceName: String): Boolean;
Function StopService(const szServiceName: String): Boolean;
Function CreateRegistryKey(Root: Pointer; const SubRoot, KeyName: String; KeyType: REG_KEY_TYPE; const InitialValue: String; samDesired: Integer = 0): Boolean;
Function DeleteRegistryKey(Root: Pointer; const KeyToRemove: String; samDesired: Integer = 0): Boolean;
Function DeleteRegistryValue(Root: Pointer; const SubRoot, KeyToRemove: String; samDesired: Integer = 0): Boolean;
Function SetRegistryKey(Root: Pointer; const SubRoot, KeyToEdit, NewValue: String; KeyType: REG_KEY_TYPE; samDesired: Integer = 0): Boolean;
Function ReadRegistryKey(Root: PtrUInt; const SubRoot, KeyToRead: String; KeyType: REG_KEY_TYPE; var Str: array of char; samDesired: Integer = 0): Integer;
Function GetDriveInfo(const Drive: String; var FreeSpace, TotalSpace: Word; InGigaBytes: Boolean = False): Boolean;
Function GetTypeOfDrive(const Drive: String): PChar;
Function GetLogicalDrivesList(const Drives: array[0..25] of char): Integer;
Function CreateThread(FunctionToPass: Pointer): Integer;
Procedure DetachThread(ThreadID: Integer);
Procedure JoinThread(ThreadID: Integer);
Procedure ClearThreads(Join: boolean);
Function ThreadHardwareConcurrency: Integer;
Function NativeThreadID(ThreadID: Integer): Int64;
Procedure SleepThreadFor(Milliseconds: Integer);
Procedure YieldThread;
Function CreateAsync(FunctionToPass: Pointer): Integer;
Procedure ClearAsync;
Procedure WaitAsync(AsyncID: Integer);
Function WaitForAsync(AsyncID, Milliseconds: Integer): Boolean;
Function CreateLock: Integer;
Procedure RemoveLock(LockID: Integer);
Procedure Lock(LockID: Integer);
Function TryLock(LockID: Integer): Boolean;
Procedure Unlock(LockID: Integer);
Procedure GlobalLock;
Function GlobalTryLock: Boolean;
Procedure GlobalUnlock;
Procedure ClearLocks;
Function CreateImage(Width, Height: Integer): Integer;
Function LoadImage(FilePath: String): Integer;
Function ImageFromPointer(Ptr: Pointer; Width, Height: Integer): Integer;
Function ImageFromCursor: Integer;
Function ImageFromWindow(WndHandle: PtrUInt; X, Y, Width, Height: Integer): Integer;
Procedure DrawToWindow(ImageID: Integer; WndHandle: PtrUInt; X, Y, Width, Height, SourceX, SourceY: Integer = 0; RasterType: Integer = $00CC0020);
Procedure SaveImage(ImageID: Integer; FilePath: String);
Procedure DeleteImage(ImageID: Integer);
Function GetImagePixel(ImageID, X, Y: Integer): Integer;
Function GetImagePixels(ImageID: Integer; var Width, Height: Integer): Pointer;
Procedure SetImagePixel(ImageID, Colour, X, Y: Integer);
Procedure GetImageDimensions(ImageID: Integer; var Width, Height: Integer);
Procedure ClearImages;


Was originally written for Java and C# but meh..

http://i.imgur.com/XOgAQud.png

Flight
02-27-2014, 02:08 AM
Wow those look like a lot of fun actually. Threads... I'd love to see an example. "Get/SetEnvironmentVariable" that's handy for SMART, "SetWindowTransparency" :stirthepot:.

Very cool Brandon. I'd really like to see some visual examples.

Brandon
02-27-2014, 02:35 AM
Wow those look like a lot of fun actually. Threads... I'd love to see an example. "Get/SetEnvironmentVariable" that's handy for SMART, "SetWindowTransparency" :stirthepot:.

Very cool Brandon. I'd really like to see some visual examples.


The threading & locking are some functions I wrote a while back: http://villavu.com/forum/showthread.php?t=103201&p=1276025#post1276025

http://i.imgur.com/8Xo9TfM.png

Simba has a new function exported in it called GetWindowHandle or GetNativeWindowHandle accessed through: getTClient().IOManager


For other functions, it should be fairly straight forward:


var
Desktop: PtrUInt;
Img: Integer;
begin
Desktop := GetDesktopWindowHandle();
Img := LoadImage('C:/Users/Brandon/Desktop/Test.bmp'); //Can use ImageFromPointer to pass a Simba Image and draw that on any window.
DrawToWindow(Img, Desktop);
end.



Will draw an image on your desktop or ANY window. You can also draw on the browser by passing the GetNativeWindowHandle as the parameter instead of GetDesktopWindowHandle.

If you want to find windows by title then GetWindowHandle will do that.


HammingDistance and LevenshteinDistance will tell you how close two strings are to eachother. The lower the value, the more accurate the matches are:

http://en.wikipedia.org/wiki/Hamming_distance
http://en.wikipedia.org/wiki/Levenshtein_distance

These are used as "Fuzzy" string matching.. I was using it to find similar words..

For example loading the plugin in Java I did:


if (args[0].equals("en") || args[0].equals("all")) {
String questions[] = new String[]{"What's up bro", "How are you doing", "How are you", "What are you doing"};

test("Ho yu ding", questions); //Prints: "How are you doing"
test("Ho yu dng", questions); //Prints: "How are you doing"
test("Ho yu dig", questions); //Prints: "How are you doing"
test("o yu dng", questions); //Prints: "How are you"
test("What o yu dng", questions); //Prints: "What are you doing"
System.out.println("\n-------------------------------------------------------------------------\n");
}

public static String test(String question, String[] questions) {
NativeParser parser = new NativeParser();
ArrayList<Integer> hdists = new ArrayList<>();
ArrayList<Integer> ldists = new ArrayList<>();

for (String q : questions) {
hdists.add(parser.quickHammingDistance(question, q));
ldists.add(parser.levenshteinDistance(question, q));
}

int hindex = min_index(hdists);
int lindex = min_index(ldists);

System.out.println("1. " + questions[hindex]);
System.out.println("2. " + questions[lindex]);
System.out.println();
return questions[hindex];
}



This way someone can have a lot of mistakes in a sentence and it can still find accurate matches..

Adler32 and CRC32 are checksums algorithms.
Memory maps can be used to communicate with other processes. Smart does this, OpenGL, DirectX, etc.. This is how they communicate with Simba.


var
Res: PROCESSENTRY32;
begin
Res := GetProcessInfo('notepad.exe');
writeln(String(ProcessInfoToString(Res)));
end.


will print:


================================================== =====
Process Name: notepad.exe
================================================== =====

Process ID: 13848
Thread Count: 1
Priority Base: 8
Parent Process ID: 6256

================================================== =====



ModulesInfo will display a list of all modules/dll's/plugins loaded by a process:

http://i.imgur.com/DXacFdG.png

as shown here: http://villavu.com/forum/showthread.php?t=100266

Starting and Stopping Services and messing with the registry can be useful at times:


Function CharArrayToString(arr: array of char): String;
var
I: Integer;
Begin
SetLength(Result, Length(Arr));
For I := 1 To Length(Arr) Do
Result[I] := Arr[I - 1];

Result := Trim(Result);
End;


var
str: array of char;
begin
setlength(str, 7);
ReadRegistryKey($80000002, 'SOFTWARE\\Microsoft\Windows\CurrentVersion\RunOnc e', 'TEST', REG_KEY_TYPE.REG_SZ, str, $0100);

writeln(CharArrayToString(Str));
end.



Prints:


HELLO


Changing your screen resolution/display can be easy as well as getting information about a computer:

begin
SetDisplayResolution(1366, 768);
writeln(String(GetDisplaySettings(0)));
SetDefaultDisplaySettings();
end.



Device name: \\.\DISPLAY1
Monitor name: MONITOR\CMO1590\{4d36e96e-e325-11ce-bfc1-08002be10318}\0001
Refresh rate: 60
Colour depth: 32
Screen resolution: 1366 x 768


SetWindowTransparency can be used to make windows invisible. Hiding certain applications in the background.


To Get Drive information:


var
I, L: Integer;
FreeSpace, TotalSpace: Word;
Drives: Array[0..25] Of Char;
begin
L := GetLogicalDrivesList(Drives);
For I := 0 To L - 1 Do
begin
writeln('Drive: ', Drives[I], ' is of type: ', String(GetTypeOfDrive(Drives[I] + ':\\')));
If (GetDriveInfo(Drives[I] + ':\\', FreeSpace, TotalSpace, True)) Then
writeln('Drive: ', Drives[I], ' has ', FreeSpace, 'GB free of ', TotalSpace, '.'#13#10);
end;
end.



Will print:


Drive: C is of type: Hard disk
Drive: C has 292GB free of 372.

Drive: D is of type: Hard disk
Drive: D has 518GB free of 537.

Drive: F is of type: CD/DVD



Procedure ThreadedWriteLn(const Str: String);
var
Wnd: PtrUInt;
Area: TBox;
begin
Wnd := GetPreviousWindow(GetPreviousWindow(FindMainWindow (GetPID())));
GetWindowDimensions(Wnd, Area);
Wnd := WindowHandleFromPoint(Point(Area.X2 - 100, Area.Y2 - 100));
AppendWindowText(Wnd, Str);
end;


So on and so forth..

Kevin
02-27-2014, 03:18 AM
Don't get me wrong, this is pretty damn huge. But Levenshtein and related StringMatch (changes the low ratio of Levenshtein into a more user-friendly %) is built into Simba atm:
http://docs.villavu.com/simba/scriptref/string.html#stringmatch
I think there was also a 3rd string comparison algorithm built in that starts with a 'G'... Can't remember full name atm though.

As far as I know the other 79 are all brand new and would probably take me a few minutes to understand the logic behind each of them :p

rj
02-27-2014, 03:50 AM
My Simba crashes when I try to do:

{$loadlib Riddler.dll}

var
ThreadOne: Integer;
stopOne:boolean;
i:integer;

procedure progress;
begin
writeln('test');
end;

procedure stopThreads;
begin
StopOne := True;
JoinThread(ThreadOne);
ClearThreads(False);
end;

begin
stopOne := true;
ClearLocks;
ThreadOne := CreateThread(Natify(@progress));
progress;
AddOnTerminate('StopThreads');
repeat
i := i + 1;
until (IsKeyDown(113));
end.


http://i.imgur.com/mrhj8TW.png

Brandon
02-27-2014, 04:05 AM
My Simba crashes when I try to do:
...

Because your thread procedure is finished long before the thread is even stopped. Thus you need to do:


ThreadOne := CreateThread(Natify(@progress));
DetachThread(ThreadOne); //Detaches the thread from the main process.



If you do NOT detach it then you must Join it. You might want to know the difference between detaching and joining a thread before diving into it.

Zyt3x
02-27-2014, 03:33 PM
Hmmm, interesting :) Nice work Brandon!

E: Tell me some more about Image; what extra potential does this have over i.e TMufasaBitmap?

Brandon
02-27-2014, 04:46 PM
Hmmm, interesting :) Nice work Brandon!

E: Tell me some more about Image; what extra potential does this have over i.e TMufasaBitmap?


This library was originally create for making Java and C# colours bots and debugging easier. It originally contained ports of FindBitmapTolerance, FindColoursTolerance, etc..

The image class was needed to do that. Now the Image class can be used as an abstract layer around TMufasaBitmaps. It can be used for drawing on external windows which you cannot do with a TMufasaBitmap as that is a Simba only interface. For example, Simba cannot draw on the browser and only has debugging in Smart unless using OpenGL or DirectX.

The ability to capture other windows, manipulate them or pass it to Simba via a pointer (rather than copying or direct access), Java, C#, C, etc.. That's basically its capabilities. Also allows threads to manipulate and communication with Simba's images without exceptions and crashes. IIRC, TMufasaBitmap or MML functions was said to be un-threadable/non-threadsafe. I had threads crashing when calling FindColoursTolerance on a Simba Bitmap. Having bitmaps that can be created within a thread or another process itself is extremely helpful especially if you want multi-threaded progress reports and stuff. Now it has locks, image wrappers, and synchronisation stuff so there shouldn't be any problems really. Though, some may arise that I haven't seen yet.


Hopefully you don't still have to wrap Simba images to draw in separate threads, but you will have to for other windows (non-smart windows).


EDIT: Updated the plugin + my example post to include a "threaded" writeln.. Apparently Simba's writeln didn't work in threads (how awful and badly non-threadsafe can Simba possibly get).. Pretty sure writeln should be thread safe, not sure why it doesn't work from threads..

Anyway, the Threaded_WriteLn should work until Simba gets some major issues sorted out.. Not being able to write to the debug box from a separate thread is as awful as it gets (no hate intended).

Dgby714
02-28-2014, 02:26 AM
This library was originally create for making Java and C# colours bots and debugging easier. It originally contained ports of FindBitmapTolerance, FindColoursTolerance, etc..

The image class was needed to do that. Now the Image class can be used as an abstract layer around TMufasaBitmaps. It can be used for drawing on external windows which you cannot do with a TMufasaBitmap as that is a Simba only interface. For example, Simba cannot draw on the browser and only has debugging in Smart unless using OpenGL or DirectX.

The ability to capture other windows, manipulate them or pass it to Simba via a pointer (rather than copying or direct access), Java, C#, C, etc.. That's basically its capabilities. Also allows threads to manipulate and communication with Simba's images without exceptions and crashes. IIRC, TMufasaBitmap or MML functions was said to be un-threadable/non-threadsafe. I had threads crashing when calling FindColoursTolerance on a Simba Bitmap. Having bitmaps that can be created within a thread or another process itself is extremely helpful especially if you want multi-threaded progress reports and stuff. Now it has locks, image wrappers, and synchronisation stuff so there shouldn't be any problems really. Though, some may arise that I haven't seen yet.


Hopefully you don't still have to wrap Simba images to draw in separate threads, but you will have to for other windows (non-smart windows).


EDIT: Updated the plugin + my example post to include a "threaded" writeln.. Apparently Simba's writeln didn't work in threads (how awful and badly non-threadsafe can Simba possibly get).. Pretty sure writeln should be thread safe, not sure why it doesn't work from threads..

Anyway, the Threaded_WriteLn should work until Simba gets some major issues sorted out.. Not being able to write to the debug box from a separate thread is as awful as it gets (no hate intended).

WriteLn wont work as it uses a ThreadVar to get the current script class. Tho Client.WriteLn should work iirc.

Brandon
02-28-2014, 02:55 AM
WriteLn wont work as it uses a ThreadVar to get the current script class. Tho Client.WriteLn should work iirc.


Ahh you are indeed right! Why was it designed like that though :S If writeln is static within the client class, why is it called through a script instance regularly instead of just using Client.WriteLn? In other words, why is writeln not just a wrapper around Client.Writeln? What is the benefit? Anything else that behaves that way?

And yeah it works fine now:


var
Stop: Boolean;
T1: Integer;

Procedure TP;
begin
DetachThread(T1);

while(Not Stop) do
Client.WriteLn('Hello from another thread.');
end;

Procedure StopAll;
begin
Stop := True;
end;

begin
T1 := CreateThread(Natify(@TP));
AddOnTerminate('StopAll');
Sleep(2000);
end.


I was also about to modify my own Simba to allow me to export constants as I found out I can't.

Dgby714
02-28-2014, 03:07 AM
Ahh you are indeed right! Why was it designed like that though :S If writeln is static within the client class, why is it called through a script instance regularly instead of just using Client.WriteLn? In other words, why is writeln not just a wrapper around Client.Writeln? What is the benefit? Anything else that behaves that way?

And yeah it works fine now:


var
Stop: Boolean;
T1: Integer;

Procedure TP;
begin
DetachThread(T1);

while(Not Stop) do
Client.WriteLn('Hello from another thread.');
end;

Procedure StopAll;
begin
Stop := True;
end;

begin
T1 := CreateThread(Natify(@TP));
AddOnTerminate('StopAll');
Sleep(2000);
end.


I was also about to modify my own Simba to allow me to export constants as I found out I can't.

You can use most of MML thru the Client class.

It's designed like that because of how things worked in PS, if I drop PS and rewrite a lot we wouldn't even need any of that.

If I wrote the exports for MML methods strait for Lape I'd be able to make them work from any thread.

Basicly when you call a SImba method from in a Script, that method has no info about that scripts "Client". Since all scripts are on their own thread we just create a threadvar and set it to the current TMThead (which has the child Client), and use that.

If I did this how I wanted I'd just write all the wrappers as Lape native wrappers that use the Client variable we now pass to it.

Foundry
03-12-2014, 05:28 PM
Can this be used to bring a window into focus if you have the window handle? By bring into focus, I mean do something that would be equivalent to clicking on the top part of the window.

Zyt3x
03-12-2014, 06:10 PM
Can this be used to bring a window into focus if you have the window handle? By bring into focus, I mean do something that would be equivalent to clicking on the top part of the window.http://msdn.microsoft.com/en-us/library/system.windows.application.activated(v=vs.110).asp x

The plugin has some event functions but I'm not entirely sure if that's what they do
E: Misread your question. Thought you wanted to check if it was activated, not activate it

NKN
03-12-2014, 06:12 PM
Can this be used to bring a window into focus if you have the window handle? By bring into focus, I mean do something that would be equivalent to clicking on the top part of the window.

There were some system call commands you could do to do that if his library won't.

Forgot what it's called exactly, I'll PM you it when I get home today if you still need the answer.

Foundry
03-12-2014, 06:18 PM
There were some system call commands you could do to do that if his library won't.

Forgot what it's called exactly, I'll PM you it when I get home today if you still need the answer.

Thanks, that would be great. I only understand a minimal amount of what's going on with all of this.

Brandon
03-12-2014, 11:56 PM
Thanks, that would be great. I only understand a minimal amount of what's going on with all of this.

SetForegroundWindow: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx

It's not in the plugin I think but it's fairly easy to add.. I'll add it in a sec.

Foundry
03-13-2014, 01:03 AM
SetForegroundWindow: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539(v=vs.85).aspx

It's not in the plugin I think but it's fairly easy to add.. I'll add it in a sec.

You're my hero, thank you!

Olly
03-13-2014, 06:28 PM
Pretty sure activateClient() does what you want to do.

Frement
03-13-2014, 06:37 PM
Pretty sure activateClient() does what you want to do.

For current target yes, but what if he wants to do the same for another window? (which is not the current target)

Olly
03-13-2014, 07:18 PM
For current target yes, but what if he wants to do the same for another window? (which is not the current target)

procedure ActivateClient(const winName: string); overload;
var
arr: TSysProcArr;
img, km, i: integer;
begin
arr := GetProcesses();

for i := 0 to high(arr) do
if (pos(lowercase(winName), lowercase(arr[i].title)) > 0) then
begin
writeln('Found!');

img := getImageTarget();
km := getKeyMouseTarget();

setTarget(arr[i]);
ActivateClient();

setImageTarget(img);
setKeyMouseTarget(km);
end;
end;

begin
ActivateClient('Skype');
end;

:D!

Foundry
03-13-2014, 07:56 PM
Pretty sure activateClient() does what you want to do.

Right under my nose the whole time. Thanks!

Zyt3x
03-13-2014, 09:28 PM
procedure ActivateClient(const winName: string); overload;
var
arr: TSysProcArr;
img, km, i: integer;
begin
arr := GetProcesses();

for i := 0 to high(arr) do
if (pos(lowercase(winName), lowercase(arr[i].title)) > 0) then
begin
writeln('Found!');

img := getImageTarget();
km := getKeyMouseTarget();

setTarget(arr[i]);
ActivateClient();

setImageTarget(img);
setKeyMouseTarget(km);
end;
end;

begin
ActivateClient('Skype');
end;

:D!Ah, of course.. :)

Frement
03-18-2014, 11:56 AM
Brandon;

I'm getting this: [Error] (2:1): Unable to register type PWChar

Brandon
03-18-2014, 01:51 PM
Brandon;

I'm getting this: [Error] (2:1): Unable to register type PWChar


Shouldn't be happening at all. The only time that could happen is if Simba does not have WideChar and it should.

A PWChar is defined as ^WideChar. Pointers require Lape.

Try running:


type PWChar = ^WideChar;

var
P: PWChar;
begin
end.


See what happens.

Frement
03-18-2014, 01:53 PM
Shouldn't be happening at all. The only time that could happen is if Simba does not have WideChar and it should.

A PWChar is defined as ^WideChar. Pointers require Lape.

Try running:


type PWChar = ^WideChar;

var
P: PWChar;
begin
end.


See what happens.

So this is lape only? :/

Anyway to have the threading stuff only for PS?

Brandon
03-18-2014, 01:59 PM
So this is lape only? :/

Anyway to have the threading stuff only for PS?


I'm not sure if the threading stuff could work in PS.. The whole concept of the threading revolved around Natify which might be a Lape only function.


For example:

CreateThread(Natify(@MyFunction));


This will thread "MyFunction" or whatever function you passed it. Natify gets the address of that function and passes it to the thread..

I'm not too sure if you can do: CreateThread(@MyFunction). Last time I tried that, it crashes my script but that was when I first wrote it. Might be different now.


I'll try it and see how it goes. I might be able to come up with something for PS or change it to work with PS but there isn't any guarantees yet.

Frement
03-18-2014, 02:02 PM
I'm not sure if the threading stuff could work in PS.. The whole concept of the threading revolved around Natify which might be a Lape only function.


For example:

CreateThread(Natify(@MyFunction));


This will thread "MyFunction" or whatever function you passed it. Natify gets the address of that function and passes it to the thread..

I'm not too sure if you can do: CreateThread(@MyFunction). Last time I tried that, it crashes my script but that was when I first wrote it. Might be different now.


I'll try it and see how it goes. I might be able to come up with something for PS or change it to work with PS but there isn't any guarantees yet.

Ok, looking forward to the results :)

EDIT: Brandon;
How would I read something from SMART within a thread? For example SmartGetFieldInt.

Brandon
03-18-2014, 03:42 PM
Ok, looking forward to the results :)

EDIT: Brandon;
How would I read something from SMART within a thread? For example SmartGetFieldInt.



Procedure ThreadProc;
begin
SmartGetFieldInt(...);
end;

CreateThread(Natify(@ThreadProc));



Natify only allows "Procedures" atm. Why use SmartGetFieldInt in a thread though? I also don't think it will help you because Smart's sockets might actually be synchronized or you might have to do synchronization yourself. You can try it and see how it goes.

Frement
03-18-2014, 03:45 PM
Procedure ThreadProc;
begin
SmartGetFieldInt(...);
end;

CreateThread(Natify(@ThreadProc));



Natify only allows "Procedures" atm. Why use SmartGetFieldInt in a thread though? I also don't think it will help you because Smart's sockets might actually be synchronized or you might have to do synchronization yourself. You can try it and see how it goes.

Using a function within the thread like R_GetTileGlobal gives access violation. Same goes for drawing on the canvas.

Brandon
03-18-2014, 04:13 PM
Using a function within the thread like R_GetTileGlobal gives access violation. Same goes for drawing on the canvas.


I have not tested this with Reflection but I do know drawing works (perfect for live progress reports and other stuff):


{$DEFINE SMART}
{$I SRL-6/SRL.Simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean; //To tell threads when to terminate.

Procedure StopThreads; //called when the script terminates.
begin
TerminateThreads := True;
Sleep(1000); //give threads time to process the interrupt.
end;

Procedure DrawingThread; //Procedure that will be passed to a thread.
begin
SmartImage.DrawBox(0, 0, 200, 200, true, clRed); //draw red box when the thread starts.

while(Not TerminateThreads) do //while the script is running, keep drawing a blue box.
begin
SmartImage.DrawBox(200, 200, 400, 400, true, clBlue);
Sleep(100); //give the thread a small break. No need to overwork it. Even Sleep(1) is fine.
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer; //Spawns a thread and detaches it immediately from the main process.
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(100); //Give the thread time to spawn. Even lower works too.
end;

Procedure Main(); //Script's main code goes in here.. Basically, everything else..
begin
//All other script code goes here..
Sleep(2000);
end;

var
Thread: Integer;
begin
smartEnableDrawing := True; //Enable drawing..

SetupSRL; //Setup SRL for convenience..
AddOnTerminate('StopThreads'); //Before we terminate the script, terminate all threads..
Thread := SpawnThreadDetached(@DrawingThread); //Spawn our drawing thread..

Main(); //Run the rest of our script alongside our drawing thread.
end.


The above works just fine. It doesn't need synchronisation for the above.

http://i.imgur.com/l55MNVu.png


Can also spawn multiple threads to draw on Smart at the same time but I felt that one drawing thread was fine and let the script do whatever else it has to while the thread draws..

Frement
03-18-2014, 04:41 PM
I have not tested this with Reflection but I do know drawing works (perfect for live progress reports and other stuff):


{$DEFINE SMART}
{$I SRL-6/SRL.Simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean; //To tell threads when to terminate.

Procedure StopThreads; //called when the script terminates.
begin
TerminateThreads := True;
Sleep(1000); //give threads time to process the interrupt.
end;

Procedure DrawingThread; //Procedure that will be passed to a thread.
begin
SmartImage.DrawBox(0, 0, 200, 200, true, clRed); //draw red box when the thread starts.

while(Not TerminateThreads) do //while the script is running, keep drawing a blue box.
begin
SmartImage.DrawBox(200, 200, 400, 400, true, clBlue);
Sleep(100); //give the thread a small break. No need to overwork it. Even Sleep(1) is fine.
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer; //Spawns a thread and detaches it immediately from the main process.
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(100); //Give the thread time to spawn. Even lower works too.
end;

Procedure Main(); //Script's main code goes in here.. Basically, everything else..
begin
//All other script code goes here..
Sleep(2000);
end;

var
Thread: Integer;
begin
smartEnableDrawing := True; //Enable drawing..

SetupSRL; //Setup SRL for convenience..
AddOnTerminate('StopThreads'); //Before we terminate the script, terminate all threads..
Thread := SpawnThreadDetached(@DrawingThread); //Spawn our drawing thread..

Main(); //Run the rest of our script alongside our drawing thread.
end.


The above works just fine. It doesn't need synchronisation for the above.

http://i.imgur.com/l55MNVu.png


Can also spawn multiple threads to draw on Smart at the same time but I felt that one drawing thread was fine and let the script do whatever else it has to while the thread draws..

I modified the snippet to run with OSR and this line in SmartGraphics.simba is giving access violation:
SetPersistentMemoryBitmap(SMART_Canvas.getIndex(), SmartDebugArray(smartCurrentTarget), 765, 503);

EDIT: The code:
{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}
{$I SRL-OSR/SRL/Reflection-lape/Reflection.simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean; //To tell threads when to terminate.

Procedure StopThreads; //called when the script terminates.
begin
TerminateThreads := True;
Sleep(1000); //give threads time to process the interrupt.
end;

Procedure DrawingThread; //Procedure that will be passed to a thread.
begin
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed); //draw red box when the thread starts.

while(Not TerminateThreads) do //while the script is running, keep drawing a blue box.
begin
SMART_DrawBoxEx(False, True, IntToBox(200, 200, 400, 400), clBlue);
Sleep(100); //give the thread a small break. No need to overwork it. Even Sleep(1) is fine.
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer; //Spawns a thread and detaches it immediately from the main process.
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(100); //Give the thread time to spawn. Even lower works too.
end;

Procedure Main(); //Script's main code goes in here.. Basically, everything else..
begin
//All other script code goes here..
Sleep(2000);
end;

var
Thread: Integer;
begin
SetupSRL; //Setup SRL for convenience..
SetupReflection;
AddOnTerminate('StopThreads'); //Before we terminate the script, terminate all threads..
Thread := SpawnThreadDetached(@DrawingThread); //Spawn our drawing thread..

Main(); //Run the rest of our script alongside our drawing thread.
end.

Brandon
03-18-2014, 05:11 PM
I modified the snippet to run with OSR..


This is the problem with OSR though. Here's what I found:

Running it without threads:


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}

begin
SetupSRL;

SMART_SetupDebug();
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);
end.


Not only say: Compiled successfully in 10125 ms.

But.. It didn't draw at all.. Even when I manually called SMART_SetupDebug;

So I looked into SmartGraphics.Simba to see where the problem lies.. and I end up finding some of the dirtiest/hard to read patches I ever saw in Simba's includes.. What was once clean is now a mess:

This function:

procedure SMART_SetupDebug;
begin
SmartSetDebug(smartCurrentTarget, True);
{$IFDEF LAPE}
SMART_Canvas.init();
{$ELSE}
SMART_Canvas := TMufasaBitmap.Create;
{$ENDIF}
SMART_Canvas.setSize(765, 503);
{$IFDEF LAPE}
SetPersistentMemoryBitmap(SMART_Canvas.getIndex(), SmartDebugArray(smartCurrentTarget), 765, 503);
SMART_Canvas.drawClear(0); //clear it in case of previous usage
{$ELSE}
SetPersistentMemoryBitmap(SMART_Canvas.index, SmartDebugArray(smartCurrentTarget), 765, 503);
SMART_Canvas.FastDrawClear(0); //clear it in case of previous usage
{$ENDIF}
SMART_DebugSetup := true;
if not SMART_Reset then
AddOnTerminate('SMART_FreeDebug');
end;


With that many pre-processor arguments, I gave up and cleaned it up:

So it now looks like:

procedure SMART_SetupDebug;
begin
SmartSetDebug(smartCurrentTarget, True);

{$IFDEF LAPE}
SMART_Canvas.init(Client.GetMBitmaps);
SMART_Canvas.SetPersistentMemory(SmartDebugArray(s martCurrentTarget), 765, 503);
SMART_Canvas.drawClear(0);
{$ELSE}
SMART_Canvas := TMufasaBitmap.Create;
SMART_Canvas.setSize(765, 503);
SetPersistentMemoryBitmap(SMART_Canvas.index, SmartDebugArray(smartCurrentTarget), 765, 503);
SMART_Canvas.FastDrawClear(0);
{$ENDIF}

SMART_DebugSetup := true;

if not SMART_Reset then
AddOnTerminate('SMART_FreeDebug');
end;


With this, you can clearly see which section is Lape and which section is PS..

And the difference is that instead of Printing "Bitmap at line 32 does not exist", it now draws on Smart.. The main difference is the TMufasaBitmap.init(Client.GetMBitmaps). I don't mean to bash anyone here but whoever ported the old code to Lape missed a lot of things.. Mostly details and crucial steps.

Client.GetMBitmaps is needed if you want to use Bitmap.GetIndex() and garbage cleanup.. Otherwise it is your responsibility for everything. At least, that's what I was told. With the above changes, it is finally able to draw on Smart. I haven't looked at anything else yet but that part works.. I will try to thread it in a sec and see how it goes. Might be more problems in the include :l

Anyway, until the include itself is fixed, you cannot draw normally and you cannot draw with Threads as a consequence. I can try and help out and fix it up I guess.. I see my name in that include but with the code the way it is now, I don't recognize what portions I wrote or helped write..

It is also printing a lot of "Bitmap not freed" stuff for me :S

I'd probably get Olly or Coh3n or Dgby or anyone that is fairly verse in Lape scripting to look at it.. I can but I make no promises yet. I will try to look at it tonight and see what else I find.



EDIT: With the above changes, it threads properly (Again, be careful using that OSR-Lape include..):


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean;

Procedure StopThreads;
begin
TerminateThreads := True;
Sleep(1000);
end;

Procedure DrawingThread;
begin
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);

while(Not TerminateThreads) do
begin
SMART_DrawBoxEx(False, True, IntToBox(200, 200, 400, 400), clBlue);
Sleep(100);
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer;
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(100);
end;

Procedure Main();
begin
Sleep(2000);
end;

var
Thread: Integer;
begin
SetupSRL;
SMART_SetupDebug();
AddOnTerminate('StopThreads');
Thread := SpawnThreadDetached(@DrawingThread);
end.


http://i.imgur.com/tBFDZ2V.png

Frement
03-18-2014, 05:20 PM
This is the problem with OSR though. Here's what I found:

Running it without threads:


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}

begin
SetupSRL;

SMART_SetupDebug();
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);
end.


Not only say: Compiled successfully in 10125 ms.

But.. It didn't draw at all.. Even when I manually called SMART_SetupDebug;

So I looked into SmartGraphics.Simba to see where the problem lies.. and I end up finding some of the dirtiest/hard to read patches I ever saw in Simba's includes.. What was once clean is now a mess:

This function:

procedure SMART_SetupDebug;
begin
SmartSetDebug(smartCurrentTarget, True);
{$IFDEF LAPE}
SMART_Canvas.init();
{$ELSE}
SMART_Canvas := TMufasaBitmap.Create;
{$ENDIF}
SMART_Canvas.setSize(765, 503);
{$IFDEF LAPE}
SetPersistentMemoryBitmap(SMART_Canvas.getIndex(), SmartDebugArray(smartCurrentTarget), 765, 503);
SMART_Canvas.drawClear(0); //clear it in case of previous usage
{$ELSE}
SetPersistentMemoryBitmap(SMART_Canvas.index, SmartDebugArray(smartCurrentTarget), 765, 503);
SMART_Canvas.FastDrawClear(0); //clear it in case of previous usage
{$ENDIF}
SMART_DebugSetup := true;
if not SMART_Reset then
AddOnTerminate('SMART_FreeDebug');
end;


With that many pre-processor arguments, I gave up and cleaned it up:

So it now looks like:

procedure SMART_SetupDebug;
begin
SmartSetDebug(smartCurrentTarget, True);

{$IFDEF LAPE}
SMART_Canvas.init(Client.GetMBitmaps);
SMART_Canvas.SetPersistentMemory(SmartDebugArray(s martCurrentTarget), 765, 503);
SMART_Canvas.drawClear(0);
{$ELSE}
SMART_Canvas := TMufasaBitmap.Create;
SMART_Canvas.setSize(765, 503);
SetPersistentMemoryBitmap(SMART_Canvas.index, SmartDebugArray(smartCurrentTarget), 765, 503);
SMART_Canvas.FastDrawClear(0);
{$ENDIF}

SMART_DebugSetup := true;

if not SMART_Reset then
AddOnTerminate('SMART_FreeDebug');
end;


With this, you can clearly see which section is Lape and which section is PS..

And the difference is that instead of Printing "Bitmap at line 32 does not exist", it now draws on Smart.. The main difference is the TMufasaBitmap.init(Client.GetMBitmaps). I don't mean to bash anyone here but whoever ported the old code to Lape missed a lot of things..

Client.GetMBitmaps is needed if you want to use Bitmap.GetIndex() and garbage cleanup.. Otherwise it is your responsibility for everything. At least, that's what I was told.

Anyway, until the include itself is fixed, you cannot draw normally and you cannot draw with Threads as a consequence. I can try and help out and fix it up I guess.. I see my name in that include but with the code the way it is now, I don't recognize what portions I wrote or helped write..

It is also printing a lot of "Bitmap not freed" stuff for me :S

I did some of the messy porting, without knowing much of how things work with Lape.

Anyway, with the new code you provided, it still gives me access violation, now on line 40:
AddOnTerminate('SMART_FreeDebug');

Brandon
03-18-2014, 05:28 PM
I did some of the messy porting, without knowing much of how things work with Lape.

Anyway, with the new code you provided, it still gives me access violation, now on line 40:
AddOnTerminate('SMART_FreeDebug');

Well I hope you don't take offense to anything I said. Don't mean it badly. It just needs work/fine-tuning is all.

Anyway, are you sure? I also added that and it works fine? You can draw normally without threads? That would be the first requirement. You manually called Smart_SetupDebug as well? Because you need to.

Line 40 doesn't seem right..

I have 46 lines:


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean;

Procedure StopThreads;
begin
TerminateThreads := True;
Sleep(1000);
end;

Procedure DrawingThread;
begin
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);

while(Not TerminateThreads) do
begin
SMART_DrawBoxEx(False, True, IntToBox(200, 200, 400, 400), random(clBlue) + 1);
Sleep(100);
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer;
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(500);
end;

Procedure Main();
begin
Sleep(2000);
end;

var
Thread: Integer;
begin
SetupSRL;
SMART_SetupDebug();
AddOnTerminate('StopThreads');
AddOnTerminate('SMART_FreeDebug');
Thread := SpawnThreadDetached(@DrawingThread);
end.

Frement
03-18-2014, 05:46 PM
Well I hope you don't take offense to anything I said. Don't mean it badly. It just needs work/fine-tuning is all.

Anyway, are you sure? I also added that and it works fine? You can draw normally without threads? That would be the first requirement. You manually called Smart_SetupDebug as well? Because you need to.

Line 40 doesn't seem right..

I have 46 lines:


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean;

Procedure StopThreads;
begin
TerminateThreads := True;
Sleep(1000);
end;

Procedure DrawingThread;
begin
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);

while(Not TerminateThreads) do
begin
SMART_DrawBoxEx(False, True, IntToBox(200, 200, 400, 400), random(clBlue) + 1);
Sleep(100);
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer;
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(500);
end;

Procedure Main();
begin
Sleep(2000);
end;

var
Thread: Integer;
begin
SetupSRL;
SMART_SetupDebug();
AddOnTerminate('StopThreads');
AddOnTerminate('SMART_FreeDebug');
Thread := SpawnThreadDetached(@DrawingThread);
end.


I forgot to setup debug, now works. How about the reflection portion? R_GetTileGlobal for example. Also trying to use SMART_DrawTextEx gives me access violation from line 700 in text.simba, TPAFromText.

Brandon
03-18-2014, 06:26 PM
I forgot to setup debug, now works. How about the reflection portion? R_GetTileGlobal for example. Also trying to use SMART_DrawTextEx gives me access violation from line 700 in text.simba, TPAFromText.

You'll have to give me some time to look over the Osr/Ref includes and see how it is structured. I'm not very familiar with it yet.

EDIT: Frement;

Override LoadTextTPA with:


function LoadTextTPA(Text, Chars: string; var height: integer): TPointArray; override;
var
w: integer;
begin
result := Client.GetMOCR().TextToFontTPA(text,chars,w,height );
dec(height);
end;


Why? Because: https://github.com/MerlijnWajer/Simba/blob/42be9f4a60940a63c709779bfc21017b5b55f52a/Units/MMLAddon/PSInc/Wrappers/ocr.inc
You can see they belong to CurrThread.


By override, I mean do NOT replace the old one with the above.. Instead, add it to your script like this:


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean;

Procedure StopThreads;
begin
TerminateThreads := True;
Sleep(1000);
end;

Procedure DrawingThread;
begin
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);

while(Not TerminateThreads) do
begin
SMART_DrawBoxEx(False, True, IntToBox(200, 200, 400, 400), random(clBlue) + 1);
SMART_DrawTextMulti(False, False, ['HELLO WORLD!'], Point(0, 300), 'BigChars', random(clBlue) + 1);
Sleep(100);
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer;
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(500);
end;

Procedure Main();
begin
Sleep(2000);
end;

function LoadTextTPA(Text, Chars: string; var height: integer): TPointArray; override;
var
w: integer;
begin
result := Client.GetMOCR().TextToFontTPA(text,chars,w,height );
dec(height);
end;

var
Thread: Integer;
begin
SetupSRL;
SMART_SetupDebug();
AddOnTerminate('StopThreads');
AddOnTerminate('SMART_FreeDebug');
Thread := SpawnThreadDetached(@DrawingThread);
end.


That will certainly work.. I just tested it.. Also, if you want to write to Simba's debug from a thread, you'll need to use Client.WriteLn('SomeText');

as Dgby pointed out earlier. I haven't tried Reflection yet. I don't have the ref include anymore.. I'll download it later and check.

Frement
03-18-2014, 07:20 PM
You'll have to give me some time to look over the Osr/Ref includes and see how it is structured. I'm not very familiar with it yet.

EDIT: Frement;

Override LoadTextTPA with:


function LoadTextTPA(Text, Chars: string; var height: integer): TPointArray; override;
var
w: integer;
begin
result := Client.GetMOCR().TextToFontTPA(text,chars,w,height );
dec(height);
end;


Why? Because: https://github.com/MerlijnWajer/Simba/blob/42be9f4a60940a63c709779bfc21017b5b55f52a/Units/MMLAddon/PSInc/Wrappers/ocr.inc
You can see they belong to CurrThread.


By override, I mean do NOT replace the old one with the above.. Instead, add it to your script like this:


{$DEFINE SMART8}
{$I SRL-OSR/SRL.Simba}
{$I SRL-OSR/SRL/misc/SmartGraphics.simba}
{$loadlib Riddler.dll}

var
TerminateThreads: Boolean;

Procedure StopThreads;
begin
TerminateThreads := True;
Sleep(1000);
end;

Procedure DrawingThread;
begin
SMART_DrawBoxEx(True, True, IntToBox(0, 0, 200, 200), clRed);

while(Not TerminateThreads) do
begin
SMART_DrawBoxEx(False, True, IntToBox(200, 200, 400, 400), random(clBlue) + 1);
SMART_DrawTextMulti(False, False, ['HELLO WORLD!'], Point(0, 300), 'BigChars', random(clBlue) + 1);
Sleep(100);
end;
end;

Function SpawnThreadDetached(Proc: Procedure): Integer;
begin
Result := CreateThread(Natify(@Proc));
DetachThread(Result);
Sleep(500);
end;

Procedure Main();
begin
Sleep(2000);
end;

function LoadTextTPA(Text, Chars: string; var height: integer): TPointArray; override;
var
w: integer;
begin
result := Client.GetMOCR().TextToFontTPA(text,chars,w,height );
dec(height);
end;

var
Thread: Integer;
begin
SetupSRL;
SMART_SetupDebug();
AddOnTerminate('StopThreads');
AddOnTerminate('SMART_FreeDebug');
Thread := SpawnThreadDetached(@DrawingThread);
end.


That will certainly work.. I just tested it.. Also, if you want to write to Simba's debug from a thread, you'll need to use Client.WriteLn('SomeText');

as Dgby pointed out earlier. I haven't tried Reflection yet. I don't have the ref include anymore.. I'll download it later and check.

Worked great, thought SMART did crash when I made it walk and sleep for 60 seconds. (I did this in the Main procedure)

caused
04-12-2014, 09:23 PM
Very good job. Also ne latest updates :D

Foundry
04-27-2014, 11:51 PM
I am trying to figure out how to use this to draw on OpenGL windows. This is what I have now.

var
img: Integer;
window: PtrUInt;

begin
img := LoadImage('C:/Users/Robert/Test.bmp');
window := findmainWindow(4048); // This was the PID of the window.
repeat
DrawToWindow(img, window);
sleep(10); // Even this doesn't make the image stay.
until(false);
end.

It draws but it keeps disappearing so I must be doing something wrong...

Olly
04-28-2014, 12:09 AM
I am trying to figure out how to use this to draw on OpenGL windows. This is what I have now.

var
img: Integer;
window: PtrUInt;

begin
img := LoadImage('C:/Users/Robert/Test.bmp');
window := findmainWindow(4048); // This was the PID of the window.
repeat
DrawToWindow(img, window);
sleep(10); // Even this doesn't make the image stay.
until(false);
end.

It draws but it keeps disappearing so I must be doing something wrong...

I don't think so. I'm pretty sure Brandons plugins draws on the window doesn't create another layer (if that's even possible). And when ogl updates the window it's cleared.

Foundry
04-28-2014, 12:59 AM
I don't think so. I'm pretty sure Brandons plugins draws on the window doesn't create another layer (if that's even possible). And when ogl updates the window it's cleared.

That's sort of what I thought. Brandon;, help?

Brandon
04-28-2014, 05:36 AM
That's sort of what I thought. Brandon;, help?
Olly; is correct. OpenGL is ALWAYS double buffered. It is possible to "overlay" on top of it but that requires sub-classing the window's WndProc and in turn requires either a system wide hook via 'SetWindowHookEx' or injecting a module into the process.

Might also be possible if I make the draw function use OpenGL instead of GDI/GDI+.