libpicasso/source/picasso_frontend.cpp
2014-11-16 18:59:54 +01:00

205 lines
4.5 KiB
C++

#include "picasso.h"
// !! Taken from ctrulib !!
u32 f32tof24(float vf)
{
if (!vf) return 0;
union { float f; u32 v; } q;
q.f=vf;
u8 s = q.v>>31;
u32 exp = ((q.v>>23) & 0xFF) - 0x40;
u32 man = (q.v>>7) & 0xFFFF;
if (exp >= 0)
return man | (exp<<16) | (s<<23);
else
return s<<23;
}
#ifdef WIN32
static inline void FixMinGWPath(char* buf)
{
if (buf && *buf == '/')
{
buf[0] = buf[1];
buf[1] = ':';
}
}
#endif
int usage(const char* prog)
{
fprintf(stderr,
"Usage:\n\n"
"%s shbinFile vshFile [hFile]\n", prog);
return 0;
}
int main(int argc, char* argv[])
{
if (argc < 3 || argc > 4)
return usage(argv[0]);
char* shbinFile = argv[1];
char* vshFile = argv[2];
char* hFile = argc > 3 ? argv[3] : NULL;
#ifdef WIN32
FixMinGWPath(shbinFile);
FixMinGWPath(vshFile);
FixMinGWPath(hFile);
#endif
char* sourceCode = StringFromFile(vshFile);
if (!sourceCode)
{
fprintf(stderr, "Cannot open input file!\n");
return 1;
}
int rc = AssembleString(sourceCode, vshFile);
free(sourceCode);
if (rc != 0)
return rc;
auto mainIt = g_procTable.find("main");
if (mainIt == g_procTable.end())
{
fprintf(stderr, "Error: main proc not defined\n");
return 1;
}
//if (g_opdescCount > 9)
// printf("WARNING: currently using more than 9 opdescs -- libctru has a bug\n");
FileClass f(shbinFile, "wb");
if (f.openerror())
{
fprintf(stderr, "Can't open output file!");
return 1;
}
f.WriteWord(0x424C5644); // DVLB
f.WriteWord(1); // 1 DVLE
f.WriteWord(3*4 + 0x28); // offset to DVLE
u32 dvlpStart = f.Tell();
u32 shaderSize = g_outputBuf.size();
u32 paramStart = 0x28 + 0x40;
f.WriteWord(0x504C5644); // DVLP
f.WriteWord(0); // version
f.WriteWord(paramStart); // offset to shader binary blob
f.WriteWord(shaderSize); // size of shader binary blob
paramStart += shaderSize*4;
f.WriteWord(paramStart); // offset to opdesc table
f.WriteWord(g_opdescCount); // number of opdescs
paramStart += g_opdescCount*8;
f.WriteWord(paramStart); // offset to symtable (TODO)
f.WriteWord(0); // ????
f.WriteWord(0); // ????
f.WriteWord(0); // ????
u32 dvleStart = f.Tell();
paramStart -= dvleStart - dvlpStart;
f.WriteWord(0x454C5644); // DVLE
f.WriteHword(0); // padding?
f.WriteHword(0); // Vertex shader
f.WriteWord(mainIt->second.first); // offset to main
f.WriteWord(mainIt->second.first+mainIt->second.second); // offset to end of main
f.WriteWord(0); // ???
f.WriteWord(0); // ???
f.WriteWord(paramStart); // offset to constant table
f.WriteWord(g_constantCount); // size of constant table
paramStart += g_constantCount*0x14;
f.WriteWord(paramStart); // offset to label table (TODO)
f.WriteWord(0); // size of label table (TODO)
f.WriteWord(paramStart); // offset to output table
f.WriteWord(g_outputCount); // size of output table
paramStart += g_outputCount*8;
f.WriteWord(paramStart); // offset to uniform table
f.WriteWord(g_uniformCount); // size of uniform table
paramStart += g_uniformCount*8;
f.WriteWord(paramStart); // offset to symbol table
u32 temp = f.Tell();
f.WriteWord(0); // size of symbol table
// Write program
for (u32 p : g_outputBuf)
f.WriteWord(p);
// Write opdescs
for (int i = 0; i < g_opdescCount; i ++)
{
f.WriteWord(g_opdescTable[i]);
f.WriteWord(0x0000000F); // unknown
}
// Write constants
for (int i = 0; i < g_constantCount; i ++)
{
auto& ct = g_constantTable[i];
f.WriteHword(0);
f.WriteByte(ct.regId-0x20);
f.WriteByte(0);
for (int j = 0; j < 4; j ++)
f.WriteWord(f32tof24(ct.param[j]));
}
// Write outputs
for (int i = 0; i < g_outputCount; i ++)
f.WriteDword(g_outputTable[i]);
// Write uniforms
size_t sp = 0;
for (int i = 0; i < g_uniformCount; i ++)
{
auto& u = g_uniformTable[i];
size_t l = strlen(u.name)+1;
f.WriteWord(sp); sp += l;
f.WriteHword(u.pos-0x20);
f.WriteHword(u.pos+u.size-1-0x20);
}
// Write size of symbol table
u32 temp2 = f.Tell();
f.Seek(temp, SEEK_SET);
f.WriteWord(sp);
f.Seek(temp2, SEEK_SET);
// Write symbols
for (int i = 0; i < g_uniformCount; i ++)
{
auto u = g_uniformTable[i].name;
size_t l = strlen(u)+1;
f.WriteRaw(u, l);
}
if (hFile)
{
auto f2 = fopen(hFile, "w");
if (!f2)
{
fprintf(stderr, "Can't open header file!\n");
return 1;
}
fprintf(f2, "// Generated by picasso\n");
fprintf(f2, "#pragma once\n");
for (int i = 0; i < g_uniformCount; i ++)
{
auto& u = g_uniformTable[i];
fprintf(f2, "#define SHADER_UREG_%s 0x%02X\n", u.name, u.pos-0x20);
fprintf(f2, "#define SHADER_ULEN_%s %d\n", u.name, u.size);
}
fclose(f2);
}
return 0;
}