#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; procTableIter mainIt = g_procTable.find("main"); if (mainIt == g_procTable.end()) { fprintf(stderr, "Error: main proc not defined\n"); return 1; } 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_constantSize; 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) 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 constants for (int i = 0; i < g_constantCount; i ++) { Constant& ct = g_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 < g_outputCount; i ++) f.WriteDword(g_outputTable[i]); // Write uniforms size_t sp = 0; for (int i = 0; i < g_uniformCount; i ++) { Uniform& u = g_uniformTable[i]; size_t l = strlen(u.name)+1; f.WriteWord(sp); sp += l; f.WriteHword(u.pos-0x10); f.WriteHword(u.pos+u.size-1-0x10); } // 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 ++) { const char* u = g_uniformTable[i].name; size_t l = strlen(u)+1; f.WriteRaw(u, l); } 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"); for (int i = 0; i < g_uniformCount; i ++) { Uniform& u = g_uniformTable[i]; if (u.type == UTYPE_FVEC) fprintf(f2, "#define SHADER_FVEC_%s 0x%02X\n", u.name, u.pos-0x20); else if (u.type == UTYPE_IVEC) fprintf(f2, "#define SHADER_IVEC_%s 0x%02X\n", u.name, u.pos-0x80); else if (u.type == UTYPE_BOOL) { if (u.size == 1) fprintf(f2, "#define SHADER_FLAG_%s BIT(%d)\n", u.name, u.pos-0x88); else fprintf(f2, "#define SHADER_FLAG_%s(_n) BIT(%d+(_n))\n", u.name, u.pos-0x88); } fprintf(f2, "#define SHADER_ULEN_%s %d\n", u.name, u.size); } fclose(f2); } return 0; }