aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/util/pluto/FILEFORMAT
blob: e7716675c7c2cc008a5a82f46c97cc17b0298195 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
$Id$

pluto_persist() produces a "hunk" of objects. Here's the file format adhered
to by the function, and expected by pluto_unpersist(). 

As a developer, I feel that where file format information is given it is of
utmost importance that that information precisely and accurately reflects the
actual operation of the application. Therefore, if you find any discrepancy
between this and actual operation, please lambast me thoroughly over email.

Pseudo-C is used to express the file format. Padding is assumed to be
nonexistent. The keyword "one_of" is used to express a concept similar to
"union", except that its size is the size of the actual datatype chosen. Thus,
objects which contain, directly or indirectly, a one_of, may vary  in size.


struct Object {
	int firstTime;		/* Whether this is the first time the object
				is being referenced */
	one_of {
		RealObject o;	/* if firstTime == 1 */
		Reference r;	/* if firstTime == 0 */
	};
};

struct Reference {
	int ref;	/* The index the object was registered with */
};

struct RealObject {
	int type;		/* The type of the object */
	one_of {
		Boolean b;	/* If type == LUA_TBOOLEAN */
		LightUserData l;	/* If type == LUA_TLIGHTUSERDATA */
		Number n;	/* If type == LUA_TNUMBER */
		String s;	/* If type == LUA_TSTRING */
		Table t;	/* If type == LUA_TTABLE */
		Function f;	/* If type == LUA_TFUNCTION */
		Userdata u;	/* If type == LUA_TUSERDATA */
		Thread th;	/* If type == LUA_TTHREAD */
		Proto p;	/* If type == LUA_TPROTO (from lobject.h) */
		Upval uv;	/* If type == LUA_TUPVAL (from lobject.h) */
	};			/* The actual object */
};

struct Boolean {
	int32 bvalue;		/* 0 for false, 1 for true */
};

struct LightUserData {
	void* luvalue;		/* The actual, literal pointer */
};

struct Number {
	lua_Number nvalue;	/* The actual number */
};

struct String {
	int length;		/* The length of the string */
	char str[length];	/* The actual string (not null terminated) */
};

struct Table {
	int isspecial;		/* 1 if SP is used; 0 otherwise */
	one_of {
		Closure c;	/* if isspecial == 1; closure to refill the table */
		LiteralTable t;	/* if isspecial == 0; literal table info */
	};
};

struct LiteralTable {
	Object metatable;	/* nil for default metatable */
	Pair p[];		/* key/value pairs */
	Object nil = nil;	/* Nil reference to terminate */
};

struct Pair {
	Object key;
	Object value;
};

struct Function { 		/* Actually a closure */
	lu_byte nups;		/* Number of upvalues the function uses */
	Object proto;		/* The proto this function uses */
	Object upvals[nups];	/* All upvalues */
	Object fenv;		/* The FEnv (nil for the global table)
};

struct Upval {
	Object obj;		/* The object this upval refers to */
}

struct Userdata {
	int isSpecial; 		/* 1 for special persistence, 0 for literal
	one_of {
		LiteralUserdata lu;	/* if is_special is 0 */
		SpecialUserdata su;	/* if is_special is 1 */
	};
};

struct LiteralUserdata {
	Object metatable;		/* The metatable (nil for default) */
	int length;		/* Size of the data */
	char data[length];	/* The actual data */
};

struct SpecialUserdata {
	int length;		/* The size of the data */
	Object func;		/* The closure used to fill the userdata */
};

struct Thread {
	int stacksize;		/* The size of the stack filled with objects,
				 * including the "nil" that is hidden below
				 * the bottom of the stack visible to C */
	Object stack[stacksize];/* Indices of all stack values, bottom up */
	int callinfosize;	/* Number of elements in the CallInfo stack */
	CallInfo callinfostack[callinfosize];	/* The CallInfo stack */
	int base;		/* base = L->base - L->stack; */
	int top;		/* top = L->top - L->stack; */
	OpenUpval openupvals[]; /* Upvalues to open */
	Object nil = nil;	/* To terminate the open upvalues list */
};

struct OpenUpval {
	Object upval;		/* The upvalue */
	int stackpos;		/* The stack position to "reopen" it to */

};

struct CallInfo {
	int base;		/* base = ci->base - L->stack; */
	int top;		/* top = ci->top - L->stack; */
	int pc;			/* pc = ci->pc - proto->code; */
	int state;		/* flags used by the CallInfo */
};

struct Proto {
	int sizek;		/* Number of constants referenced */
	Object k[sizek];	/* Constants referenced */
	int sizep;		/* Number of inner Protos referenced */
	Object p[sizep];	/* Inner Protos referenced */
	int sizecode;		/* Number of instructions in code */
	Instruction code[sizecode];	/* The proto's code */
	ProtoDebug debuginfo;	/* Debug information for the proto */
	lu_byte nups;		/* Number of upvalues used */
	lu_byte numparams;	/* Number of parameters taken */
	lu_byte is_vararg;	/* 1 if function accepts varargs, 0 otherwise */
	lu_byte maxstacksize;	/* Size of stack reserved for the function */
};

struct ProtoDebug {
	int sizeupvals;		/* Number of upvalue names */
	Object upvals;		/* Upvalue names */
	int sizelocvars;	/* Number of local variable names */
	LocVar[sizelocvars];	/* Local variable names */
	Object source;		/* The source code */
	int sizelineinfo;	/* Number of opcode-line mappings */
	int lineinfo[sizelineinfo];	/* opcode-line mappings */
	int linedefined;	/* Start of line range */
	int lastlinedefined;	/* End of line range */
};

struct LocVar {
	Object name;		/* Name of the local variable */
	int startpc;		/* Point where variable is active */
	int endpc;		/* Point where variable is dead */
};