|
@ -10,9 +10,10 @@ struct size2d { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
struct buffer { |
|
|
struct buffer { |
|
|
char *data; |
|
|
void *data; |
|
|
size_t len; |
|
|
size_t len; |
|
|
size_t alloc; |
|
|
size_t alloc; |
|
|
|
|
|
unsigned element; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
void *xrealloc(void *ptr, size_t size) |
|
|
void *xrealloc(void *ptr, size_t size) |
|
@ -25,22 +26,23 @@ void *xrealloc(void *ptr, size_t size) |
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct buffer buffer_alloc() |
|
|
struct buffer buffer_alloc(const unsigned element_size) |
|
|
{ |
|
|
{ |
|
|
struct buffer buffer; |
|
|
struct buffer buffer; |
|
|
buffer.len = 0; |
|
|
buffer.len = 0; |
|
|
buffer.alloc = 0x10; |
|
|
buffer.alloc = 0x10; |
|
|
buffer.data = xrealloc(NULL, buffer.alloc); |
|
|
buffer.element = element_size; |
|
|
|
|
|
buffer.data = xrealloc(NULL, buffer.alloc * buffer.element); |
|
|
return buffer; |
|
|
return buffer; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void buffer_append(struct buffer *buffer, char c) |
|
|
void buffer_append(struct buffer *buffer, void *data) |
|
|
{ |
|
|
{ |
|
|
if (buffer->alloc <= buffer->len) { |
|
|
if (buffer->alloc <= buffer->len) { |
|
|
buffer->alloc *= 2; |
|
|
buffer->alloc *= 2; |
|
|
buffer->data = xrealloc(buffer->data, buffer->alloc); |
|
|
buffer->data = xrealloc(buffer->data, buffer->alloc * buffer->element); |
|
|
} |
|
|
} |
|
|
buffer->data[buffer->len++] = c; |
|
|
memcpy((char *)buffer->data + buffer->len++ * buffer->element, data, buffer->element); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
char *parse_acres(const char *fname, struct size2d *size) |
|
|
char *parse_acres(const char *fname, struct size2d *size) |
|
@ -51,7 +53,7 @@ char *parse_acres(const char *fname, struct size2d *size) |
|
|
return NULL; |
|
|
return NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
struct buffer buffer = buffer_alloc(); |
|
|
struct buffer buffer = buffer_alloc(sizeof(char)); |
|
|
size->w = 0; |
|
|
size->w = 0; |
|
|
size->h = 0; |
|
|
size->h = 0; |
|
|
|
|
|
|
|
@ -79,7 +81,7 @@ char *parse_acres(const char *fname, struct size2d *size) |
|
|
goto error; |
|
|
goto error; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
buffer_append(&buffer, c); |
|
|
buffer_append(&buffer, &c); |
|
|
width++; |
|
|
width++; |
|
|
} |
|
|
} |
|
|
funlockfile(f); |
|
|
funlockfile(f); |
|
@ -184,6 +186,19 @@ int render_bitmap(const char *fname, const char *acres, const struct size2d size |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint32_t adler32(const unsigned char *data, const size_t len) |
|
|
|
|
|
{ |
|
|
|
|
|
// Shamelessly copied from wikipedia...
|
|
|
|
|
|
uint32_t a = 1, b = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (size_t index = 0; index < len; index++) { |
|
|
|
|
|
a = (a + data[index]) % 65521; |
|
|
|
|
|
b = (b + a) % 65521; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return (b << 16) | a; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
int main(int argc, char *argv[]) |
|
|
{ |
|
|
{ |
|
|
struct size2d size; |
|
|
struct size2d size; |
|
@ -198,6 +213,10 @@ int main(int argc, char *argv[]) |
|
|
char *next = xrealloc(NULL, size.w * size.h); |
|
|
char *next = xrealloc(NULL, size.w * size.h); |
|
|
memcpy(next, acres, size.w * size.h); |
|
|
memcpy(next, acres, size.w * size.h); |
|
|
|
|
|
|
|
|
|
|
|
struct buffer hashes = buffer_alloc(sizeof(uint32_t)); |
|
|
|
|
|
unsigned loop_found = 0; |
|
|
|
|
|
unsigned loop_iterlen = 0; |
|
|
|
|
|
|
|
|
char *fname = NULL; |
|
|
char *fname = NULL; |
|
|
clock_t start = clock(); |
|
|
clock_t start = clock(); |
|
|
for (unsigned i = 0; i <= minutes; i++) { |
|
|
for (unsigned i = 0; i <= minutes; i++) { |
|
@ -205,6 +224,24 @@ int main(int argc, char *argv[]) |
|
|
advance_frame(acres, next, size); |
|
|
advance_frame(acres, next, size); |
|
|
memcpy(acres, next, size.w * size.h); |
|
|
memcpy(acres, next, size.w * size.h); |
|
|
|
|
|
|
|
|
|
|
|
if (!loop_found) { |
|
|
|
|
|
uint32_t hash = adler32((unsigned char *)acres, size.w * size.h); |
|
|
|
|
|
for (unsigned i = 0; i < hashes.len; i++) { |
|
|
|
|
|
uint32_t check = ((uint32_t *)hashes.data)[i]; |
|
|
|
|
|
if (check == hash) { |
|
|
|
|
|
loop_found = i + 1; |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (loop_found) { |
|
|
|
|
|
loop_iterlen = (i - loop_found); |
|
|
|
|
|
minutes = (minutes - i) % loop_iterlen + i; |
|
|
|
|
|
} else { |
|
|
|
|
|
buffer_append(&hashes, &hash); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (i % 10000 == 0) { |
|
|
if (i % 10000 == 0) { |
|
|
double framespers = 10000 / ((double)(clock() - start) / CLOCKS_PER_SEC); |
|
|
double framespers = 10000 / ((double)(clock() - start) / CLOCKS_PER_SEC); |
|
|
unsigned eta = (double)(minutes - i) / framespers; |
|
|
unsigned eta = (double)(minutes - i) / framespers; |
|
@ -235,8 +272,10 @@ int main(int argc, char *argv[]) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (loop_found) printf("Loop starting frame: %u (length %u)\n", loop_found, loop_iterlen); |
|
|
printf("Resource value: %u\n", wood * lumber); |
|
|
printf("Resource value: %u\n", wood * lumber); |
|
|
|
|
|
|
|
|
|
|
|
free(hashes.data); |
|
|
free(next); |
|
|
free(next); |
|
|
free(acres); |
|
|
free(acres); |
|
|
return 0; |
|
|
return 0; |
|
|