205 lines
4.5 KiB
C++
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;
|
|
}
|