8 #include <luabind/luabind.hpp>
9 #include <boost/noncopyable.hpp>
10 #include <boost/optional.hpp>
12 #include <sys/types.h>
15 #include <lzo/lzoconf.h>
16 #include <lzo/lzo1c.h>
17 #include <lzo/lzo1x.h>
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)))
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
) {
49 template<typename T
> void pushit(lua_State
*L
, const string
&vid
, optional
<T
> &v
) {
51 lua_pushlstring(L
, vid
.data(), vid
.size());
52 lua_pushnumber(L
, *v
);
58 optional
<int> priority
;
60 optional
<bool> relative
;
68 void push(lua_State
*L
) {
69 if(c
|| x
|| y
|| rc
|| rz
) {
72 pushit(L
, "priority", priority
);
73 if(relative
&& *relative
) {
74 lua_pushstring(L
, "relative");
75 lua_pushboolean(L
, true);
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];
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
;
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]);
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
;
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
)) {
142 const char *stm
= *st
;
144 if(!(**st
== tolower(cite
) || isdigit(**st
))) {
145 // used to be a crash, now we just explode
146 printf("C abort in parsechunks\n");
150 if(**st
== tolower(cite
)) break;
153 (*out
)[cite
].push_back(atoi(stm
));
158 void tableize(lua_State
*L
, const vector
<int> &vek
) {
160 for(int i
= 0; i
< vek
.size(); i
++) {
161 lua_pushnumber(L
, i
+ 1);
162 lua_pushnumber(L
, vek
[i
]);
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();
175 lua_pushnumber(L
, ct
++);
177 map
<char, vector
<int> > matrix
;
178 vector
<int> &monsty
= matrix
['M'];
180 parsechunks(&st
, &matrix
);
182 printf("C abort in SQSE\n");
187 const char *stl
= st
;
196 Loc luc
= getLoc(stl
, loc_v
);
199 lua_pushstring(L
, "monsters");
202 lua_pushstring(L
, "loc");
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();
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
);
226 printf("C abort in SQSAT\n");
231 CHECK(count
.size() <= 1);
234 // this used to be a crash, now we just abort our faces off
235 printf("C abort in SQSAT2\n");
241 const char *stl
= st
;
251 Loc luc
= getLoc(stl
, loc_v
);
257 lua_pushstring(L
, "monster");
262 lua_pushstring(L
, "item");
267 lua_pushstring(L
, "count");
268 lua_pushnumber(L
, count
[0]);
271 lua_pushstring(L
, "loc");
278 class Image
: boost::noncopyable
{
279 vector
<unsigned int> data
;
283 Image(int width
, int 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
) {
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
);
316 fill(data
.begin(), data
.end(), 0);
319 void write(const string
&fname
) {
320 FILE *fp
= fopen(fname
.c_str(), "wb");
323 png_structp png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
326 png_infop info_ptr
= png_create_info_struct(png_ptr
);
329 if(setjmp(png_jmpbuf(png_ptr
))) {
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
);
356 class ImageTileWriter
: boost::noncopyable
{
370 ImageTileWriter(const string
&fname
, int xblock
, int yblock
, int blocksize
) : temp(xblock
* blocksize
, blocksize
) {
378 fp
= fopen(fname
.c_str(), "wb");
381 png_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
384 info_ptr
= png_create_info_struct(png_ptr
);
387 if(setjmp(png_jmpbuf(png_ptr
))) {
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
);
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
);
417 void write_tile(int x
, int y
, const Image
&tile
) {
419 CHECK(y
> cury
|| x
> curx
);
425 temp
.copyfrom(tile
, x
* chunk
, 0);
432 png_write_end(png_ptr
, info_ptr
);
433 png_destroy_write_struct(&png_ptr
, &info_ptr
);
445 void check_semiass_failure() {
446 CHECK(!semiass_failure
);
451 // yeah, uh, yeah, uh, yeah.
455 void multirun_clear() {
458 void multirun_add(const string
&str
) {
461 void multirun_spawn() {
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
470 void multirun_wait() {
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
++)
485 printf("Master %s %d/%d/%d waiting/running/finished\n", phase
.c_str(), runs
.size(), simul
, totnum
- runs
.size() - simul
);
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
);
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
);
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
);
539 extern "C" int init(lua_State
* L
) {
540 using namespace luabind
;
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
),
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
)