Edit: Before you read this post: I have already managed to solve the problems myself. I will make a later post on how to I compiled the full Mandel Machine when I understand better why it worked this time and when I'm more confident that it actually works well.
The definition "JNIEXPORT" indicates exported functions, I assume simliar to "__declspec(dllexport)"
There are only 12 exported functions:
1. Java_mm_WorkerThread_getItNative_164a
2. Java_mm_WorkerThread_getItNative_164b
3. Java_mm_WorkerThread_getItNativeEx
4. Java_mm_WorkerThread_getCPUid
5. Java_mm_WorkerThread_getIterationsPTnativeF
6. Java_mm_WorkerThread_getIterationsPTnativeD
7. Java_mm_WorkerThread_getIterationsPTnativeEx
8. Java_mm_WorkerThread_setOrbit
9. Java_mm_WorkerThread_freeOrbit
10. Java_mm_WorkerThread_initRefOrbCoeffsEx
11. Java_mm_WorkerThread_doAuxIterationEx
12. Java_mm_WorkerThread_getIterationsDnative
So, what do they do and how are they called?
I spent my time today reading about how java works, to understand more about how Mandel Machine works. According to some sites, functions from a dll should be declared with the keyword native in java. There are more functions in the java code with this keyword. All of them are declared in WorkerThread.java:
private static native int getItNative03_32(double[] iterArray, int index, int[] zxzy, int maxIterations, double bailout, final double lnlnbailout);
private static native int getItNative04_32(double[] iterArray, int index, int[] zxzy, int maxIterations, double bailout, final double lnlnbailout);
... it goes from 3 through 35
private static native int getItNative34_32(double[] iterArray, int index, int[] zxzy, int maxIterations, double bailout, final double lnlnbailout);
private static native int getItNative35_32(double[] iterArray, int index, int[] zxzy, int maxIterations, double bailout, final double lnlnbailout);
private static native void getItNative_64a(long[] zxzy, int minIterations, int maxIterations, double bailout, int fracs);
public static native void getItNative_64b(long[] zxzy, int maxIterations, double bailout, int fracs, double[] refOrbXYD, long[] refOrbXYE, int refOrbLength2, double mul, double glitchAbsThreshold, boolean extended);
private static native int getItNativeEx(double[] zxzyb, int minIterations, int maxIterations, boolean computeDE);
public static native void setOrbit(float[] referenceOrbitF, double[] referenceOrbitD, long[] referenceOrbitE);
public static native void freeOrbit();
public static native void initRefOrbCoeffsEx(long[] coeffsEx, int serApproxTerms, int coeffsScaleMode);
public static native void doAuxIterationEx(long[] coeffsEx, int serApproxTerms, int coeffsScaleMode, double[] refOrbXYs);
private static native void getIterationsDnative(int minIterations, int maxIterations, long zxzyb4Ptr, int pixels, int simdMode, boolean computeDE);
private static native void getIterationsPTnativeF(long minIterations, int orbitLength, long dxdyb4Ptr, int scale, int pixels, int simdMode);
private static native void getIterationsPTnativeD(long minIterations, int orbitLength, double[] dxdyb4, int scale, int pixels, int simdMode, boolean ignore);
private static native void getIterationsPTnativeEx(long minIterations, int orbitLength, double[] dxdyb, boolean ignore, boolean extendedReference);
public static native void getCPUid(long resultsPtr);
The remaining functions are declared in mm64.cpp and exist in mm64core.asm, so they must be the functions written in assembly language.
The source of the dll is availabe and consist of only 3 files:
mm_WorkerThread.h
mm64.cpp
mm64core.asm
...
I was able to compile the code by adding the following piece of code in the top of mm_WorkerThread.h, that defines the used datatypes and implements JNIEnv (although always return NULL):
#define JNIEXPORT __declspec(dllexport)
#define JNICALL
#define jclass void *
#define jint int
#define jdoubleArray double *
#define jfloatArray float *
#define jdouble double
#define jlong __int64
#define jlongArray __int64 *
#define jboolean bool
#define JNI_TRUE 1
#define JNI_ABORT -1
class JNIEnv
{
public:
double *GetPrimitiveArrayCritical(jdoubleArray dbla, jboolean isCopy)
{
return NULL;
}
jlongArray GetPrimitiveArrayCritical(jlongArray jzx,jboolean isCopy)
{
return NULL;
}
void ReleasePrimitiveArrayCritical(jdoubleArray dbla, jdouble* xyzbailout, jint i)
{
}
void ReleasePrimitiveArrayCritical(jlongArray dbla, jlong* xyzbailout, jint i)
{
}
void ReleaseFloatArrayElements(jfloatArray orbxyFref, float * orbxyF,jint i)
{
}
void DeleteGlobalRef(jfloatArray orbxyFref)
{
}
void DeleteGlobalRef(jdoubleArray orbxyFref)
{
}
void DeleteGlobalRef(jlongArray orbxyFref)
{
}
void ReleaseDoubleArrayElements(jdoubleArray orbxyDref, double *orbxyD, jint i)
{
}
void ReleaseLongArrayElements(jlongArray orbxyEref, __int64 *orbxyE, jint i)
{
}
double *GetDoubleArrayElements(jdoubleArray orbxyDref,jint i)
{
return NULL;
}
float *GetFloatArrayElements(jfloatArray orbxyFref,jint i)
{
return NULL;
}
__int64 *GetLongArrayElements(jlongArray orbxyEref,jint i)
{
return NULL;
}
jfloatArray NewGlobalRef(jfloatArray orbitXYF)
{
return NULL;
}
jlongArray NewGlobalRef(jlongArray orbitXYE)
{
return NULL;
}
jdoubleArray NewGlobalRef(jdoubleArray orbitXYD)
{
return NULL;
}
};
How do you do this? I tried using g++ from the commandline in cygwin64 to compile mm64.cpp. It fails (collect2: error: ld returned 1 exit status), so I inserted your piece of code, which changes the error to a lot of these:mm_WorkerThread.h:4:14: error: declaration does not declare anything [-fpermissive]
#define jint int
^
I googled the error, did some things without understanding what I was doing, which made this specific error go away and lead to another error, and another... So I can't get this compiled. Apparently it didn't normally work for you either (without the extra code). Do you have an idea why? I would assume the source code as shared by Botond Kosa be complete and we shouldn't need to change anything.I tried to find the reference to the file containing the assembly language, because that's what the dll is really about, and couldn't find it. It makes me wonder how this code was supposed to be used.
Edit:
Apparently, this is how a c file with functions in assembly language should be compiled. Taken from an example from the JWasm assembler:
gcc -c mixed1c.c
jwasm -coff mixed132.asm
gcc mixed1c.o mixed132.obj -o mixed1c.exe
JWasm is not the correct assembler for Mandel Machine's source code - it's just where I found the example. I have now found out the right one is probably ml64, an executable included in some microsoft software packages including Visual Studio. It's very hard to find otherwise. I downloaded Visual Studio 2013 (several gigabytes) and installed it in a virtual machine only to copy the ml64.exe that's just 500 kB. Using that and assuming c++ should be compiled the same way as c, this is what I did:
ml64 /c mm64core.asm
g++ -c mm64.cpp
g++ mm64.o mm64core.obj -o mm64.dll
This assembles mm64core.asm to mm64core.obj, compiles mm64.cpp to mm64.o and links the two files to form mm64.dll.
This generates a dll. That's a good sign. Unfortunately the dll makes Mandel Machine crash, so I'm still not doing something right. (Mandel Machine can start succesfully when it doesn't need to use the dll: for example when a parameter file with iteration data is last loaded.)
This works. Thanks.
There is still a problem which I'm not sure what's causing it. I used mm64.dll from version 1.3.10 because the source code is for that version. The application crashes when zooming to exactly 1951 zooms or more. (Using the latest mm64.dll from version 1.3.15 doesn't allow zooming beyond 43 zooms.)Edit: Ignore this. Parameter files with higher magnifications can be loaded succesfully and I can continue zooming without problems so it's probably just a bug.