mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-18 14:21:36 +00:00
new progs format proposal for engine developers (45% of globals are 0, why write them, let the engine populate them. We can essentially save 9884 bytes in xonotic's progs.dat with this new format.)
This commit is contained in:
parent
cda5076356
commit
8049252f65
4 changed files with 62 additions and 6 deletions
20
code.c
20
code.c
|
@ -28,8 +28,11 @@ typedef struct {
|
|||
} 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 */
|
||||
|
@ -90,6 +93,10 @@ int code_strings_add(const char *src) {
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -137,6 +144,13 @@ void code_test() {
|
|||
|
||||
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 };
|
||||
|
@ -150,7 +164,7 @@ void code_write() {
|
|||
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 */
|
||||
|
|
1
gmqcc.h
1
gmqcc.h
|
@ -485,4 +485,5 @@ enum {
|
|||
extern int opts_debug;
|
||||
extern int opts_memchk;
|
||||
extern int opts_darkplaces_stringtablebug;
|
||||
extern int opts_omit_nullcode;
|
||||
#endif
|
||||
|
|
12
main.c
12
main.c
|
@ -30,6 +30,7 @@ int opts_debug = 0;
|
|||
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");
|
||||
|
@ -48,8 +49,9 @@ static const int usage(const char *const app) {
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -92,10 +94,14 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
}
|
||||
|
|
35
propsal.txt
Normal file
35
propsal.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
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.
|
Loading…
Reference in a new issue