void ShaderCombiner_Init()
{
    //compile vertex shader:
    GLint success;
    const char *src[1];
    char buff[4096];
    char *str = buff;

    str += sprintf(str, "%s", _vert);
    if (config.enableFog)
    {
        str += sprintf(str, "%s", _vertfog);
    }
    if (config.zHack)
    {
        str += sprintf(str, "%s", _vertzhack);
    }

    str += sprintf(str, "}\n\n");

    src[0] = buff;
    _vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(_vertex_shader, 1, (const char**) src, NULL);
    glCompileShader(_vertex_shader);
    glGetShaderiv(_vertex_shader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        _glcompiler_error(_vertex_shader);
    }
};
void ShaderCombiner_Init()
{
    //compile vertex shader:
    GLint success;
    const char *src[1];
    char buff[4096];
    char *str = buff;

    str += sprintf(str, "%s", _vert);
    if (config.enableFog)
    {
        str += sprintf(str, "%s", _vertfog);
    }
    if (config.zHack)
    {
        str += sprintf(str, "%s", _vertzhack);
    }

    str += sprintf(str, "}\n\n");

#ifdef PRINT_SHADER
    LOG(LOG_VERBOSE, "=============================================================\n");
    LOG(LOG_VERBOSE, "Vertex Shader:\n");
    LOG(LOG_VERBOSE, "=============================================================\n");
    LOG(LOG_VERBOSE, "%s", buff);
    LOG(LOG_VERBOSE, "=============================================================\n");
#endif
	buff[4095] = 0;
    src[0] = buff;
    _vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(_vertex_shader, 1, (const char**) src, NULL);
	OPENGL_CHECK_ERRORS;

    glCompileShader(_vertex_shader);
	OPENGL_CHECK_ERRORS;

    glGetShaderiv(_vertex_shader, GL_COMPILE_STATUS, &success);
	OPENGL_CHECK_ERRORS;

    if (!success)
    {
		printf("Shader Source:\n%s\n", buff);
        _glcompiler_error(_vertex_shader);
    }
	else
	{
		//printf("%d Shader COMPILED\n", __LINE__);
	}
};
ShaderProgram *ShaderCombiner_Compile(DecodedMux *dmux, int flags)
{
    GLint success;
    char frag[4096];
    char *buffer = frag;
    ShaderProgram *prog = (ShaderProgram*) malloc(sizeof(ShaderProgram));

    prog->left = prog->right = NULL;
    prog->usesT0 = prog->usesT1 = prog->usesCol = prog->usesNoise = 0;
    prog->combine = dmux->combine;
    prog->flags = flags;
    prog->vertex = _vertex_shader;

    for(int i=0; i < ((flags & SC_2CYCLE) ? 4 : 2); i++)
    {
        //make sure were not ignoring cycle:
        if ((dmux->flags&(1<<i)) == 0)
        {
            for(int j=0;j<4;j++)
            {
                prog->usesT0 |= (dmux->decode[i][j] == TEXEL0 || dmux->decode[i][j] == TEXEL0_ALPHA);
                prog->usesT1 |= (dmux->decode[i][j] == TEXEL1 || dmux->decode[i][j] == TEXEL1_ALPHA);
                prog->usesCol |= (dmux->decode[i][j] == SHADE || dmux->decode[i][j] == SHADE_ALPHA);
                prog->usesNoise |= (dmux->decode[i][j] == NOISE);
            }
        }
    }

    buffer += sprintf(buffer, "%s", _frag_header);
    if (prog->usesT0)
        buffer += sprintf(buffer, "lowp vec4 lTex0 = texture2D(uTex0, vTexCoord0); \n");
    if (prog->usesT1)
        buffer += sprintf(buffer, "lowp vec4 lTex1 = texture2D(uTex1, vTexCoord1); \n");
    if (prog->usesNoise)
        buffer += sprintf(buffer, "lowp vec4 lNoise = texture2D(uNoise, (1.0 / 1024.0) * gl_FragCoord.st); \n");

    for(int i = 0; i < ((flags & SC_2CYCLE) ? 2 : 1); i++)
    {
        if ((dmux->flags&(1<<(i*2))) == 0)
        {
            buffer += sprintf(buffer, "lFragColor.rgb = (%s - %s) * %s + %s; \n",
                _color_param_str(dmux->decode[i*2][0]),
                _color_param_str(dmux->decode[i*2][1]),
                _color_param_str(dmux->decode[i*2][2]),
                _color_param_str(dmux->decode[i*2][3])
                );
        }

        if ((dmux->flags&(1<<(i*2+1))) == 0)
        {
            buffer += sprintf(buffer, "lFragColor.a = (%s - %s) * %s + %s; \n",
                _alpha_param_str(dmux->decode[i*2+1][0]),
                _alpha_param_str(dmux->decode[i*2+1][1]),
                _alpha_param_str(dmux->decode[i*2+1][2]),
                _alpha_param_str(dmux->decode[i*2+1][3])
                );
        }
        buffer += sprintf(buffer, "gl_FragColor = lFragColor; \n");
    };

    //fog
    if (flags&SC_FOGENABLED)
    {
        buffer += sprintf(buffer, "gl_FragColor = mix(gl_FragColor, uFogColor, vFactor); \n");
    }

    //alpha function
    if (flags&SC_ALPHAENABLED)
    {
        if (flags&SC_ALPHAGREATER)
            buffer += sprintf(buffer, "if (gl_FragColor.a < uAlphaRef) %s;\n", config.hackAlpha ? "gl_FragColor.a = 0" : "discard");
        else
            buffer += sprintf(buffer, "if (gl_FragColor.a <= uAlphaRef) %s;\n", config.hackAlpha ? "gl_FragColor.a = 0" : "discard");
    }
    buffer += sprintf(buffer, "} \n\n");
    *buffer = 0;

#ifdef PRINT_SHADER
    LOG(LOG_VERBOSE, "=============================================================\n");
    LOG(LOG_VERBOSE, "Combine=0x%llx flags=0x%x dmux flags=0x%x\n", prog->combine.mux, flags, dmux->flags);
    LOG(LOG_VERBOSE, "Num=%i \t usesT0=%i usesT1=%i usesCol=%i usesNoise=%i\n", scProgramCount, prog->usesT0, prog->usesT1, prog->usesCol, prog->usesNoise);
    LOG(LOG_VERBOSE, "=============================================================\n");
    LOG(LOG_VERBOSE, "%s", frag);
    LOG(LOG_VERBOSE, "=============================================================\n");
#endif

    prog->program = glCreateProgram();

    //Compile:
    char *src[1];
    src[0] = frag;
    GLint len[1];
    len[0] = min(4096, strlen(frag));
    prog->fragment = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(prog->fragment, 1, (const char**) src, len);
    glCompileShader(prog->fragment);


    glGetShaderiv(prog->fragment, GL_COMPILE_STATUS, &success);
    if (!success)
    {
		printf("%d Shader Source:\n%s\n", __LINE__, frag);
        _glcompiler_error(prog->fragment);
    }
	else
	{
		//printf("%d Shader COMPILED\n", __LINE__);
	}

    //link
    _locate_attributes(prog);
    glAttachShader(prog->program, prog->fragment);
    glAttachShader(prog->program, prog->vertex);
    glLinkProgram(prog->program);
    glGetProgramiv(prog->program, GL_LINK_STATUS, &success);
    if (!success)
    {
        _gllinker_error(prog->program);
    }
	else
	{
		//printf("%d Program COMPILED\n", __LINE__);
	}
    //remove fragment shader:
    glDeleteShader(prog->fragment);

    _locate_uniforms(prog);
    return prog;
}