Automated update from: http://smariot.no-ip.org/translate
[QuestHelper.git] / Development / build2 / compile_core.cpp
blobe1d45dc2cd62fdbab1931a0846bbfe4eda6cbdbf
2 #include <iostream>
3 #include <cstdio>
4 #include <errno.h>
5 #include <stack>
6 #include <unistd.h>
8 #include <luabind/luabind.hpp>
9 #include <boost/noncopyable.hpp>
10 #include <boost/optional.hpp>
12 #include <sys/types.h>
13 #include <sys/wait.h>
15 #include <lzo/lzoconf.h>
16 #include <lzo/lzo1c.h>
17 #include <lzo/lzo1x.h>
19 #include <png.h>
21 using namespace std;
22 using boost::optional;
24 bool semiass_failure = false;
25 #define semi_assert(x) (__builtin_expect(!!(x), 1) ? (void)(1) : (printf("SEMIASSERT at %s:%d - %s\n", __FILE__, __LINE__, #x), semiass_failure = true, (void)(1)))
27 stack<int> ids;
29 int cur_file_id() {
30 if(ids.empty()) {
31 return -77;
32 } else {
33 return ids.top();
37 #define CHECK(x) (__builtin_expect(!!(x), 1) ? (void)(1) : (printf("CHECK at %s:%d / %d - %s\n", __FILE__, __LINE__, cur_file_id(), #x), throw("CHECK failed")))
39 void push_file_id(int loc_id) {
40 ids.push(loc_id);
44 void pop_file_id() {
45 CHECK(!ids.empty());
46 ids.pop();
49 template<typename T> void pushit(lua_State *L, const string &vid, optional<T> &v) {
50 if(v) {
51 lua_pushlstring(L, vid.data(), vid.size());
52 lua_pushnumber(L, *v);
53 lua_settable(L, -3);
57 struct Loc {
58 optional<int> priority;
60 optional<bool> relative;
62 optional<int> c;
63 optional<int> rc;
64 optional<int> rz;
65 optional<double> x;
66 optional<double> y;
68 void push(lua_State *L) {
69 if(c || x || y || rc || rz) {
70 lua_newtable(L);
72 pushit(L, "priority", priority);
73 if(relative && *relative) {
74 lua_pushstring(L, "relative");
75 lua_pushboolean(L, true);
76 lua_settable(L, -3);
78 pushit(L, "c", c);
79 pushit(L, "x", x);
80 pushit(L, "y", y);
81 pushit(L, "rc", rc);
82 pushit(L, "rz", rz);
83 } else {
84 lua_pushnil(L);
89 Loc getLoc(const char *pt, int loc_v) {
90 if(loc_v == 0 || loc_v == 1) {
91 signed char c = pt[0];
92 signed int x = *(int*)&(pt[1]); // go go gadget alignment error
93 signed int y = *(int*)&(pt[5]);
94 signed char rc = pt[9];
95 signed char rz = pt[10];
97 Loc rv;
98 rv.priority = 3;
99 rv.relative = false;
100 if(c != -128) rv.c = c;
101 if(x != -2147483648) rv.x = x / 1000.0;
102 if(y != -2147483648) rv.y = y / 1000.0;
103 if(rc != -128) rv.rc = rc;
104 if(rz != -128) rv.rz = rz;
106 return rv;
107 } else if(loc_v == 2) {
108 signed char delay = pt[0];
109 signed char rc = pt[1];
110 signed char rz = pt[2];
111 signed int x = *(int*)&(pt[3]); // go go gadget alignment error
112 signed int y = *(int*)&(pt[7]);
114 Loc rv;
115 if(delay)
116 rv.priority = 2;
117 else
118 rv.priority = 1;
119 rv.relative = true;
120 if(x != -2147483648) rv.x = x / (double)(1 << 24);
121 if(y != -2147483648) rv.y = y / (double)(1 << 24);
122 if(rc != -128) rv.rc = rc;
123 if(rz != -128) rv.rz = rz;
125 return rv;
126 } else {
127 CHECK(0);
131 void slice_loc(lua_State *L, const std::string &dat, int loc_v) {
132 CHECK(dat.size() == 11);
134 getLoc(dat.c_str(), loc_v).push(L);
137 // we don't bother with the end because it's null-terminated
138 void parsechunks(const char **st, map<char, vector<int> > *out) {
139 while(out->count(**st)) {
140 char cite = **st;
141 (*st)++;
142 const char *stm = *st;
143 while(true) {
144 if(!(**st == tolower(cite) || isdigit(**st))) {
145 // used to be a crash, now we just explode
146 printf("C abort in parsechunks\n");
147 out->clear();
148 return;
150 if(**st == tolower(cite)) break;
151 (*st)++;
153 (*out)[cite].push_back(atoi(stm));
154 (*st)++;
158 void tableize(lua_State *L, const vector<int> &vek) {
159 lua_newtable(L);
160 for(int i = 0; i < vek.size(); i++) {
161 lua_pushnumber(L, i + 1);
162 lua_pushnumber(L, vek[i]);
163 lua_settable(L, -3);
167 void split_quest_startend(lua_State *L, const std::string &dat, int loc_v) {
168 const char *st = dat.c_str();
169 const char *ed = st + dat.size();
171 lua_newtable(L);
173 int ct = 1;
174 while(st != ed) {
175 lua_pushnumber(L, ct++);
177 map<char, vector<int> > matrix;
178 vector<int> &monsty = matrix['M'];
180 parsechunks(&st, &matrix);
181 if(!matrix.size()) {
182 printf("C abort in SQSE\n");
183 lua_pop(L, 2);
184 return;
187 const char *stl = st;
188 st += 11;
189 if(st > ed) {
190 // This is flimsy.
191 lua_pop(L, 2);
192 break;
194 CHECK(st <= ed);
196 Loc luc = getLoc(stl, loc_v);
198 lua_newtable(L);
199 lua_pushstring(L, "monsters");
200 tableize(L, monsty);
201 lua_settable(L, -3);
202 lua_pushstring(L, "loc");
203 luc.push(L);
204 lua_settable(L, -3);
205 lua_settable(L, -3);
209 void split_quest_satisfied(lua_State *L, const std::string &dat, int loc_v) {
210 const char *st = dat.c_str();
211 const char *ed = st + dat.size();
213 lua_newtable(L);
215 int ct = 1;
216 while(st != ed) {
217 lua_pushnumber(L, ct++);
219 map<char, vector<int> > matrix;
220 const vector<int> &monsty = matrix['M'];
221 const vector<int> &item = matrix['I'];
222 const vector<int> &count = matrix['C'];
224 parsechunks(&st, &matrix);
225 if(!matrix.size()) {
226 printf("C abort in SQSAT\n");
227 lua_pop(L, 2);
228 return;
231 CHECK(count.size() <= 1);
233 if(*st != 'L') {
234 // this used to be a crash, now we just abort our faces off
235 printf("C abort in SQSAT2\n");
236 lua_pop(L, 2);
237 return;
239 st++;
241 const char *stl = st;
242 st += 11;
243 CHECK(st <= ed);
244 if(*st != 'l') {
245 // This is flimsy.
246 lua_pop(L, 2);
247 break;
249 CHECK(*st == 'l');
251 Loc luc = getLoc(stl, loc_v);
253 st++;
255 lua_newtable(L);
256 if(monsty.size()) {
257 lua_pushstring(L, "monster");
258 tableize(L, monsty);
259 lua_settable(L, -3);
261 if(item.size()) {
262 lua_pushstring(L, "item");
263 tableize(L, item);
264 lua_settable(L, -3);
266 if(count.size()) {
267 lua_pushstring(L, "count");
268 lua_pushnumber(L, count[0]);
269 lua_settable(L, -3);
271 lua_pushstring(L, "loc");
272 luc.push(L);
273 lua_settable(L, -3);
274 lua_settable(L, -3);
278 class Image : boost::noncopyable {
279 vector<unsigned int> data;
280 int wid;
281 int hei;
282 public:
283 Image(int width, int height) {
284 CHECK(width >= 0);
285 CHECK(height >= 0);
286 wid = width;
287 hei = height;
288 data.resize(width * height, 0);
291 void set(int x, int y, unsigned int pix) {
292 CHECK(x >= 0 && x < wid);
293 CHECK(y >= 0 && y < hei);
294 data[y * wid + x] = pix;
297 const unsigned int *getPtr(int x, int y) const { return &data[y * wid + x]; }
298 unsigned int *getPtr(int x, int y) { return &data[y * wid + x]; }
300 void copyfrom(const Image &image, int x, int y) {
301 CHECK(x >= 0);
302 CHECK(y >= 0);
303 CHECK(x + image.wid <= wid);
304 CHECK(y + image.hei <= hei);
306 unsigned int *itx = getPtr(x, y);
307 const unsigned int *src = image.getPtr(0, 0);
308 for(int i = 0; i < image.hei; i++) {
309 memcpy(itx, src, sizeof(unsigned int) * image.wid);
310 itx += wid;
311 src += image.wid;
315 void clear() {
316 fill(data.begin(), data.end(), 0);
319 void write(const string &fname) {
320 FILE *fp = fopen(fname.c_str(), "wb");
321 CHECK(fp);
323 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
324 CHECK(png_ptr);
326 png_infop info_ptr = png_create_info_struct(png_ptr);
327 CHECK(info_ptr);
329 if(setjmp(png_jmpbuf(png_ptr))) {
330 CHECK(0);
333 png_init_io(png_ptr, fp);
335 //png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
336 //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
338 png_set_IHDR(png_ptr, info_ptr, wid, hei, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
340 png_write_info(png_ptr, info_ptr);
341 png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
343 vector<png_bytep> dats;
344 for(int i = 0; i < hei; i++)
345 dats.push_back((png_bytep)&data[i * wid]);
347 png_write_rows(png_ptr, &dats[0], hei);
349 png_write_end(png_ptr, info_ptr);
350 png_destroy_write_struct(&png_ptr, &info_ptr);
352 fclose(fp);
356 class ImageTileWriter : boost::noncopyable {
357 Image temp;
358 int wid;
359 int hei;
360 int chunk;
362 int cury;
363 int curx;
365 FILE *fp;
366 png_structp png_ptr;
367 png_infop info_ptr;
369 public:
370 ImageTileWriter(const string &fname, int xblock, int yblock, int blocksize) : temp(xblock * blocksize, blocksize) {
371 cury = 0;
372 curx = -1;
374 wid = xblock;
375 hei = yblock;
376 chunk = blocksize;
378 fp = fopen(fname.c_str(), "wb");
379 CHECK(fp);
381 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
382 CHECK(png_ptr);
384 info_ptr = png_create_info_struct(png_ptr);
385 CHECK(info_ptr);
387 if(setjmp(png_jmpbuf(png_ptr))) {
388 CHECK(0);
391 png_init_io(png_ptr, fp);
393 //png_set_filter(png_ptr, 0, PNG_ALL_FILTERS);
394 //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
396 png_set_IHDR(png_ptr, info_ptr, wid * chunk, hei * chunk, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
398 png_write_info(png_ptr, info_ptr);
399 png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
402 void flush_row() {
403 CHECK(cury != hei);
405 vector<png_bytep> dats;
406 for(int i = 0; i < chunk; i++)
407 dats.push_back((png_bytep)temp.getPtr(0, i));
409 png_write_rows(png_ptr, &dats[0], chunk);
411 temp.clear();
413 cury++;
414 curx = -1;
417 void write_tile(int x, int y, const Image &tile) {
418 CHECK(y >= cury);
419 CHECK(y > cury || x > curx);
421 while(y > cury)
422 flush_row();
424 curx = x;
425 temp.copyfrom(tile, x * chunk, 0);
428 void finish() {
429 while(cury < hei)
430 flush_row();
432 png_write_end(png_ptr, info_ptr);
433 png_destroy_write_struct(&png_ptr, &info_ptr);
435 fclose(fp);
437 fp = NULL;
440 ~ImageTileWriter() {
441 semi_assert(!fp);
445 void check_semiass_failure() {
446 CHECK(!semiass_failure);
447 CHECK(ids.empty());
451 // yeah, uh, yeah, uh, yeah.
454 deque<string> runs;
455 void multirun_clear() {
456 runs.clear();
458 void multirun_add(const string &str) {
459 runs.push_back(str);
461 void multirun_spawn() {
462 if(!fork()) {
463 //CHECK(!execlp("bash", "-c", "echo", runs[0].c_str(), NULL)); // if it returns, something went wrong, but it always returns -1, so
464 CHECK(!system(runs[0].c_str())); // if it returns, something went wrong, but it always returns -1, so
465 exit(0);
466 } else {
467 runs.pop_front();
470 void multirun_wait() {
471 int stat;
472 waitpid(-1, &stat, 0);
474 CHECK(WIFEXITED(stat) && WEXITSTATUS(stat) == 0);
476 void multirun_complete(const string &phase, int simul) {
477 int totnum = runs.size();
479 while(waitpid(-1, NULL, WNOHANG) > 0) printf("wtt\n");
481 for(int i = 0; i < simul; i++)
482 multirun_spawn();
484 while(runs.size()) {
485 printf("Master %s %d/%d/%d waiting/running/finished\n", phase.c_str(), runs.size(), simul, totnum - runs.size() - simul);
486 multirun_wait();
487 multirun_spawn();
490 for(int i = 0; i < simul; i++) {
491 printf("Master %s %d/%d/%d waiting/running/finished\n", phase.c_str(), 0, simul - i, totnum - runs.size() - simul + i);
492 multirun_wait();
496 //void syncfile(lua_State *L) {
499 unsigned char wrk[LZO1C_MEM_COMPRESS];
500 unsigned char dat[1024768 * 16];
502 string lzo_decompress(const string &str) {
503 //printf("dinput %d\n", str.size());
504 lzo_uint outlen = sizeof(dat);
505 CHECK(lzo1x_decompress_safe((const unsigned char*)str.c_str(), str.size(), dat, &outlen, wrk) == LZO_E_OK);
506 CHECK(outlen >= 0 && outlen < sizeof(dat));
507 //printf("decompressed to %d\n", outlen);
508 //printf("%d, %s, %d\n", (int)outlen, str.c_str(), str.size());
509 return string(dat, dat + outlen);
511 string lzo_compress(const string &str) {
512 CHECK(str.size() <= sizeof(dat));
513 lzo_uint outlen = sizeof(dat);
514 //printf("cinput %d\n", str.size());
515 CHECK(lzo1x_1_compress((const unsigned char*)str.c_str(), str.size(), dat, &outlen, wrk) == LZO_E_OK);
516 CHECK(outlen >= 0 && outlen < sizeof(dat));
517 //printf("compressed to %d\n", outlen);
518 string oot = string(dat, dat + outlen);
520 string retest = lzo_decompress(oot);
522 if(str != retest) {
523 printf("failure %d/%d\n", str.size(), retest.size());
524 if(str.size() == retest.size()) {
525 for(int i = 0; i < str.size(); i++) {
526 if(str[i] != retest[i]) {
527 printf("%d: %d/%d\n", i, (unsigned char)str[i], (unsigned char)retest[i]);
531 CHECK(str == retest);
533 return oot;
539 extern "C" int init(lua_State* L) {
540 using namespace luabind;
542 open(L);
544 module(L)
546 def("push_file_id", &push_file_id),
547 def("pop_file_id", &pop_file_id),
548 def("cur_file_id", &cur_file_id),
549 def("slice_loc", &slice_loc, raw(_1)),
550 def("split_quest_startend", &split_quest_startend, raw(_1)),
551 def("split_quest_satisfied", &split_quest_satisfied, raw(_1)),
552 def("check_semiass_failure", &check_semiass_failure),
553 def("multirun_clear", &multirun_clear),
554 def("multirun_add", &multirun_add),
555 def("multirun_complete", &multirun_complete),
556 def("sleep", &sleep),
557 def("sync", &sync),
558 def("lzo_compress", &lzo_compress),
559 def("lzo_decompress", &lzo_decompress),
560 class_<Image>("Image")
561 .def(constructor<int, int>())
562 .def("write", &Image::write)
563 .def("set", &Image::set),
564 class_<ImageTileWriter>("ImageTileWriter")
565 .def(constructor<const string &, int, int, int>())
566 .def("write_tile", &ImageTileWriter::write_tile)
567 .def("finish", &ImageTileWriter::finish)
570 lzo_init();
572 return 0;