1 #include "types.h"
2 #include "common.h"
3 #include "vm.h"
4 #include "gefile.h"
5 #include "bytecode.h"
6
7
8
9 void STDCALL gesave_addubyte( pvmEngine pThis, uint val )
10 {
11 buf_appendch( pThis, pThis->gesave, ( ubyte )val );
12 }
13
14 void STDCALL gesave_adduint( pvmEngine pThis, uint val )
15 {
16 buf_appenduint( pThis, pThis->gesave, val );
17 }
18
19 void STDCALL gesave_addushort( pvmEngine pThis, uint val )
20 {
21 buf_appendushort( pThis, pThis->gesave, ( ushort )val );
22 }
23
24
25 void STDCALL gesave_addptr( pvmEngine pThis, pubyte data )
26 {
27 buf_append( pThis, pThis->gesave, data, mem_len( pThis, data ) + 1 );
28 }
29
30 void STDCALL gesave_adddata( pvmEngine pThis, pubyte data, uint size )
31 {
32 buf_append( pThis, pThis->gesave, data, size );
33 }
34
35 //--------------------------------------------------------------------------
36
37 uint STDCALL gesave_bwd( pvmEngine pThis, uint val )
38 {
39 if ( val <= 187 )
40 gesave_addubyte( pThis, val );
41 else
42 if ( val < 16830 ) // 0xFF *( 253 - 188 ) + 0xFF
43 {
44 gesave_addubyte( pThis, 188 + val / 0xFF );
45 gesave_addubyte( pThis, val % 0xFF );
46 }
47 else
48 if ( val > MAX_USHORT )
49 {
50 gesave_addubyte( pThis, MAX_BYTE );
51 gesave_adduint( pThis, val );
52 }
53 else
54 {
55 gesave_addubyte( pThis, MAX_BYTE - 1 );
56 gesave_addushort( pThis, val );
57 }
58 return val;
59 }
60
61
62 void STDCALL gesave_head( pvmEngine pThis, uint type, pubyte name, uint flag )
63 {
64 pThis->gesaveoff = buf_len( pThis, pThis->gesave );
65
66 flag &= 0xFFFFFF;
67
68 if ( name && name[0] )
69 flag |= GHCOM_NAME;
70 else
71 flag &= ~GHCOM_NAME;
72
73 flag |= GHCOM_PACK;
74
75 gesave_addubyte( pThis, type );
76 gesave_adduint( pThis, flag );
77 // The size will be inserted in gesave_finish
78 // Now add just one byte
79 gesave_addubyte( pThis, 0 );
80
81 if ( flag & GHCOM_NAME )
82 gesave_addptr( pThis, name );
83 }
84
85 void STDCALL gesave_finish( pvmEngine pThis )
86 {
87 buf bt;
88 pbuf pb = pThis->gesave;
89 uint size = buf_len( pThis, pb ) - pThis->gesaveoff;
90
91 if ( size <= 187 )
92 *( pubyte )(( pubyte )buf_ptr( pThis, pThis->gesave ) + pThis->gesaveoff + 5 ) = ( ubyte )size;
93 else
94 {
95 buf_init( pThis, &bt );
96 pThis->gesave = &bt;
97 if ( size < 16800 )
98 {
99 size++;
100 gesave_bwd( pThis, size );
101 }
102 else
103 if ( size < 0xFFF0 )
104 {
105 gesave_addubyte( pThis, 0xFE );
106 size += 2;
107 gesave_addushort( pThis, size );
108 }
109 else
110 {
111 gesave_addubyte( pThis, 0xFF );
112 size += 4;
113 gesave_adduint( pThis, size );
114 }
115 // Write the size
116 // We have already had one byte, so -1
117 buf_insert( pThis, pb, pThis->gesaveoff + 5, ( pubyte )&size /*any*/, buf_len( pThis, pThis->gesave ) - 1 );
118 mem_copy( pThis, buf_ptr( pThis, pb ) + pThis->gesaveoff + 5, buf_ptr( pThis, pThis->gesave ), buf_len( pThis, pThis->gesave ));
119
120 buf_delete( pThis, &bt );
121 pThis->gesave = pb;
122 }
123 }
124
125 void STDCALL gesave_var( pvmEngine pThis, pvartype var )
126 {
127 uint i;
128 povmtype ptype;
129 pubyte ptr;
130
131 gesave_bwd( pThis, ((pvmobj)PCMD(var->type))->id );
132 gesave_addubyte( pThis, var->flag );
133
134 if ( var->flag & VAR_NAME )
135 gesave_addptr( pThis, var->name );
136 if ( var->flag & VAR_OFTYPE )
137 gesave_bwd( pThis, ((pvmobj)PCMD(var->oftype))->id);
138
139 if ( var->flag & VAR_DIM )
140 {
141 gesave_addubyte( pThis, var->dim );
142 for ( i = 0; i < var->dim; i++ )
143 gesave_bwd( pThis, var->ptr[i] );
144 }
145 if ( var->flag & VAR_DATA )
146 {
147 ptr = ( pubyte )( var->ptr + var->dim );
148 ptype = ( povmtype )PCMD( var->type );
149 if ( ptype->vmo.flag & GHTY_STACK )
150 i = ptype->size;
151 else
152 if ( var->type == TStr )
153 i = mem_len( pThis, ptr ) + 1;
154 else
155 {
156 i = *( puint )ptr;
157 ptr += sizeof( uint );
158 gesave_bwd( pThis, i ); // save data size as bwd
159 }
160 gesave_adddata( pThis, ptr, i );
161 }
162 }
163
164 void STDCALL gesave_varlist( pvmEngine pThis, pvartype pvar, uint count )
165 {
166 uint i;
167
168 gesave_bwd( pThis, count );
169 for ( i = 0; i < count; i++ )
170 gesave_var( pThis, pvar++ );
171 }
172
173 void STDCALL gesave_resource( pvmEngine pThis )
174 {
175 uint i, count;
176 pcollect pres;
177
178 pres = &pThis->_vm.resource;
179
180 gesave_head( pThis, OVM_RESOURCE, "", 0 );
181
182 count = collect_count( pThis, pres );
183 gesave_bwd( pThis, count );
184 for ( i = 0; i < count; i++ )
185 {
186 gesave_bwd( pThis, collect_gettype( pThis, pres, i ));
187 gesave_addptr( pThis, str_ptr( vmres_getstr( pThis, i )) );
188 }
189 gesave_finish(pThis);
190 }
191
192 void STDCALL gesave_bytecode( pvmEngine pThis, povmbcode bcode )
193 {
194 pvartype pvar;
195 uint i, count = 0, cmd, val;
196 puint end, ptr;
197
198 gesave_var( pThis, bcode->vmf.ret );
199 gesave_varlist( pThis, bcode->vmf.params, bcode->vmf.parcount );
200
201 gesave_bwd( pThis, bcode->setcount );
202 for ( i = 0; i < bcode->setcount; i++ )
203 {
204 gesave_bwd( pThis, bcode->sets[i].count );
205 count += bcode->sets[i].count;
206 }
207 pvar = bcode->vars;
208 for ( i = 0; i < count; i++ )
209 gesave_var( pThis, pvar++ );
210
211 ptr = ( puint )bcode->vmf.func;
212 if ( ptr )
213 {
214 end = ( puint )( ( pubyte )ptr + bcode->bcsize );
215 while ( ptr < end )
216 {
217 if(*ptr>KERNEL_COUNT)
218 *ptr = ((pvmobj)PCMD(*ptr))->id;
219 cmd = gesave_bwd( pThis, *ptr++ );
220 if ( cmd >= CNop && cmd < CNop + STACK_COUNT )
221 switch ( cmd )
222 {
223 case CPtrglobal:
224 case CResload:
225 case CCmdload:
226 cmd = gesave_bwd( pThis, ((pvmobj)PCMD(*ptr++))->id );
227 break;
228 case CQwload:
229 gesave_adduint( pThis, *ptr++ );
230 gesave_adduint( pThis, *ptr++ );
231 break;
232 case CDwload:
233 val = *ptr++;
234 if ( val <= 0xFF )
235 {
236 buf_ptr( pThis, pThis->gesave )[ buf_len( pThis, pThis->gesave ) - 1 ] = CByload;
237 gesave_addubyte( pThis, val );
238 }
239 else
240 if ( val <= 0xFFFF )
241 {
242 buf_ptr( pThis, pThis->gesave )[ buf_len( pThis, pThis->gesave ) - 1 ] = CShload;
243 gesave_addushort( pThis, val );
244 }
245 else
246 gesave_adduint( pThis, val );
247 break;
248 case CDwsload:
249 i = gesave_bwd( pThis, *ptr++ );
250 gesave_adddata( pThis, ( pubyte )ptr, i << 2 );
251 ptr += i;
252 break;
253 case CDatasize:
254 i = gesave_bwd( pThis, *ptr++ );
255 gesave_adddata( pThis, ( pubyte )ptr, i );
256 ptr += ( i >> 2 ) + ( i & 3 ? 1 : 0 );
257 break;
258 default:
259 switch ( shifts[ cmd - CNop ] )
260 {
261 case SH1_3:
262 case SH2_3:
263 cmd = gesave_bwd( pThis, *ptr++ );
264 case SHN1_2:
265 case SH0_2:
266 case SH1_2:
267 cmd = gesave_bwd( pThis, *ptr++ );
268 break;
269 }
270 }
271 }
272 }
273 }
274
275
276 void STDCALL gesave_exfunc( pvmEngine pThis, povmfunc exfunc )
277 {
278 gesave_var( pThis, exfunc->vmf.ret );
279 gesave_varlist( pThis, exfunc->vmf.params, exfunc->vmf.parcount );
280
281 if ( exfunc->vmf.vmo.flag & GHEX_IMPORT )
282 {
283 gesave_bwd( pThis, exfunc->import );
284 gesave_addptr( pThis, exfunc->original );
285 }
286 }
287
288 void STDCALL gesave_import( pvmEngine pThis, povmimport import )
289 {
290 gesave_addptr( pThis, import->filename );
291 if ( import->vmo.flag & GHIMP_LINK )
292 {
293 gesave_adduint( pThis, import->size );
294 gesave_adddata( pThis, import->data, import->size );
295 }
296 }
297
298 void STDCALL gesave_type( pvmEngine pThis, povmtype ptype )
299 {
300 uint i, k;
301 uint flag = ptype->vmo.flag;
302
303 if ( flag & GHTY_INHERIT )
304 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->inherit))->id );
305
306 if ( flag & GHTY_INDEX )
307 {
308 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->index.type))->id );
309 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->index.oftype))->id );
310 }
311 if ( flag & GHTY_INITDEL )
312 {
313 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->ftype[ FTYPE_INIT ]))->id );
314 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->ftype[ FTYPE_DELETE ]))->id );
315 }
316 if ( flag & GHTY_EXTFUNC )
317 {
318 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->ftype[ FTYPE_OFTYPE ]))->id );
319 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->ftype[ FTYPE_COLLECTION]))->id );
320 }
321 if ( flag & GHTY_ARRAY )
322 {
323 i = 0;
324 while ( ptype->ftype[ FTYPE_ARRAY + i ] )
325 i++;
326 gesave_bwd( pThis, i == 1 ? ((pvmobj)PCMD(ptype->ftype[ FTYPE_ARRAY ]))->id : i );
327 if ( i > 1 )
328 for ( k = 0; k < i; k++ )
329 gesave_bwd( pThis, ((pvmobj)PCMD(ptype->ftype[ FTYPE_ARRAY + k ]))->id );
330 }
331 gesave_varlist( pThis, ptype->children, ptype->count );
332 }
333
334 void STDCALL gesave_define( pvmEngine pThis, povmdefine pdefine )
335 {
336 gesave_varlist( pThis, pdefine->macros, pdefine->count );
337 }
338
339 uint STDCALL ge_save( pvmEngine pThis, char* fileName, char* isSave)
340 {
341 gehead head;
342 pgehead phead;
343 uint i, ii, count;
344 pvmobj pvmo;
345 buf out;
346 str filename;
347 if ( setjmp( pThis->stack_state) == -1 )
348 return 0;
349
350 str_init( pThis, &filename );
351 str_copyzero( pThis, &filename, fileName );
352 buf_init( pThis, &out );
353
354 pThis->gesave = &out;
355 buf_reserve( pThis, &out, 0x1ffff );
356
357 *( puint )&head.idname = GE_STRING;//0x00004547; // строка GE
358 head.flags = 0;
359 head.crc = 0;
360 head.headsize = sizeof( gehead );
361 head.size = 0;
362 head.vermajor = GEVER_MAJOR;
363 head.verminor = GEVER_MINOR;
364
365 buf_append( pThis, &out, ( pubyte )&head, sizeof( gehead ));
366 // Save resources at the first !
367 gesave_resource(pThis);
368
369 count = arr_count( pThis, &pThis->_vm.objtbl );
370 for ( i = KERNEL_COUNT; i < count ; i++ )
371 {
372 if(isSave && isSave[i] == 0)
373 {
374 /* gesave_addubyte( pThis, OVM_NONE );
375 gesave_adduint( pThis, GHCOM_PACK);
376 gesave_bwd( pThis, 6 );*/
377 pThis->popravka ++;
378 continue;
379 }
380
381 pvmo = ( pvmobj )PCMD( i );
382 pvmo->id -= pThis->popravka;
383 //@init @delete @array @oftype @index -не удалять имена
384 if(pThis->isDelName&&(pvmo->flag&GHCOM_NAME)&&pvmo->name&&lstrcmpA("@init",pvmo->name)&&
385 lstrcmpA("@delete",pvmo->name)&&lstrcmpA("@array",pvmo->name)&&
386 lstrcmpA("@oftype",pvmo->name)&&lstrcmpA("@index",pvmo->name))
387 {
388 pvmo->flag &= ~GHCOM_NAME;
389 }else
390 if(pvmo->name)
391 pvmo->flag |= ~GHCOM_NAME;
392
393 gesave_head( pThis, pvmo->type, pvmo->flag & GHCOM_NAME ?
394 pvmo->name : NULL, pvmo->flag );
395
396 switch ( pvmo->type )
397 {
398 case OVM_NONE:
399 break;
400 case OVM_BYTECODE:
401 gesave_bytecode( pThis, ( povmbcode )pvmo );
402 break;
403 case OVM_EXFUNC:
404 ((povmfunc)pvmo)->import = ((pvmobj)PCMD(((povmfunc)pvmo)->import))->id;
405 gesave_exfunc( pThis, ( povmfunc )pvmo );
406 break;
407 case OVM_TYPE:
408 {
409 for(ii = 0; ii<((povmtype)pvmo)->count; ii++)
410 {
411 if(pThis->isDelName)
412 ((povmtype)pvmo)->children[ii].flag &=~GHCOM_NAME;
413 else if(((povmtype)pvmo)->children[ii].name)
414 ((povmtype)pvmo)->children[ii].flag |=GHCOM_NAME;
415 }
416 gesave_type( pThis, ( povmtype )pvmo );
417 }break;
418 case OVM_GLOBAL:
419 gesave_var( pThis, (( povmglobal )pvmo)->type );
420 break;
421 case OVM_DEFINE:
422 gesave_define( pThis, ( povmdefine )pvmo );
423 break;
424 case OVM_IMPORT:
425 gesave_import( pThis, ( povmimport )pvmo );
426 break;
427 case OVM_ALIAS:
428 gesave_bwd( pThis, (( povmalias )pvmo)->idlink );
429 break;
430 }
431 gesave_finish(pThis);
432 }
433 // Specify the full size and crc
434 phead = ( pgehead )buf_ptr( pThis, &out );
435 phead->size = buf_len( pThis, &out );
436 phead->crc = crc( pThis, ( pubyte )phead + 12, phead->size - 12, 0xFFFFFFFF );
437 buf2file( pThis, &filename, &out );
438 buf_delete( pThis, &out );
439 str_delete( pThis, &filename );
440 return 1;
441 }