
- picasso now accepts several input files, which are each compiled into DVLE objects inside the .shbin - Uniform allocation is shared amongst all DVLEs. - Constant allocation is private to each DVLE. - Header file generation is temporarily disabled. - New directives: .nodvle Disables the generation of a DVLE object for the current input file. This allows sharing code amongst shaders. .entry entryName Specifies the name of the entrypoint procedure of the current DVLE. By default it's 'main'.
234 lines
5.4 KiB
C++
234 lines
5.4 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 output.shbin input1.pica input2.pica ...\n", prog);
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
if (argc < 3)
|
|
return usage(argv[0]);
|
|
|
|
char* shbinFile = argv[1];
|
|
//char* hFile = argc > 3 ? argv[3] : NULL;
|
|
|
|
#ifdef WIN32
|
|
FixMinGWPath(shbinFile);
|
|
//FixMinGWPath(hFile);
|
|
#endif
|
|
|
|
int rc = 0;
|
|
for (int i = 2; i < argc; i ++)
|
|
{
|
|
char* vshFile = argv[i];
|
|
|
|
#ifdef WIN32
|
|
FixMinGWPath(vshFile);
|
|
#endif
|
|
|
|
char* sourceCode = StringFromFile(vshFile);
|
|
if (!sourceCode)
|
|
{
|
|
fprintf(stderr, "error: cannot open input file: %s\n");
|
|
return 1;
|
|
}
|
|
|
|
rc = AssembleString(sourceCode, vshFile);
|
|
free(sourceCode);
|
|
if (rc != 0)
|
|
return rc;
|
|
}
|
|
|
|
rc = RelocateProduct();
|
|
if (rc != 0)
|
|
return rc;
|
|
|
|
FileClass f(shbinFile, "wb");
|
|
|
|
if (f.openerror())
|
|
{
|
|
fprintf(stderr, "Can't open output file!");
|
|
return 1;
|
|
}
|
|
|
|
u32 progSize = g_outputBuf.size();
|
|
u32 dvlpSize = 10*4 + progSize*4 + g_opdescCount*8;
|
|
|
|
// Write DVLB header
|
|
f.WriteWord(0x424C5644); // DVLB
|
|
f.WriteWord(g_totalDvleCount); // Number of DVLEs
|
|
|
|
// Calculate and write DVLE offsets
|
|
u32 curOff = 2*4 + g_totalDvleCount*4 + dvlpSize;
|
|
for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end(); ++dvle)
|
|
{
|
|
if (dvle->nodvle) continue;
|
|
f.WriteWord(curOff);
|
|
curOff += 16*4; // Header
|
|
curOff += dvle->constantSize;
|
|
curOff += dvle->outputCount*8;
|
|
curOff += dvle->uniformCount*8;
|
|
curOff += dvle->symbolSize;
|
|
}
|
|
|
|
// Write DVLP header
|
|
f.WriteWord(0x504C5644); // DVLP
|
|
f.WriteWord(0); // version
|
|
f.WriteWord(10*4); // offset to shader binary blob
|
|
f.WriteWord(progSize); // size of shader binary blob
|
|
f.WriteWord(10*4 + progSize*4); // offset to opdesc table
|
|
f.WriteWord(g_opdescCount); // number of opdescs
|
|
f.WriteWord(dvlpSize); // offset to symtable (TODO)
|
|
f.WriteWord(0); // ????
|
|
f.WriteWord(0); // ????
|
|
f.WriteWord(0); // ????
|
|
|
|
// Write program
|
|
for (outputBufIter it = g_outputBuf.begin(); it != g_outputBuf.end(); ++it)
|
|
f.WriteWord(*it);
|
|
|
|
// Write opdescs
|
|
for (int i = 0; i < g_opdescCount; i ++)
|
|
f.WriteDword(g_opdescTable[i]);
|
|
|
|
// Write DVLEs
|
|
for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end(); ++dvle)
|
|
{
|
|
if (dvle->nodvle) continue;
|
|
curOff = 16*4;
|
|
|
|
f.WriteWord(0x454C5644); // DVLE
|
|
f.WriteHword(0); // padding?
|
|
f.WriteHword(dvle->isGeoShader ? 1 : 0); // Shader type
|
|
f.WriteWord(dvle->entryStart); // offset to main
|
|
f.WriteWord(dvle->entryEnd); // offset to end of main
|
|
f.WriteWord(0); // ???
|
|
f.WriteWord(0); // ???
|
|
f.WriteWord(curOff); // offset to constant table
|
|
f.WriteWord(dvle->constantCount); // size of constant table
|
|
curOff += dvle->constantSize;
|
|
f.WriteWord(curOff); // offset to label table (TODO)
|
|
f.WriteWord(0); // size of label table (TODO)
|
|
f.WriteWord(curOff); // offset to output table
|
|
f.WriteWord(dvle->outputCount); // size of output table
|
|
curOff += dvle->outputCount*8;
|
|
f.WriteWord(curOff); // offset to uniform table
|
|
f.WriteWord(dvle->uniformCount); // size of uniform table
|
|
curOff += dvle->uniformCount*8;
|
|
f.WriteWord(curOff); // offset to symbol table
|
|
u32 temp = f.Tell();
|
|
f.WriteWord(dvle->symbolSize); // size of symbol table
|
|
|
|
// Write constants
|
|
for (int i = 0; i < dvle->constantCount; i ++)
|
|
{
|
|
Constant& ct = dvle->constantTable[i];
|
|
f.WriteHword(ct.type);
|
|
if (ct.type == UTYPE_FVEC)
|
|
{
|
|
f.WriteHword(ct.regId-0x20);
|
|
for (int j = 0; j < 4; j ++)
|
|
f.WriteWord(f32tof24(ct.fparam[j]));
|
|
} else if (ct.type == UTYPE_IVEC)
|
|
{
|
|
f.WriteHword(ct.regId-0x80);
|
|
for (int j = 0; j < 4; j ++)
|
|
f.WriteByte(ct.iparam[j]);
|
|
}
|
|
}
|
|
|
|
// Write outputs
|
|
for (int i = 0; i < dvle->outputCount; i ++)
|
|
f.WriteDword(dvle->outputTable[i]);
|
|
|
|
// Write uniforms
|
|
size_t sp = 0;
|
|
for (int i = 0; i < dvle->uniformCount; i ++)
|
|
{
|
|
Uniform& u = dvle->uniformTable[i];
|
|
size_t l = u.name.length()+1;
|
|
f.WriteWord(sp); sp += l;
|
|
f.WriteHword(u.pos-0x10);
|
|
f.WriteHword(u.pos+u.size-1-0x10);
|
|
}
|
|
|
|
// Write symbols
|
|
for (int i = 0; i < dvle->uniformCount; i ++)
|
|
{
|
|
std::string& u = dvle->uniformTable[i].name;
|
|
size_t l = u.length()+1;
|
|
f.WriteRaw(u.c_str(), l);
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
if (hFile)
|
|
{
|
|
FILE* 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");
|
|
const char* prefix = g_isGeoShader ? "GSH" : "VSH";
|
|
for (int i = 0; i < g_uniformCount; i ++)
|
|
{
|
|
Uniform& u = g_uniformTable[i];
|
|
const char* name = u.name.c_str();
|
|
if (u.type == UTYPE_FVEC)
|
|
fprintf(f2, "#define %s_FVEC_%s 0x%02X\n", prefix, name, u.pos-0x20);
|
|
else if (u.type == UTYPE_IVEC)
|
|
fprintf(f2, "#define %s_IVEC_%s 0x%02X\n", prefix, name, u.pos-0x80);
|
|
else if (u.type == UTYPE_BOOL)
|
|
{
|
|
if (u.size == 1)
|
|
fprintf(f2, "#define %s_FLAG_%s BIT(%d)\n", prefix, name, u.pos-0x88);
|
|
else
|
|
fprintf(f2, "#define %s_FLAG_%s(_n) BIT(%d+(_n))\n", prefix, name, u.pos-0x88);
|
|
}
|
|
fprintf(f2, "#define %s_ULEN_%s %d\n", prefix, name, u.size);
|
|
}
|
|
|
|
fclose(f2);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|