unit jniTMemScan; {$mode delphi} interface uses Classes, SysUtils, jni, unixporthelper, commonTypeDefs, math; procedure InitializeJniTMemScan(env: PJNIEnv); implementation uses jniTObject, memscan, Globals; var scanDoneMethodID: jmethodID; type TJniMemscan=class(TMemScan) private procedure cleanup; protected procedure ScanDone; override; public javaowner: jobject; destructor destroy; override; end; procedure TJniMemscan.ScanDone; //called by synchronize begin log('TJniMemscan.ScanDone'); if javaowner<>nil then begin MainThreadEnv^.CallVoidMethod(MainThreadEnv, javaowner, scanDoneMethodID); log('Returned from OnScanDone'); end; end; procedure TJniMemscan.cleanup; begin log('TJniMemscan.destroy'); MainThreadEnv^.DeleteGlobalRef(MainThreadEnv, javaowner); end; destructor TJniMemscan.destroy; begin log('TJniMemscan.destroy'); if javaowner<>nil then TThread.Synchronize(nil, cleanup); inherited destroy; end; function TMemScan_Create(PEnv: PJNIEnv; Obj: JObject; owner: JObject): jlong; cdecl; var ms: TJniMemscan; begin log('Creating a memscan object'); ms:=TJniMemscan.create(nil); if penv^.IsSameObject(PEnv, obj, owner)<>0 then log('Weird'); ms.javaowner:=penv^.NewGlobalRef(penv, owner); result:=ptruint(ms); end; procedure TMemScan_NewScan(PEnv: PJNIEnv; Obj: JObject); cdecl; var ms: TMemScan; begin log('new scan'); ms:=TMemScan(JObjectToTObject(penv, obj)); ms.newscan; end; function TMemScan_GetProgress(PEnv: PJNIEnv; Obj: JObject):jint; cdecl; var ms: TMemscan; total,current: qword; p: integer; begin result:=0; p:=0; try ms:=TMemScan(JObjectToTObject(penv, obj)); if (ms<>nil) then begin p:=1; ms.GetProgress(total, current); p:=2; if total>0 then begin p:=3; result:=(current*100) div total; p:=4; //log(format('TMemScan_GetProgress returns %d',[result])); end end; p:=5; except on e:exception do log('Exception in TMemScan_GetProgress:'+e.message+' (p='+inttostr(p)); end; end; procedure TMemScan_NextScan(PEnv: PJNIEnv; Obj: JObject; scanOption: jint; roundingtype: jint; sv1: jstring; sv2: jstring; hexadecimal: jboolean; binaryasstring: jboolean; unicode: jboolean; casesensitive: jboolean; percentage: jboolean; compareToSavedScan: jboolean; ssn: jstring); cdecl; var ms: TJniMemscan; scanvalue1, scanvalue2, savedscanname: string; begin log('Next scan'); ms:=TJniMemscan(JObjectToTObject(penv, obj)); scanvalue1:=jniGetString(penv, sv1); scanvalue2:=jniGetString(penv, sv2); savedscanname:=jniGetString(penv, ssn); ms.NextScan(TScanOption(scanOption), TRoundingType(roundingtype), scanValue1, scanValue2, hexadecimal<>0, binaryAsString<>0, unicode<>0, casesensitive<>0, percentage<>0, comparetoSavedScan<>0, savedscanname); end; procedure TMemScan_FirstScan(PEnv: PJNIEnv; Obj: JObject; scanOption: jint; variabletype: jint; roundingtype: jint; sv1: jstring; sv2: jstring; pf: jstring; startaddress: jlong; stopaddress: jlong; fastscanmethod: jint; fastscanparameter: jstring; hexadecimal: jboolean; binaryasstring: jboolean; unicode: jboolean; casesensitive: jboolean; pagedonly: jboolean; dirtyonly: jboolean; noshared: jboolean); cdecl; var ms: TJniMemscan; scanvalue1, scanvalue2, protectionflags: string; c: jclass; begin log('First scan'); c:=penv^.FindClass(penv, 'org/cheatengine/TObject'); if penv^.IsInstanceOf(penv, obj, c)=0 then begin log('memscantest: obj<>TObject'); end; penv^.DeleteLocalRef(penv, c); ms:=TJniMemscan(JObjectToTObject(penv, obj)); Scan_MEM_MAPPED:=noshared=0; scan_dirtyonly:=dirtyonly<>0; scan_pagedonly:=pagedonly<>0; scanvalue1:=jniGetString(penv, sv1); scanvalue2:=jniGetString(penv, sv2); protectionflags:=jniGetString(penv, pf); log('scanvalue1='+scanvalue1); log('scanvalue2='+scanvalue2); log('protectionflags='+protectionflags); ms.parseProtectionflags(protectionflags); ms.firstscan(TScanOption(scanOption), TVariableType(variabletype), TRoundingType(roundingtype), scanvalue1, scanvalue2, startaddress, stopaddress, hexadecimal<>0, binaryasstring<>0, unicode<>0, casesensitive<>0, TFastScanMethod(fastscanmethod), jnigetstring(penv, fastscanparameter), nil); end; function TMemScan_HasDoneFirstScan(PEnv: PJNIEnv; Obj: JObject):jboolean; cdecl; var ms: TJniMemscan; begin ms:=TJniMemscan(JObjectToTObject(penv, obj)); result:=ifthen(ms.LastScanType<>stNewScan,1,0); end; function TMemScan_GetVarType(PEnv: PJNIEnv; Obj: JObject):jint; cdecl; var ms: TJniMemscan; begin ms:=TJniMemscan(JObjectToTObject(penv, obj)); result:=integer(ms.VarType); end; function TMemScan_GetBinarySize(PEnv: PJNIEnv; Obj: JObject):jint; cdecl; var ms: TJniMemscan; begin ms:=TJniMemscan(JObjectToTObject(penv, obj)); result:=ms.Getbinarysize; end; const methodcount=8; var jnimethods: array [0..methodcount-1] of JNINativeMethod =( (name: 'create'; signature: '(Lorg/cheatengine/TMemScan;)J'; fnPtr: @TMemScan_Create), (name: 'newScan'; signature: '()V'; fnPtr: @TMemScan_NewScan), (name: 'firstScan'; signature: '(IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;JJILjava/lang/String;ZZZZZZZ)V'; fnPtr: @TMemScan_FirstScan), (name: 'nextScan'; signature: '(IILjava/lang/String;Ljava/lang/String;ZZZZZZLjava/lang/String;)V'; fnPtr: @TMemScan_NextScan), (name: 'hasDoneFirstScan'; signature: '()Z'; fnPtr: @TMemScan_HasDoneFirstScan), (name: 'getVarType'; signature: '()I'; fnPtr: @TMemScan_GetVarType), (name: 'getProgress'; signature: '()I'; fnPtr: @TMemScan_GetProgress), (name: 'getBinarySize'; signature: '()I'; fnPtr: @TMemScan_GetBinarySize) ); procedure InitializeJniTMemScan(env: PJNIEnv); var c: jclass; begin log('InitializeJniTMemScan entry'); c:=env^.FindClass(env, 'org/cheatengine/TMemScan'); env^.RegisterNatives(env, c, @jnimethods[0], methodcount); scanDoneMethodID:=env^.GetMethodID(env, c, 'OnScanDone', '()V'); log('scanDoneMethodID='+inttohex(ptruint(scanDoneMethodID),8)); log('InitializeJniTMemScan exit'); end; end.