import subprocess
import glob
import os
import sys
import shutil
import soloud_codegen
UNSUPPORTED_TYPES = {
"int":0,
"unsigned char":0,
"void":0,
"const char *":0,
"char *":0,
"unsigned int":0,
"float":0,
"double":0,
"float *":1,
"File *":1,
"unsigned char *":1,
"const unsigned char *":1,
"short *":1
}
for soloud_type in soloud_codegen.soloud_type:
UNSUPPORTED_TYPES[soloud_type + " *"] = 0
restart = 1
while restart == 1:
restart = 0
idx = 0
for x in soloud_codegen.soloud_func:
if restart == 0:
delx = 0
if UNSUPPORTED_TYPES[x[0]] == 1:
delx = 1
for p in x[2]:
if len(p) > 0:
if UNSUPPORTED_TYPES[p[0]] == 1:
delx = 1
if delx == 1:
print("removing " + soloud_codegen.soloud_func[idx][1] + " (unsupported variable type)")
del soloud_codegen.soloud_func[idx]
restart = 1
else:
idx = idx + 1
fo = open("soloud.extension.gmx", "w")
PTRTYPE = "2"
C_TO_GMX_TYPES = {
"int":"2",
"unsigned char":"2",
"void":"2",
"const char *":PTRTYPE,
"char *":PTRTYPE,
"unsigned int":"2",
"float":"2",
"double":"2",
"float *":PTRTYPE,
"unsigned char *":PTRTYPE,
"const unsigned char *":PTRTYPE
}
for soloud_type in soloud_codegen.soloud_type:
C_TO_GMX_TYPES[soloud_type + " *"] = PTRTYPE
fo.write("""<!--SoLoud wrapper (extension) for game maker-->
<!--This Document is generated by gen_gamemaker.py, if you edit it by hand then you do so at your own risk!-->
<extension>
<name>soloud</name>
<version>1.0.0</version>
<packageID></packageID>
<ProductID>ACBD3CFF4E539AD869A0E8E3B4B022DD</ProductID>
<date>17/04/15</date>
<license>Free to use, also for commercial games.</license>
<description></description>
<helpfile></helpfile>
<androidProps>0</androidProps>
<iosProps>0</iosProps>
<installdir></installdir>
<classname></classname>
<androidclassname></androidclassname>
<sourcedir></sourcedir>
<androidsourcedir></androidsourcedir>
<macsourcedir></macsourcedir>
<maclinkerflags></maclinkerflags>
<androidinject></androidinject>
<iosSystemFrameworks/>
<iosThirdPartyFrameworks/>
<androidPermissions/>
<IncludedResources/>
<files>
<file>
<filename>soloud_gamemaker_dll.dll</filename>
<origname>extensions\soloud_gamemaker_dll.dll</origname>
<init></init>
<final></final>
<kind>1</kind>
<uncompress>0</uncompress>
<ConfigOptions>
<Config name="Default">
<CopyToMask>542113856</CopyToMask>
</Config>
</ConfigOptions>
<ProxyFiles>
<ProxyFile>
<Name>soloud_x86.dll</Name>
<TargetMask>1048640</TargetMask>
</ProxyFile>
<ProxyFile>
<Name>msvcr100.dll</Name>
<TargetMask>1048640</TargetMask>
</ProxyFile>
<ProxyFile>
<Name>soloud_gamemaker_dll.dll</Name>
<TargetMask>1048640</TargetMask>
</ProxyFile>
</ProxyFiles>
<functions>
""")
for x in soloud_codegen.soloud_func:
fo.write(" <function>\n")
fo.write(" <name>" + x[1] + "</name>\n")
fo.write(" <externalName>" + x[1] + "</externalName>\n")
fo.write(" <kind>11</kind>\n")
fo.write(" <help>Original function: ")
fo.write(x[0] + " " + x[1] + "(")
first = 1
for p in x[2]:
if len(p) > 0:
if first == 0:
fo.write(", ")
else:
first = 0
fo.write(p[0] + " " + p[1])
fo.write(")</help>\n")
fo.write(" <returnType>" + C_TO_GMX_TYPES[x[0]] + "</returnType>\n")
argcount = 0
for p in x[2]:
if len(p) > 0:
argcount = argcount + 1
fo.write(" <argCount>" + str(argcount) + "</argCount>\n")
fo.write(" <args>\n")
for p in x[2]:
if len(p) > 0:
fo.write(" <arg>" + C_TO_GMX_TYPES[p[0]] + "</arg>\n")
fo.write(" </args>\n")
fo.write(" </function>\n")
fo.write(""" </functions>
<constants>
""")
for x in soloud_codegen.soloud_enum:
fo.write(" <constant>\n")
fo.write(" <name>" + x + "</name>\n")
fo.write(" <value>" + str(soloud_codegen.soloud_enum[x]) + "</value>\n")
fo.write(" <hidden>0</hidden>\n")
fo.write(" </constant>\n")
fo.write(""" </constants>
</file>
</files>
</extension>
""")
fo.close()
print("soloud.extension.gmx generated")
fo = open("soloud_gamemaker_dll.c", "w")
fo.write("""/* SoLoud-gamemaker wrapper dll. Generated by gen_gamemaker-py */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
// Not exactly fast, but should do it for now..
struct PtrStore
{
double key;
void * val;
};
#define MAXSTORE 2048
static int gMaxStore = 0;
static struct PtrStore gStore[MAXSTORE];
static void* doubleToPointer(double d)
{
int i;
if (d == 0)
return 0;
for (i = 0; i < gMaxStore; i++)
if (gStore[i].key == d)
return gStore[i].val;
return 0;
}
static double pointerToDouble(void *p)
{
double key = gMaxStore+1;
if (p == 0)
return 0;
if (gMaxStore == MAXSTORE)
return 0;
gStore[gMaxStore].val = p;
gStore[gMaxStore].key = key;
gMaxStore++;
return key;
}
static HMODULE openDll()
{
HMODULE res;
res = LoadLibraryA("soloud_x86.dll");
return res;
}
static void* getDllProc(HMODULE aDllHandle, const char *aProcName)
{
return GetProcAddress(aDllHandle, aProcName);
}
static HMODULE dll = NULL;
static void* getSoloudProc(const char *aProcName)
{
void *ret;
if (!dll)
dll = openDll();
if (!dll)
return 0;
ret = getDllProc(dll, aProcName);
return ret;
}
""")
MASK_TYPES = {
"int":"int",
"unsigned char":"unsigned char",
"void":"void",
"const char *":"const char *",
"char *":"char *",
"unsigned int":"unsigned int",
"float":"float",
"double":"double",
"float *":"float *",
"unsigned char *":"usigned char *",
"const unsigned char *":"const usigned char *"
}
for soloud_type in soloud_codegen.soloud_type:
MASK_TYPES[soloud_type + " *"] = "void *"
for x in soloud_codegen.soloud_func:
fo.write("typedef " + MASK_TYPES[x[0]] + " (*dllproc_" + x[1] + ")(")
first = 1
for p in x[2]:
if len(p) > 0:
if first == 0:
fo.write(", ")
else:
first = 0
fo.write(MASK_TYPES[p[0]] + " " + p[1])
fo.write(");\n")
fo.write("\n")
for x in soloud_codegen.soloud_func:
fo.write("dllproc_" + x[1] + " p_" + x[1] + " = NULL;\n")
fo.write("\n")
C_TO_GMX_DLL_TYPES = {
"int":"double",
"unsigned char":"double",
"void":"double",
"const char *":"char *",
"char *":"char *",
"unsigned int":"double",
"float":"double",
"double":"double",
"float *":"char *",
"unsigned char *":"char *",
"const unsigned char *":"char *"
}
for soloud_type in soloud_codegen.soloud_type:
C_TO_GMX_DLL_TYPES[soloud_type + " *"] = "double"
IS_HANDLE_TYPE = {
"int":0,
"void":0,
"const char *":0,
"char *":0,
"const unsigned char *":0,
"unsigned int":0,
"float":0,
"double":0,
"float *":0,
"unsigned char *":0,
"unsigned char":0
}
for soloud_type in soloud_codegen.soloud_type:
IS_HANDLE_TYPE[soloud_type + " *"] = 1
for x in soloud_codegen.soloud_func:
fo.write(C_TO_GMX_DLL_TYPES[x[0]] + " " + x[1] + "(")
first = 1
for p in x[2]:
if len(p) > 0:
if first == 0:
fo.write(", ")
else:
first = 0
fo.write(C_TO_GMX_DLL_TYPES[p[0]] + " " + p[1])
fo.write(")\n")
fo.write("{\n")
fo.write(" if (p_" + x[1] + " == NULL)\n")
fo.write(" p_" + x[1] + " = getSoloudProc(\"" + x[1] + "\");\n")
fo.write(" if (p_" + x[1] + " == NULL)\n")
if (x[0] == "void"):
fo.write(" return 0;\n")
else:
fo.write(" return (" + C_TO_GMX_DLL_TYPES[x[0]] + ")0;\n")
if (x[0] == "void"):
fo.write(" p_" + x[1] + "(")
else:
if IS_HANDLE_TYPE[x[0]]:
fo.write(" return ("+ C_TO_GMX_DLL_TYPES[x[0]] + ")pointerToDouble(p_" + x[1] + "(")
else:
fo.write(" return ("+ C_TO_GMX_DLL_TYPES[x[0]] + ")p_" + x[1] + "(")
first = 1
for p in x[2]:
if len(p) > 0:
if first == 0:
fo.write(", ")
else:
first = 0
if IS_HANDLE_TYPE[p[0]] == 1:
fo.write("(" + MASK_TYPES[p[0]] + ")doubleToPointer(" + p[1] + ")")
else:
fo.write("(" + MASK_TYPES[p[0]] + ")" + p[1])
if IS_HANDLE_TYPE[x[0]]:
fo.write("));\n")
else:
fo.write(");\n")
if (x[0] == "void"):
fo.write(" return 0;\n")
fo.write("}\n")
fo.write("\n")
fo.close()
print("soloud_gamemaker_dll.c generated")
fo = open("soloud_gamemaker_dll.def", "w")
fo.write("EXPORTS\n")
for x in soloud_codegen.soloud_func:
fo.write("\t" + x[1] + "\n")
fo.close()
print("soloud_gamemaker_dll.def generated")
print("compiling dll")
callp = ["compile_gamemaker_dll.bat"]
subprocess.call(callp)
if not os.path.exists("gm_temp/soloud"):
os.makedirs("gm_temp/soloud")
print("copying files to gm_temp")
shutil.copy("soloud.extension.gmx", "gm_temp")
shutil.copy("soloud_gamemaker_dll.dll", "gm_temp/soloud")
shutil.copy("../lib/soloud_x86.dll", "gm_temp/soloud")
callp = ["make_gmez.bat"]
subprocess.call(callp)