diff --git a/configure.ac b/configure.ac index 1a7ba6c..3c9a819 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([picasso],[1.0.0],[fincs.alt1@gmail.com]) +AC_INIT([picasso],[2.0.0],[fincs.alt1@gmail.com]) AC_CONFIG_SRCDIR([source/picasso_frontend.cpp]) AM_INIT_AUTOMAKE([1.10]) diff --git a/source/picasso.h b/source/picasso.h index 48c8e56..a41c4d6 100644 --- a/source/picasso.h +++ b/source/picasso.h @@ -58,10 +58,13 @@ enum COND_UNK2, }; +//----------------------------------------------------------------------------- +// Global data +//----------------------------------------------------------------------------- + +// Output buffer typedef std::vector outputBufType; typedef outputBufType::iterator outputBufIter; - -extern bool g_isGeoShader; extern outputBufType g_outputBuf; enum @@ -87,6 +90,7 @@ struct StackEntry extern StackEntry g_stack[MAX_STACK]; extern int g_stackPos; +// Operand descriptor stuff. #define MAX_OPDESC 128 extern int g_opdescTable[MAX_OPDESC]; extern int g_opdeskMasks[MAX_OPDESC]; // used to keep track of used bits @@ -106,10 +110,45 @@ struct Uniform int type; }; +// List of uniforms #define MAX_UNIFORM 0x60 extern Uniform g_uniformTable[MAX_UNIFORM]; extern int g_uniformCount; +struct DVLEData; // Forward declaration + +typedef std::pair procedure; // position, size +typedef std::pair relocation; // position, name + +typedef std::map procTableType; +typedef std::map labelTableType; +typedef std::map aliasTableType; +typedef std::vector relocTableType; +typedef std::list dvleTableType; + +typedef procTableType::iterator procTableIter; +typedef labelTableType::iterator labelTableIter; +typedef aliasTableType::iterator aliasTableIter; +typedef relocTableType::iterator relocTableIter; +typedef dvleTableType::iterator dvleTableIter; + +extern procTableType g_procTable; +extern dvleTableType g_dvleTable; +extern relocTableType g_procRelocTable; +extern int g_totalDvleCount; + +// The following are cleared before each file is processed +extern labelTableType g_labels; +extern relocTableType g_labelRelocTable; +extern aliasTableType g_aliases; + +int AssembleString(char* str, const char* initialFilename); +int RelocateProduct(void); + +//----------------------------------------------------------------------------- +// Local data +//----------------------------------------------------------------------------- + enum { OUTTYPE_POS = 0, @@ -123,10 +162,6 @@ enum OUTTYPE_VIEW, }; -#define MAX_OUTPUT 8 -extern u64 g_outputTable[MAX_OUTPUT]; -extern int g_outputCount; - struct Constant { int regId; @@ -138,33 +173,32 @@ struct Constant }; }; -#define MAX_CONSTANT 0x60 -extern Constant g_constantTable[MAX_CONSTANT]; -extern int g_constantCount; -extern size_t g_constantSize; - -struct Relocation +struct DVLEData { - size_t instPos; - const char* target; - bool isProc; + // General config + std::string filename; + std::string entrypoint; + size_t entryStart, entryEnd; + bool nodvle, isGeoShader; + + // Uniforms + Uniform uniformTable[MAX_UNIFORM]; + int uniformCount; + size_t symbolSize; + + // Constants + #define MAX_CONSTANT 0x60 + Constant constantTable[MAX_CONSTANT]; + int constantCount; + size_t constantSize; + + // Outputs + #define MAX_OUTPUT 8 + u64 outputTable[MAX_OUTPUT]; + int outputCount; + + DVLEData(const char* filename) : + filename(filename), entrypoint("main"), + nodvle(false), isGeoShader(false), + uniformCount(0), symbolSize(0), constantCount(0), constantSize(0), outputCount(0) { } }; - -typedef std::pair procedure; // position, size - -typedef std::map procTableType; -typedef std::map labelTableType; -typedef std::map aliasTableType; -typedef std::vector relocTableType; - -typedef procTableType::iterator procTableIter; -typedef labelTableType::iterator labelTableIter; -typedef aliasTableType::iterator aliasTableIter; -typedef relocTableType::iterator relocTableIter; - -extern procTableType g_procTable; -extern labelTableType g_labels; -extern aliasTableType g_aliases; -extern relocTableType g_relocs; - -int AssembleString(char* str, const char* initialFilename); diff --git a/source/picasso_assembler.cpp b/source/picasso_assembler.cpp index a983d6a..9854e93 100644 --- a/source/picasso_assembler.cpp +++ b/source/picasso_assembler.cpp @@ -19,21 +19,63 @@ int g_opdescMasks[MAX_OPDESC]; Uniform g_uniformTable[MAX_UNIFORM]; int g_uniformCount; -static int fvecUnifPos = 0x20; -static int ivecUnifPos = 0x80; -static int boolUnifPos = 0x88; -Constant g_constantTable[MAX_CONSTANT]; -int g_constantCount; -size_t g_constantSize; +class UniformAlloc +{ + int start, end, bound, tend; +public: + UniformAlloc(int start, int end) : start(start), end(end), bound(end), tend(end) { } + void ClearLocal(void) { end = tend; } + int AllocGlobal(int size) + { + if ((start+size) > bound) return -1; + int ret = start; + start += size; + return ret; + } + int AllocLocal(int size) + { + int pos = end - size; + if (pos < start) return -1; + bound = pos < bound ? pos : bound; + return pos; + } +}; -u64 g_outputTable[MAX_OUTPUT]; -int g_outputCount; +static UniformAlloc fvecAlloc(0x20, 0x80), ivecAlloc(0x80, 0x84), boolAlloc(0x88, 0x98); procTableType g_procTable; +dvleTableType g_dvleTable; +relocTableType g_procRelocTable; +int g_totalDvleCount; + labelTableType g_labels; +relocTableType g_labelRelocTable; aliasTableType g_aliases; -relocTableType g_relocs; + +static DVLEData* curDvle; + +static void ClearStatus(void) +{ + fvecAlloc.ClearLocal(); + ivecAlloc.ClearLocal(); + boolAlloc.ClearLocal(); + g_labels.clear(); + g_labelRelocTable.clear(); + g_aliases.clear(); + curDvle = NULL; +} + +static DVLEData* GetDvleData(void) +{ + if (!curDvle) + { + g_dvleTable.push_back( DVLEData(curFile) ); + curDvle = &g_dvleTable.back(); + g_totalDvleCount ++; + } + return curDvle; +} static char* mystrtok_pos; static char* mystrtok(char* str, const char* delim) @@ -126,13 +168,15 @@ static int parseInt(char* pos, int& out, long long min, long long max) } while(0) static int ProcessCommand(const char* cmd); -static int FixupRelocations(); +static int FixupLabelRelocations(); int AssembleString(char* str, const char* initialFilename) { curFile = initialFilename; curLine = 1; + ClearStatus(); + int nextLineIncr = 0; char* nextStr = NULL; for (; str; str = nextStr, curLine += nextLineIncr) @@ -192,35 +236,55 @@ int AssembleString(char* str, const char* initialFilename) if (g_stackPos) return throwError("unclosed block(s)\n"); - safe_call(FixupRelocations()); + safe_call(FixupLabelRelocations()); return 0; } -int FixupRelocations() +int FixupLabelRelocations() { - for (relocTableIter it = g_relocs.begin(); it != g_relocs.end(); ++it) + for (relocTableIter it = g_labelRelocTable.begin(); it != g_labelRelocTable.end(); ++it) { - Relocation& r = *it; - u32& inst = BUF[r.instPos]; - if (r.isProc) - { - procTableIter proc = g_procTable.find(r.target); - if (proc == g_procTable.end()) - return throwError("procedure '%s' is undefined\n", r.target); - u32 dst = proc->second.first; - u32 num = proc->second.second; - inst &= ~0x3FFFFF; - inst |= num | (dst << 10); - } else - { - labelTableIter lbl = g_labels.find(r.target); - if (lbl == g_labels.end()) - return throwError("label '%s' is undefined\n", r.target); - u32 dst = lbl->second; - inst &= ~(0xFFF << 10); - inst |= dst << 10; - } + relocation& r = *it; + u32& inst = BUF[r.first]; + labelTableIter lbl = g_labels.find(r.second); + if (lbl == g_labels.end()) + return throwError("label '%s' is undefined\n", r.second.c_str()); + u32 dst = lbl->second; + inst &= ~(0xFFF << 10); + inst |= dst << 10; + } + return 0; +} + +int RelocateProduct() +{ + for (relocTableIter it = g_procRelocTable.begin(); it != g_procRelocTable.end(); ++it) + { + relocation& r = *it; + u32& inst = BUF[r.first]; + procTableIter proc = g_procTable.find(r.second); + if (proc == g_procTable.end()) + return throwError("procedure '%s' is undefined\n", r.second.c_str()); + u32 dst = proc->second.first; + u32 num = proc->second.second; + inst &= ~0x3FFFFF; + inst |= num | (dst << 10); + } + + if (g_totalDvleCount == 0) + return throwError("no DVLEs can be generated from the given input file(s)\n"); + + for (dvleTableIter it = g_dvleTable.begin(); it != g_dvleTable.end(); ++it) + { + if (it->nodvle) continue; + curFile = it->filename.c_str(); + curLine = 1; + procTableIter mainIt = g_procTable.find(it->entrypoint); + if (mainIt == g_procTable.end()) + return throwError("entrypoint '%s' is undefined\n", it->entrypoint.c_str()); + it->entryStart = mainIt->second.first; + it->entryEnd = it->entryStart + mainIt->second.second; } return 0; } @@ -422,12 +486,16 @@ static int parseSwizzling(const char* b) return out<<1; } -static int maskFromSwizzling(int sw) +static int maskFromSwizzling(int sw, bool reverse = true) { sw >>= 1; // get rid of negation bit int out = 0; for (int i = 0; i < 4; i ++) - out |= BIT(3-((sw>>(i*2))&3)); + { + int bitid = (sw>>(i*2))&3; + if (reverse) bitid = 3 - bitid; + out |= BIT(bitid); + } return out; } @@ -841,10 +909,10 @@ DEF_COMMAND(formatsetemit) safe_call(parseSetEmitFlags(flagStr, isPrim, isInv)); #ifdef DEBUG - printf("%s:%02X vtx%d, %s, %s\n", cmdName, opcode, vtxId, isPrim?"true":"false", isInv=?"true":"false"); + printf("%s:%02X vtx%d, %s, %s\n", cmdName, opcode, vtxId, isPrim?"true":"false", isInv?"true":"false"); #endif BUF.push_back(FMT_OPCODE(opcode) | ((u32)isInv<<22) | ((u32)isPrim<<23) | (vtxId<<24)); - g_isGeoShader = true; + GetDvleData()->isGeoShader = true; return 0; } @@ -856,11 +924,7 @@ DEF_COMMAND(formatcall) ARG_TARGET(procName); - Relocation r; - r.instPos = BUF.size(); - r.target = procName; - r.isProc = true; - g_relocs.push_back(r); + g_procRelocTable.push_back( std::make_pair(BUF.size(), procName) ); BUF.push_back(FMT_OPCODE(opcode)); @@ -919,11 +983,8 @@ DEF_COMMAND(format2) ARG_TARGET(targetName); - Relocation r; - r.instPos = BUF.size(); - r.target = targetName; - r.isProc = opcode==MAESTRO_CALLC; - g_relocs.push_back(r); + relocTableType& rt = opcode==MAESTRO_CALLC ? g_procRelocTable : g_labelRelocTable; + rt.push_back( std::make_pair(BUF.size(), targetName) ); #ifdef DEBUG printf("%s:%02X %s, %s\n", cmdName, opcode, condExp, targetName); @@ -971,11 +1032,8 @@ DEF_COMMAND(format3) ARG_TARGET(targetName); - Relocation r; - r.instPos = BUF.size(); - r.target = targetName; - r.isProc = opcode==MAESTRO_CALLU; - g_relocs.push_back(r); + relocTableType& rt = opcode==MAESTRO_CALLU ? g_procRelocTable : g_labelRelocTable; + rt.push_back( std::make_pair(BUF.size(), targetName) ); #ifdef DEBUG printf("%s:%02X d%02X, %s\n", cmdName, opcode, regId, targetName); @@ -1185,21 +1243,20 @@ DEF_DIRECTIVE(alias) return 0; } -static inline int& getAllocVar(int type, int& bound) +static inline UniformAlloc& getAlloc(int type) { switch (type) { default: - case UTYPE_FVEC: bound = 0x80; return fvecUnifPos; - case UTYPE_IVEC: bound = 0x84; return ivecUnifPos; - case UTYPE_BOOL: bound = 0x98; return boolUnifPos; + case UTYPE_FVEC: return fvecAlloc; + case UTYPE_IVEC: return ivecAlloc; + case UTYPE_BOOL: return boolAlloc; } } DEF_DIRECTIVE(uniform) { - int bound; - int& uniformPos = getAllocVar(dirParam, bound); + UniformAlloc& alloc = getAlloc(dirParam); for (;;) { @@ -1222,19 +1279,55 @@ DEF_DIRECTIVE(uniform) } if (!validateIdentifier(argText)) return throwError("invalid uniform name: %s\n", argText); - if ((uniformPos+uSize) >= bound) - return throwError("not enough uniform registers: %s[%d]\n", argText, uSize); - if (g_uniformCount == MAX_UNIFORM) - return throwError("too many uniforms: %s[%d]\n", argText, uSize); if (g_aliases.find(argText) != g_aliases.end()) return duplicateIdentifier(argText); + int uniformPos = -1; + + // Find the uniform in the table + int i; + for (i = 0; i < g_uniformCount; i ++) + { + Uniform& uniform = g_uniformTable[i]; + if (uniform.name == argText) + { + if (uniform.type != dirParam) + return throwError("mismatched uniform type: %s\n", argText); + if (uniform.size != uSize) + return throwError("uniform '%s' previously declared as having size %d\n", argText, uniform.size); + break; + } + } + + // If not found, create it + if (i == g_uniformCount && uniformPos < 0) + { + if (g_uniformCount == MAX_UNIFORM) + return throwError("too many global uniforms: %s\n", argText); + + uniformPos = alloc.AllocGlobal(uSize); + if (uniformPos < 0) + return throwError("not enough uniform space: %s[%d]\n", argText, uSize); + } + Uniform& uniform = g_uniformTable[g_uniformCount++]; uniform.name = argText; uniform.pos = uniformPos; uniform.size = uSize; uniform.type = dirParam; uniformPos += uSize; + + if (*argText != '_') + { + DVLEData* dvle = GetDvleData(); + + // Add the uniform to the table + if (dvle->uniformCount == MAX_UNIFORM) + return throwError("too many referenced uniforms: %s\n", argText); + dvle->uniformTable[dvle->uniformCount++] = uniform; // Copy constructor + dvle->symbolSize += strlen(argText)+1; + } + g_aliases.insert( std::pair(argText, uniform.pos | (DEFAULT_OPSRC<<8)) ); #ifdef DEBUG @@ -1246,8 +1339,8 @@ DEF_DIRECTIVE(uniform) DEF_DIRECTIVE(const) { - int bound; - int& uniformPos = getAllocVar(dirParam, bound); + DVLEData* dvle = GetDvleData(); + UniformAlloc& alloc = getAlloc(dirParam); NEXT_ARG_CPAREN(constName); NEXT_ARG(arg0Text); @@ -1260,14 +1353,18 @@ DEF_DIRECTIVE(const) *parenPos = 0; arg3Text = trim_whitespace(arg3Text); - if (g_constantCount == MAX_CONSTANT || uniformPos>=bound) - return throwError("not enough space for constant\n"); - if (g_aliases.find(constName) != g_aliases.end()) return duplicateIdentifier(constName); - Constant& ct = g_constantTable[g_constantCount++]; - ct.regId = uniformPos++; + int uniformPos = alloc.AllocLocal(1); + if (uniformPos < 0) + return throwError("not enough space for local constant '%s'\n", constName); + + if (dvle->constantCount == MAX_CONSTANT) + return throwError("too many local constants\n"); + + Constant& ct = dvle->constantTable[dvle->constantCount++]; + ct.regId = uniformPos; ct.type = dirParam; if (dirParam == UTYPE_FVEC) { @@ -1275,14 +1372,14 @@ DEF_DIRECTIVE(const) ct.fparam[1] = atof(arg1Text); ct.fparam[2] = atof(arg2Text); ct.fparam[3] = atof(arg3Text); - g_constantSize += 4 + 4*4; + dvle->constantSize += 4 + 4*4; } else if (dirParam == UTYPE_IVEC) { ct.iparam[0] = atoi(arg0Text) & 0xFF; ct.iparam[1] = atoi(arg1Text) & 0xFF; ct.iparam[2] = atoi(arg2Text) & 0xFF; ct.iparam[3] = atoi(arg3Text) & 0xFF; - g_constantSize += 4 + 4; + dvle->constantSize += 4 + 4; } g_aliases.insert( std::pair(constName, ct.regId | (DEFAULT_OPSRC<<8)) ); @@ -1321,6 +1418,8 @@ static int parseOutType(const char* text) DEF_DIRECTIVE(out) { + DVLEData* dvle = GetDvleData(); + NEXT_ARG_SPC(outName); NEXT_ARG_SPC(outType); ENSURE_NO_MORE_ARGS(); @@ -1337,28 +1436,54 @@ DEF_DIRECTIVE(out) if (sw < 0) return throwError("invalid output mask: %s\n", dotPos); } - int mask = maskFromSwizzling(sw); + int mask = maskFromSwizzling(sw, false); int type = parseOutType(outType); if (type < 0) return throwError("invalid output type: %s\n", outType); - if (g_outputCount==MAX_OUTPUT) + if (dvle->outputCount==MAX_OUTPUT) return throwError("too many outputs\n"); if (g_aliases.find(outName) != g_aliases.end()) return duplicateIdentifier(outName); - int oid = g_outputCount; + int oid = dvle->outputCount; #ifdef DEBUG printf("output %s <- o%d (%d:%X)\n", outName, oid, type, mask); #endif - g_outputTable[g_outputCount++] = OUTPUT_MAKE(type, oid, mask); + dvle->outputTable[dvle->outputCount++] = OUTPUT_MAKE(type, oid, mask); g_aliases.insert( std::pair(outName, oid | (sw<<8)) ); return 0; } +DEF_DIRECTIVE(entry) +{ + DVLEData* dvle = GetDvleData(); + + NEXT_ARG_SPC(entrypoint); + ENSURE_NO_MORE_ARGS(); + + if (!validateIdentifier(entrypoint)) + return throwError("invalid identifier: %s\n", entrypoint); + + dvle->entrypoint = entrypoint; + return 0; +} + +DEF_DIRECTIVE(nodvle) +{ + DVLEData* dvle = GetDvleData(); + ENSURE_NO_MORE_ARGS(); + + if (!dvle->nodvle) + { + dvle->nodvle = true; + g_totalDvleCount --; + } +} + static const cmdTableType dirTable[] = { DEC_DIRECTIVE(proc), @@ -1371,6 +1496,8 @@ static const cmdTableType dirTable[] = DEC_DIRECTIVE2(constf, const, UTYPE_FVEC), DEC_DIRECTIVE2(consti, const, UTYPE_IVEC), DEC_DIRECTIVE(out), + DEC_DIRECTIVE(entry), + DEC_DIRECTIVE(nodvle), { NULL, NULL }, }; diff --git a/source/picasso_frontend.cpp b/source/picasso_frontend.cpp index e05bc75..76f4a9f 100644 --- a/source/picasso_frontend.cpp +++ b/source/picasso_frontend.cpp @@ -33,44 +33,49 @@ int usage(const char* prog) { fprintf(stderr, "Usage:\n\n" - "%s shbinFile vshFile [hFile]\n", prog); + "%s output.shbin input1.pica input2.pica ...\n", prog); return 0; } int main(int argc, char* argv[]) { - if (argc < 3 || argc > 4) + if (argc < 3) return usage(argv[0]); char* shbinFile = argv[1]; - char* vshFile = argv[2]; - char* hFile = argc > 3 ? argv[3] : NULL; + //char* hFile = argc > 3 ? argv[3] : NULL; #ifdef WIN32 FixMinGWPath(shbinFile); - FixMinGWPath(vshFile); - FixMinGWPath(hFile); + //FixMinGWPath(hFile); #endif - char* sourceCode = StringFromFile(vshFile); - if (!sourceCode) + int rc = 0; + for (int i = 2; i < argc; i ++) { - fprintf(stderr, "Cannot open input file!\n"); - return 1; + 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; } - int rc = AssembleString(sourceCode, vshFile); - free(sourceCode); + rc = RelocateProduct(); 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()) @@ -79,54 +84,39 @@ int main(int argc, char* argv[]) 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(1); // 1 DVLE - f.WriteWord(3*4 + 0x28); // offset to DVLE + f.WriteWord(g_totalDvleCount); // Number of DVLEs - u32 dvlpStart = f.Tell(); - u32 shaderSize = g_outputBuf.size(); - u32 paramStart = 0x28 + 0x40; + // 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(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(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 - paramStart += g_opdescCount*8; - f.WriteWord(paramStart); // offset to symtable (TODO) + f.WriteWord(dvlpSize); // 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(g_isGeoShader ? 1 : 0); // Shader type - 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); @@ -134,53 +124,77 @@ int main(int argc, char* argv[]) for (int i = 0; i < g_opdescCount; i ++) f.WriteDword(g_opdescTable[i]); - // Write constants - for (int i = 0; i < g_constantCount; i ++) + // Write DVLEs + for (dvleTableIter dvle = g_dvleTable.begin(); dvle != g_dvleTable.end(); ++dvle) { - Constant& ct = g_constantTable[i]; - f.WriteHword(ct.type); - if (ct.type == UTYPE_FVEC) + 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 ++) { - f.WriteHword(ct.regId-0x20); - for (int j = 0; j < 4; j ++) - f.WriteWord(f32tof24(ct.fparam[j])); - } else if (ct.type == UTYPE_IVEC) + 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 ++) { - f.WriteHword(ct.regId-0x80); - for (int j = 0; j < 4; j ++) - f.WriteByte(ct.iparam[j]); + 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); } } - // 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 = u.name.length()+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 ++) - { - std::string& u = g_uniformTable[i].name; - size_t l = u.length()+1; - f.WriteRaw(u.c_str(), l); - } - +#if 0 if (hFile) { FILE* f2 = fopen(hFile, "w"); @@ -213,6 +227,7 @@ int main(int argc, char* argv[]) fclose(f2); } +#endif return 0; }