} prog_section;
typedef struct {
- uint32_t version; /* Program version (6) */
- uint32_t crc16; /* What is this? */
+ uint16_t version; /* Program version (6) */
+ uint16_t flags; /* see propsal.txt */
+ uint16_t crc16; /* What is this? */
+ uint16_t skip; /* see propsal.txt */
+
prog_section statements; /* prog_section_statement */
prog_section defs; /* prog_section_def */
prog_section fields; /* prog_section_field */
}
void code_init() {
+ /* omit creation of null code */
+ if (opts_omit_nullcode)
+ return;
+
/*
* The way progs.dat is suppose to work is odd, there needs to be
* some null (empty) statements, functions, and 28 globals
void code_write() {
prog_header code_header={0};
+
+ /* see proposal.txt */
+ if (opts_omit_nullcode) {
+ code_header.skip = 28;
+ code_header.flags = 1;
+ }
+
code_header.version = 6;
code_header.crc16 = 0; /* TODO: */
code_header.statements = (prog_section){sizeof(prog_header), code_statements_elements };
if (opts_darkplaces_stringtablebug) {
util_debug("GEN", "Patching stringtable for -fdarkplaces-stringtablebug\n");
- /* >= + padd */
+ /* >= + P */
code_chars_add('\0'); /* > */
code_chars_add('\0'); /* = */
code_chars_add('\0'); /* P */
extern int opts_debug;
extern int opts_memchk;
extern int opts_darkplaces_stringtablebug;
+extern int opts_omit_nullcode;
#endif
int opts_memchk = 0;
int opts_compiler = COMPILER_GMQCC;
int opts_darkplaces_stringtablebug = 0;
+int opts_omit_nullcode = 0;
static const int usage(const char *const app) {
printf("usage:\n");
printf(" -std=ftqecc -- fteqcc QuakeC\n");
printf(" -std=qccx -- qccx QuakeC\n");
printf(" -std=gmqcc -- this compiler QuakeC (default selection)\n");
- printf(" code flags -f*\n");
- printf(" -fdarkplaces-stringtablebug -- patches the string table to work with bugged versions of darkplaces\n");
+ printf(" codegen flags:\n");
+ printf(" -fdarkplaces-string-table-bug -- patches the string table to work with bugged versions of darkplaces\n");
+ printf(" -fomit-nullcode -- omits the generation of null code (will break everywhere see propsal.txt)\n");
return -1;
}
}
/* code specific switches */
- if (!strncmp(&argv[1][1], "fdarkplaces-stringtablebug", 26)) {
+ if (!strcmp(&argv[1][1], "fdarkplaces-string-table-bug")) {
opts_darkplaces_stringtablebug = 1;
break;
}
+ if (!strcmp(&argv[1][1], "fomit-nullcode")) {
+ opts_omit_nullcode = 1;
+ break;
+ }
return usage(app);
}
--- /dev/null
+This is a propsal to extend the progs.dat file format without breaking
+backwards compatability. Currently the progs file format header has a
+description simaler to this:
+
+struct {
+ uint32_t version;
+ uint32_t crc16;
+ ....
+ uint32_t entfield;
+}
+
+The obvious notable issue here is version and crc16 are larger than they
+essentially need to be, if we made version and crc16 both uint16_t we can
+give ourselfs 32 bytes (2x16) to store additional data that can be used
+to make smaller progs.dat files.
+
+I propose a new structual layout like this:
+struct {
+ uint16_t version;
+ uint16_t flags; /* contains a skip field */
+ uint16_t crc16;
+ uint16_t skip; /* skiped globals */
+ ....
+ uint32_t entfield;
+}
+
+about 45% of globals are zero, if we could order them at the top of the
+globals array we can essentially use the skip field to specify how much
+zero globals the engine would have to populate (instead of being stored
+in the actual file itself) flags can specify if the progs.dat file skiped
+globals on the write of the progs.dat file.
+
+Of course only one bit in the flags would have to be set to specify if the
+file contains a skip field. Which lends itself to the fact that flags could
+later be extended for other things.