build.c (60794B)
1 #include <sys/mman.h> 2 #include <sys/stat.h> 3 #include <sys/types.h> 4 5 #include <ctype.h> 6 #include <dirent.h> 7 #include <err.h> 8 #include <fcntl.h> 9 #include <math.h> 10 #include <pthread.h> 11 #include <stdio.h> 12 #include <stdint.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #include "skins.h" 18 19 #define COL_HASH_SZ 65536 20 #define GRID_SZ 64 21 #define MAP_MAX 3000.0f 22 #define MAP_MIN -3000.0f 23 #define MAX_COL_MODELS 32768 24 #define MAX_FILES 32768 25 #define NAME_SZ 24 26 #define PATH_CACHE_SZ 16384 27 #define PATH_DB_SZ 65536 28 29 30 struct col_cell { 31 struct col_triangle *tris; 32 uint32_t count; 33 uint32_t capacity; 34 }; 35 36 struct col_header { 37 char magic[4]; 38 uint32_t size; 39 char model_name[22]; 40 uint16_t model_id; 41 float radius; 42 float center[3]; 43 float min[3]; 44 float max[3]; 45 uint16_t num_spheres; 46 uint16_t num_boxes; 47 uint16_t num_faces; 48 uint8_t num_lines; 49 uint8_t pad; 50 uint32_t flags; 51 uint32_t spheres_offset; 52 uint32_t boxes_offset; 53 uint32_t lines_offset; 54 uint32_t vertices_offset; 55 uint32_t faces_offset; 56 uint32_t shadow_offset; 57 } __attribute__((packed)); 58 59 struct col_model { 60 char name[NAME_SZ]; 61 struct col_triangle *tris; 62 uint32_t num_tris; 63 }; 64 65 struct col_triangle { 66 float v0[3]; 67 float v1[3]; 68 float v2[3]; 69 float norm[3]; 70 uint8_t surface; 71 }; 72 73 struct file_list { 74 char names[MAX_FILES][NAME_SZ]; 75 int count; 76 }; 77 78 struct img_header { 79 char magic[4]; 80 uint32_t entries; 81 }; 82 83 struct img_entry { 84 uint32_t offset; 85 uint16_t size; 86 uint16_t size2; 87 char name[24]; 88 }; 89 90 struct ide_entry { 91 int id; 92 char model[NAME_SZ]; 93 char txd[NAME_SZ]; 94 int time_on; 95 int time_off; 96 }; 97 98 struct mstream { 99 const uint8_t *data; 100 size_t size; 101 size_t pos; 102 }; 103 104 struct path_entry { 105 char key[512]; 106 char resolved[1024]; 107 }; 108 109 struct raw_col_box { 110 float min[3]; 111 float max[3]; 112 uint8_t surface; 113 uint8_t piece; 114 uint8_t lighting; 115 uint8_t pad; 116 } __attribute__((packed)); 117 118 struct raw_col_face { 119 uint16_t a; 120 uint16_t b; 121 uint16_t c; 122 uint8_t surface; 123 uint8_t piece; 124 } __attribute__((packed)); 125 126 struct raw_col_vertex { 127 int16_t x; 128 int16_t y; 129 int16_t z; 130 } __attribute__((packed)); 131 132 struct rw_header { 133 uint32_t type; 134 uint32_t size; 135 uint32_t version; 136 } __attribute__((packed)); 137 138 struct special_actor { 139 int id; 140 const char *model; 141 const char *txd; 142 }; 143 144 struct mat4 { float m[4][4]; }; 145 struct rw_triangle { uint16_t v1, v2, m, v3; }; 146 struct atomic_entry { uint32_t f, g; }; 147 struct tex_name { char name[32]; }; 148 149 struct water_face { 150 float x[4], y[4], z[4]; 151 float u[4], v[4], h[4]; 152 int num; 153 }; 154 155 struct timecyc_entry { 156 uint8_t amb[3]; 157 uint8_t dir[3]; 158 uint8_t sky_top[3]; 159 uint8_t sky_bot[3]; 160 uint8_t water[4]; 161 float far_clp; 162 float fog_st; 163 }; 164 165 struct arena { 166 uint8_t *mem; 167 size_t pos; 168 size_t size; 169 }; 170 171 struct thread_arg { 172 const uint8_t *img_data; 173 struct img_entry *entries; 174 uint32_t start; 175 uint32_t end; 176 struct file_list *fl; 177 struct arena arena; 178 }; 179 180 struct tga_header { 181 uint8_t id_length; 182 uint8_t color_map_type; 183 uint8_t image_type; 184 uint16_t color_map_first; 185 uint16_t color_map_length; 186 uint8_t color_map_entry_size; 187 uint16_t x_origin; 188 uint16_t y_origin; 189 uint16_t width; 190 uint16_t height; 191 uint8_t pixel_depth; 192 uint8_t image_descriptor; 193 } __attribute__((packed)); 194 195 struct tar_header { 196 char name[100]; 197 char mode[8]; 198 char uid[8]; 199 char gid[8]; 200 char size[12]; 201 char mtime[12]; 202 char chksum[8]; 203 char typeflag; 204 char linkname[100]; 205 char magic[6]; 206 char version[2]; 207 char uname[32]; 208 char gname[32]; 209 char devmajor[8]; 210 char devminor[8]; 211 char prefix[155]; 212 char pad[12]; 213 } __attribute__((packed)); 214 215 static struct ide_entry ide_db[65536]; 216 static int ide_count = 0; 217 218 static struct col_cell world_col_grid[GRID_SZ][GRID_SZ]; 219 static struct col_model col_db[MAX_COL_MODELS]; 220 static int col_db_count = 0; 221 static int col_hash[COL_HASH_SZ]; 222 223 static char existing_models[32768][NAME_SZ]; 224 static int existing_models_count = 0; 225 static char existing_textures[32768][NAME_SZ]; 226 static int existing_textures_count = 0; 227 228 static struct water_face water_db[8192]; 229 static int water_face_count = 0; 230 231 static const struct special_actor special_actors[] = { 232 { 1, "truth", "truth" }, 233 { 2, "maccer", "maccer" }, 234 { 3, "andre", "andre" }, 235 { 4, "bbthin", "bbthin" }, 236 { 5, "bb", "bb" }, 237 { 6, "emmet", "emmet" }, 238 { 8, "janitor", "janitor" }, 239 { 290, "rose", "rose" }, 240 { 291, "paul", "paul" }, 241 { 292, "cesar", "cesar" }, 242 { 293, "ogloc", "ogloc" }, 243 { 294, "wuzimu", "wuzimu" }, 244 { 295, "toreno", "toreno" }, 245 { 296, "jizzy", "jizzy" }, 246 { 297, "maddogg", "maddogg" }, 247 { 298, "cat", "cat" }, 248 { 299, "claude", "claude" }, 249 { 300, "ryder2", "ryder" }, 250 { 301, "ryder3", "ryder" }, 251 { 302, "emmet", "emmet" }, 252 { 303, "andre", "andre" }, 253 { 304, "kendl", "kendl" }, 254 { 305, "jethro", "jethro" }, 255 { 306, "zero", "zero" }, 256 { 307, "tbone", "tbone" }, 257 { 308, "maccer", "maccer" }, 258 { 309, "forelli", "forelli" }, 259 { 310, "sweet", "sweet" }, 260 { 311, "smoke", "smoke" }, 261 { 312, "ryder", "ryder" } 262 }; 263 264 static void 265 to_lower_str(char *str) 266 { 267 while (*str) { 268 *str = tolower((unsigned char)*str); 269 str++; 270 } 271 } 272 273 static void 274 scan_existing_assets(void) 275 { 276 DIR *dir; 277 struct dirent *de; 278 char *ext; 279 size_t len; 280 281 dir = opendir("assets/models"); 282 if (dir) { 283 while ((de = readdir(dir))) { 284 ext = strrchr(de->d_name, '.'); 285 if (ext && strcasecmp(ext, ".ply") == 0 && 286 existing_models_count < 32768) { 287 len = ext - de->d_name; 288 if (len >= NAME_SZ) { 289 len = NAME_SZ - 1; 290 } 291 memcpy(existing_models[existing_models_count], 292 de->d_name, len); 293 existing_models[existing_models_count][len] = '\0'; 294 to_lower_str(existing_models[existing_models_count]); 295 existing_models_count++; 296 } 297 } 298 closedir(dir); 299 } 300 301 dir = opendir("assets/textures"); 302 if (dir) { 303 while ((de = readdir(dir))) { 304 ext = strrchr(de->d_name, '.'); 305 if (ext && strcasecmp(ext, ".tga") == 0 && 306 existing_textures_count < 32768) { 307 len = ext - de->d_name; 308 if (len >= NAME_SZ) { 309 len = NAME_SZ - 1; 310 } 311 memcpy(existing_textures[existing_textures_count], 312 de->d_name, len); 313 existing_textures[existing_textures_count][len] = '\0'; 314 to_lower_str(existing_textures[existing_textures_count]); 315 existing_textures_count++; 316 } 317 } 318 closedir(dir); 319 } 320 } 321 322 static int 323 asset_cached(const char *name, int is_model) 324 { 325 char base[NAME_SZ]; 326 size_t len; 327 int i; 328 329 len = strlen(name); 330 if (len < 5) { 331 return (0); 332 } 333 334 strncpy(base, name, len - 4); 335 base[len - 4] = '\0'; 336 to_lower_str(base); 337 338 if (is_model) { 339 for (i = 0; i < existing_models_count; i++) { 340 if (strcmp(existing_models[i], base) == 0) { 341 return (1); 342 } 343 } 344 } else { 345 346 for (i = 0; i < existing_textures_count; i++) { 347 if (strcmp(existing_textures[i], base) == 0) { 348 return (1); 349 } 350 } 351 } 352 return (0); 353 } 354 355 static int 356 asset_exists(const char *name) 357 { 358 if (strstr(name, ".dff") || strstr(name, ".DFF")) { 359 return (asset_cached(name, 1)); 360 } 361 if (strstr(name, ".txd") || strstr(name, ".TXD")) { 362 return (asset_cached(name, 0)); 363 } 364 return (0); 365 } 366 367 static void * 368 arena_alloc(struct arena *a, size_t sz) 369 { 370 size_t align; 371 void *ptr; 372 373 align = (sz + 7) & ~7; 374 if (a->pos + align > a->size) { 375 errx(1, "OOM arena"); 376 } 377 ptr = a->mem + a->pos; 378 a->pos += align; 379 return (ptr); 380 } 381 #define A_ALLOC(a, type, count) (type *)arena_alloc((a), sizeof(type) * (count)) 382 383 static size_t 384 mread(void *dst, size_t sz, size_t n, struct mstream *s) 385 { 386 size_t bytes; 387 388 bytes = sz * n; 389 if (s->pos + bytes <= s->size) { 390 memcpy(dst, s->data + s->pos, bytes); 391 s->pos += bytes; 392 return (n); 393 } 394 return (0); 395 } 396 397 static void 398 mat_identity(struct mat4 *m) 399 { 400 memset(m, 0, sizeof(*m)); 401 m->m[0][0] = 1.0f; 402 m->m[1][1] = 1.0f; 403 m->m[2][2] = 1.0f; 404 m->m[3][3] = 1.0f; 405 } 406 407 static inline void 408 mat_mul(struct mat4 *dst, const struct mat4 *a, const struct mat4 *b) 409 { 410 struct mat4 r; 411 int i; 412 413 for (i = 0; i < 4; i++) { 414 r.m[i][0] = a->m[i][0]*b->m[0][0] + a->m[i][1]*b->m[1][0] + 415 a->m[i][2]*b->m[2][0] + a->m[i][3]*b->m[3][0]; 416 r.m[i][1] = a->m[i][0]*b->m[0][1] + a->m[i][1]*b->m[1][1] + 417 a->m[i][2]*b->m[2][1] + a->m[i][3]*b->m[3][1]; 418 r.m[i][2] = a->m[i][0]*b->m[0][2] + a->m[i][1]*b->m[1][2] + 419 a->m[i][2]*b->m[2][2] + a->m[i][3]*b->m[3][2]; 420 r.m[i][3] = a->m[i][0]*b->m[0][3] + a->m[i][1]*b->m[1][3] + 421 a->m[i][2]*b->m[2][3] + a->m[i][3]*b->m[3][3]; 422 } 423 *dst = r; 424 } 425 426 static int 427 resolve_simple(const char *root, const char *rel, char *out, size_t out_sz) 428 { 429 DIR *dir; 430 struct dirent *de; 431 char path[1024]; 432 char tmp[1024]; 433 char *seg, *saveptr; 434 int found; 435 436 if (snprintf(path, sizeof(path), "%s", root) >= (int)sizeof(path)) { 437 return (0); 438 } 439 strncpy(tmp, rel, sizeof(tmp) - 1); 440 tmp[sizeof(tmp) - 1] = '\0'; 441 442 seg = strtok_r(tmp, "/", &saveptr); 443 while (seg) { 444 dir = opendir(path); 445 if (!dir) { 446 return (0); 447 } 448 found = 0; 449 while ((de = readdir(dir))) { 450 if (strcasecmp(de->d_name, seg) == 0) { 451 if (snprintf(path + strlen(path), 452 sizeof(path) - strlen(path), "/%s", 453 de->d_name) >= (int)(sizeof(path) - strlen(path))) { 454 closedir(dir); 455 return (0); 456 } 457 found = 1; 458 break; 459 } 460 } 461 closedir(dir); 462 if (!found) { 463 return (0); 464 } 465 seg = strtok_r(NULL, "/", &saveptr); 466 } 467 468 strncpy(out, path, out_sz - 1); 469 out[out_sz - 1] = '\0'; 470 return (1); 471 } 472 473 static FILE * 474 fopen_simple(const char *root, const char *rel) 475 { 476 char resolved[1024]; 477 478 if (resolve_simple(root, rel, resolved, sizeof(resolved))) { 479 return (fopen(resolved, "rb")); 480 } 481 return (NULL); 482 } 483 484 static void 485 trim_spaces(char *str) 486 { 487 char *start = str; 488 size_t len; 489 char *end; 490 491 while (*start == ' ' || *start == '\t') { 492 start++; 493 } 494 if (start != str) { 495 memmove(str, start, strlen(start) + 1); 496 } 497 498 len = strlen(str); 499 if (len == 0) { 500 return; 501 } 502 503 end = str + len - 1; 504 while (end >= str && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) { 505 *end = '\0'; 506 end--; 507 } 508 } 509 510 static int 511 list_has(struct file_list *l, const char *name) 512 { 513 int i; 514 515 for (i = 0; i < l->count; i++) { 516 if (strcasecmp(l->names[i], name) == 0) { 517 return (1); 518 } 519 } 520 return (0); 521 } 522 523 static void 524 list_add(struct file_list *l, const char *name) 525 { 526 size_t len, i; 527 528 if (l->count >= MAX_FILES || list_has(l, name)) { 529 return; 530 } 531 len = strlen(name); 532 if (len >= NAME_SZ) { 533 len = NAME_SZ - 1; 534 } 535 for (i = 0; i < len; i++) { 536 l->names[l->count][i] = tolower((unsigned char)name[i]); 537 } 538 l->names[l->count][len] = '\0'; 539 l->count++; 540 } 541 542 static void 543 clean_ide_line(char *p) 544 { 545 char *comment; 546 char *end; 547 size_t len; 548 549 comment = strchr(p, '#'); 550 if (comment) { 551 *comment = '\0'; 552 } 553 554 len = strlen(p); 555 if (len == 0) { 556 return; 557 } 558 559 end = p + len - 1; 560 while (end >= p && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) { 561 *end = '\0'; 562 end--; 563 } 564 } 565 566 static void 567 preparse_ide(const char *root, const char *rel, struct file_list *fl) 568 { 569 FILE *f; 570 char line[512]; 571 char *p; 572 int in_tobj = 0; 573 int in_peds = 0; 574 575 f = fopen_simple(root, rel); 576 if (!f) { 577 return; 578 } 579 580 while (fgets(line, sizeof(line), f)) { 581 p = line; 582 line[strcspn(line, "\r\n")] = '\0'; 583 while (*p == ' ' || *p == '\t') { 584 p++; 585 } 586 if (*p == '\0' || *p == '#') { 587 continue; 588 } 589 590 if (strncasecmp(p, "objs", 4) == 0) { 591 in_tobj = 0; 592 in_peds = 0; 593 continue; 594 } 595 if (strncasecmp(p, "cars", 4) == 0) { 596 in_tobj = 0; 597 in_peds = 0; 598 continue; 599 } 600 if (strncasecmp(p, "peds", 4) == 0) { 601 in_tobj = 0; 602 in_peds = 1; 603 continue; 604 } 605 if (strncasecmp(p, "tobj", 4) == 0) { 606 in_tobj = 1; 607 in_peds = 0; 608 continue; 609 } 610 if (strncasecmp(p, "end", 3) == 0) { 611 in_tobj = 0; 612 in_peds = 0; 613 continue; 614 } 615 616 if (isdigit((unsigned char)p[0]) && ide_count < 65536) { 617 char model[NAME_SZ], txd[NAME_SZ]; 618 char *c1, *c2, *c3; 619 char *last_comma, *prev_comma; 620 size_t len; 621 int time_on = 0, time_off = 0; 622 623 c1 = strchr(p, ','); 624 if (!c1) continue; 625 c2 = strchr(c1 + 1, ','); 626 if (!c2) continue; 627 c3 = strchr(c2 + 1, ','); 628 if (!c3) continue; 629 630 len = c2 - (c1 + 1); 631 if (len >= NAME_SZ) { 632 len = NAME_SZ - 1; 633 } 634 memcpy(model, c1 + 1, len); 635 model[len] = '\0'; 636 trim_spaces(model); 637 to_lower_str(model); 638 639 len = c3 - (c2 + 1); 640 if (len >= NAME_SZ) { 641 len = NAME_SZ - 1; 642 } 643 memcpy(txd, c2 + 1, len); 644 txd[len] = '\0'; 645 trim_spaces(txd); 646 to_lower_str(txd); 647 648 if (in_tobj) { 649 char temp_line[512]; 650 strncpy(temp_line, p, sizeof(temp_line) - 1); 651 temp_line[sizeof(temp_line) - 1] = '\0'; 652 clean_ide_line(temp_line); 653 654 last_comma = strrchr(temp_line, ','); 655 if (last_comma) { 656 time_off = atoi(last_comma + 1); 657 *last_comma = '\0'; 658 prev_comma = strrchr(temp_line, ','); 659 if (prev_comma) { 660 time_on = atoi(prev_comma + 1); 661 } 662 *last_comma = ','; 663 } 664 } 665 666 if (in_peds && fl) { 667 char d_name[32], t_name[32]; 668 snprintf(d_name, sizeof(d_name), "%s.dff", model); 669 snprintf(t_name, sizeof(t_name), "%s.txd", txd); 670 list_add(fl, d_name); 671 list_add(fl, t_name); 672 } 673 674 ide_db[ide_count].id = atoi(p); 675 strncpy(ide_db[ide_count].model, model, NAME_SZ); 676 strncpy(ide_db[ide_count].txd, txd, NAME_SZ); 677 ide_db[ide_count].time_on = time_on; 678 ide_db[ide_count].time_off = time_off; 679 ide_count++; 680 } 681 } 682 fclose(f); 683 } 684 685 686 static const struct ide_entry * 687 ide_lookup(int id) 688 { 689 int i; 690 691 for (i = 0; i < ide_count; i++) { 692 if (ide_db[i].id == id) { 693 return (&ide_db[i]); 694 } 695 } 696 return (NULL); 697 } 698 699 static int 700 is_lod_name(const char *name) 701 { 702 return (strstr(name, "lod") != NULL); 703 } 704 705 static void 706 parse_text_ipl(const char *buf, size_t size, FILE *out, struct file_list *fl) 707 { 708 const char *p, *end, *next; 709 char line[512]; 710 char *s, *comma; 711 size_t len; 712 int in_inst; 713 714 p = buf; 715 end = buf + size; 716 in_inst = 0; 717 718 while (p < end) { 719 next = memchr(p, '\n', end - p); 720 len = next ? (size_t)(next - p) : (size_t)(end - p); 721 if (len >= sizeof(line)) { 722 len = sizeof(line) - 1; 723 } 724 memcpy(line, p, len); 725 line[len] = '\0'; 726 p = next ? next + 1 : end; 727 728 s = line; 729 while (*s == ' ' || *s == '\t' || *s == '\r') { 730 s++; 731 } 732 if (*s == '\0' || *s == '#') { 733 continue; 734 } 735 736 if (strncasecmp(s, "inst", 4) == 0 || strncasecmp(s, "tobj", 4) == 0) { 737 in_inst = 1; 738 fprintf(out, "\ninst\n"); 739 continue; 740 } 741 if (strncasecmp(s, "end", 3) == 0) { 742 in_inst = 0; 743 fprintf(out, "end\n"); 744 continue; 745 } 746 747 if (in_inst) { 748 int id; 749 const struct ide_entry *ide; 750 751 id = atoi(s); 752 ide = ide_lookup(id); 753 if (ide && (!is_lod_name(ide->model) || ide->time_on != ide->time_off)) { 754 char d_name[32], t_name[32]; 755 756 snprintf(d_name, sizeof(d_name), "%s.dff", ide->model); 757 snprintf(t_name, sizeof(t_name), "%s.txd", ide->txd); 758 list_add(fl, d_name); 759 list_add(fl, t_name); 760 761 comma = strchr(s, ','); 762 if (comma) { 763 int dummy_id; 764 char dummy_model[64]; 765 int interior; 766 float px, py, pz, rx, ry, rz, rw; 767 768 if (sscanf(s, "%d, %63[^,], %d, %f, " 769 "%f, %f, %f, %f, %f, %f", 770 &dummy_id, dummy_model, &interior, 771 &px, &py, &pz, &rx, &ry, &rz, &rw) == 10) { 772 fprintf(out, "%d, %s, %d, %f, " 773 "%f, %f, %f, %f, %f, %f, " 774 "-1, %d, %d\n", 775 id, ide->model, interior, 776 px, py, pz, rx, ry, rz, rw, 777 ide->time_on, ide->time_off); 778 } 779 } 780 } 781 } 782 } 783 } 784 785 static void 786 parse_binary_ipl(const uint8_t *buf, size_t size, FILE *out, struct file_list *fl) 787 { 788 uint32_t num, off, i; 789 790 memcpy(&num, buf + 4, 4); 791 memcpy(&off, buf + 28, 4); 792 if (off + num * 40 > size) { 793 return; 794 } 795 796 fprintf(out, "\ninst\n"); 797 for (i = 0; i < num; i++) { 798 struct { 799 float px, py, pz, rx, ry, rz, rw; 800 int32_t id, interior, lod; 801 } inst; 802 const struct ide_entry *ide; 803 804 memcpy(&inst, buf + off + i * 40, 40); 805 806 ide = ide_lookup(inst.id); 807 if (ide && (!is_lod_name(ide->model) || ide->time_on != ide->time_off)) { 808 char d_name[32], t_name[32]; 809 810 snprintf(d_name, sizeof(d_name), "%s.dff", ide->model); 811 snprintf(t_name, sizeof(t_name), "%s.txd", ide->txd); 812 list_add(fl, d_name); 813 list_add(fl, t_name); 814 815 fprintf(out, "%d, %s, %d, %f, %f, %f, %f, %f, %f, %f, " 816 "-1, %d, %d\n", 817 inst.id, ide->model, inst.interior, 818 inst.px, inst.py, inst.pz, inst.rx, inst.ry, 819 inst.rz, inst.rw, ide->time_on, ide->time_off); 820 } 821 } 822 fprintf(out, "end\n"); 823 } 824 825 static void 826 blur_pixels(uint32_t *pixels, int w, int h) 827 { 828 uint32_t *temp; 829 int x, y, kx, ky, px, py, count; 830 uint32_t r_sum, g_sum, b_sum, a_sum, c; 831 832 temp = malloc(w * h * 4); 833 if (!temp) { 834 return; 835 } 836 memcpy(temp, pixels, w * h * 4); 837 838 for (y = 0; y < h; y++) { 839 for (x = 0; x < w; x++) { 840 r_sum = 0; 841 g_sum = 0; 842 b_sum = 0; 843 a_sum = 0; 844 count = 0; 845 for (ky = -1; ky <= 1; ky++) { 846 for (kx = -1; kx <= 1; kx++) { 847 px = x + kx; 848 py = y + ky; 849 if (px >= 0 && px < w && py >= 0 && 850 py < h) { 851 c = temp[py * w + px]; 852 b_sum += (c & 0xFF); 853 g_sum += ((c >> 8) & 0xFF); 854 r_sum += ((c >> 16) & 0xFF); 855 a_sum += ((c >> 24) & 0xFF); 856 count++; 857 } 858 } 859 } 860 pixels[y * w + x] = (b_sum/count) | 861 ((g_sum/count) << 8) | ((r_sum/count) << 16) | 862 ((a_sum/count) << 24); 863 } 864 } 865 free(temp); 866 } 867 868 static int 869 nearest_pow2(int x) 870 { 871 int p = 1; 872 873 while (p * 2 <= x) { 874 p *= 2; 875 } 876 if (x - p < p * 2 - x) { 877 return (p); 878 } 879 return (p * 2); 880 } 881 882 static void 883 convert_txd(const uint8_t *data, size_t size, const char *name, struct arena *a) 884 { 885 struct mstream ms = { data, size, 0 }; 886 struct rw_header h, sh; 887 struct { 888 uint32_t plt, flt; char n[32], m[32]; uint32_t fmt; char fcc[4]; 889 uint16_t w, h; uint8_t d, lvl, typ, cmp; 890 } __attribute__((packed)) rh; 891 uint32_t mip_size, p_size, *pixels, code, cols[4], pal[256]; 892 uint8_t *cmp, r0, g0, b0, r1, g1, b1, a_val, *src, *indices; 893 uint16_t c0, c1, *src16; 894 size_t chunk_end; 895 int bx, by, is_dxt3, x, y, i, j, k, pal_has_alpha; 896 char t_name[32], out_name[256]; 897 FILE *out; 898 struct tga_header out_hdr; 899 uint32_t *final_pixels; 900 int new_w, new_h, sy, sx; 901 902 while (mread(&h, sizeof(h), 1, &ms) == 1) { 903 chunk_end = ms.pos + h.size; 904 if (h.type == 0x16) { 905 continue; 906 } 907 908 if (h.type == 0x15) { 909 if (mread(&sh, sizeof(sh), 1, &ms) != 1) { 910 break; 911 } 912 if (mread(&rh, sizeof(rh), 1, &ms) != 1) { 913 break; 914 } 915 916 if (rh.plt != 9 && rh.plt != 8) { 917 ms.pos = chunk_end; 918 continue; 919 } 920 921 if (rh.d == 8) { 922 if (mread(pal, 4, 256, &ms) != 256) { 923 break; 924 } 925 pal_has_alpha = 0; 926 for (k = 0; k < 256; k++) { 927 if ((pal[k] >> 24) != 0) { 928 pal_has_alpha = 1; 929 break; 930 } 931 } 932 if (!pal_has_alpha) { 933 for (k = 0; k < 256; k++) { 934 pal[k] |= (255U << 24); 935 } 936 } 937 } else if (rh.d == 4) { 938 if (mread(pal, 4, 16, &ms) != 16) { 939 break; 940 } 941 for (k = 0; k < 16; k++) { 942 pal[k] |= (255U << 24); 943 } 944 } 945 946 if (mread(&mip_size, 4, 1, &ms) != 1) { 947 break; 948 } 949 950 p_size = rh.w * rh.h; 951 pixels = A_ALLOC(a, uint32_t, p_size); 952 memset(pixels, 0, p_size * 4); 953 954 if (memcmp(rh.fcc, "DXT1", 4) == 0 || 955 memcmp(rh.fcc, "DXT3", 4) == 0) { 956 cmp = A_ALLOC(a, uint8_t, mip_size); 957 mread(cmp, 1, mip_size, &ms); 958 bx = rh.w / 4; 959 by = rh.h / 4; 960 is_dxt3 = memcmp(rh.fcc, "DXT3", 4) == 0; 961 962 for (y = 0; y < by; y++) { 963 for (x = 0; x < bx; x++) { 964 const uint8_t *blk = cmp + 965 (y * bx + x) * (is_dxt3 ? 16 : 8); 966 const uint8_t *cblk = is_dxt3 ? 967 blk + 8 : blk; 968 969 c0 = cblk[0] | (cblk[1] << 8); 970 c1 = cblk[2] | (cblk[3] << 8); 971 code = cblk[4] | (cblk[5] << 8) | 972 (cblk[6] << 16) | (cblk[7] << 24); 973 974 r0 = ((c0 >> 11) & 0x1F) << 3; 975 g0 = ((c0 >> 5) & 0x3F) << 2; 976 b0 = (c0 & 0x1F) << 3; 977 r1 = ((c1 >> 11) & 0x1F) << 3; 978 g1 = ((c1 >> 5) & 0x3F) << 2; 979 b1 = (c1 & 0x1F) << 3; 980 981 cols[0] = b0 | (g0 << 8) | 982 (r0 << 16) | (0xFFU << 24); 983 cols[1] = b1 | (g1 << 8) | 984 (r1 << 16) | (0xFFU << 24); 985 if (c0 > c1 || is_dxt3) { 986 cols[2] = ((2*b0+b1)/3) | 987 (((2*g0+g1)/3)<<8) | 988 (((2*r0+r1)/3)<<16) | 989 (0xFFU<<24); 990 cols[3] = ((b0+2*b1)/3) | 991 (((g0+2*g1)/3)<<8) | 992 (((r0+2*r1)/3)<<16) | 993 (0xFFU<<24); 994 } else { 995 cols[2] = ((b0+b1)/2) | 996 (((g0+g1)/2)<<8) | 997 (((r0+r1)/2)<<16) | 998 (0xFFU<<24); 999 cols[3] = 0; 1000 } 1001 1002 for (i = 0; i < 4; i++) { 1003 for (j = 0; j < 4; j++) { 1004 int px_idx = x * 4 + j; 1005 int py_idx = y * 4 + i; 1006 if (px_idx < rh.w && 1007 py_idx < rh.h) { 1008 uint32_t c = cols[(code >> (2 * (i * 4 + j))) & 3]; 1009 if (is_dxt3) { 1010 a_val = (blk[i * 2 + (j / 2)] >> (4 * (j % 2))) & 0x0F; 1011 a_val = (a_val << 4) | a_val; 1012 c = (c & 0x00FFFFFF) | ((uint32_t)a_val << 24); 1013 } 1014 pixels[py_idx * rh.w + px_idx] = c; 1015 } 1016 } 1017 } 1018 } 1019 } 1020 } else if (rh.d == 8) { 1021 indices = malloc(mip_size); 1022 if (indices) { 1023 mread(indices, 1, mip_size, &ms); 1024 for (i = 0; (uint32_t)i < p_size; i++) { 1025 uint32_t c = pal[indices[i]]; 1026 pixels[i] = (c & 0xFF00FF00) | 1027 ((c & 0x00FF0000) >> 16) | 1028 ((c & 0x000000FF) << 16); 1029 } 1030 free(indices); 1031 } 1032 } else if (rh.d == 32) { 1033 mread(pixels, 1, mip_size, &ms); 1034 if (rh.fmt == 22) { 1035 for (i = 0; (uint32_t)i < p_size; i++) { 1036 pixels[i] |= (255U << 24); 1037 } 1038 } 1039 } else if (rh.d == 16) { 1040 src16 = malloc(mip_size); 1041 if (src16) { 1042 mread(src16, 1, mip_size, &ms); 1043 for (i = 0; (uint32_t)i < p_size; i++) { 1044 uint16_t val = src16[i]; 1045 uint8_t r = 0, g = 0, b = 0, a_v = 255; 1046 if (rh.fmt == 26) { 1047 a_v = ((val >> 12) & 0x0F) * 17; 1048 r = ((val >> 8) & 0x0F) * 17; 1049 g = ((val >> 4) & 0x0F) * 17; 1050 b = (val & 0x0F) * 17; 1051 } else if (rh.fmt == 25) { 1052 a_v = ((val >> 15) & 0x01) ? 255 : 0; 1053 r = ((val >> 10) & 0x1F) << 3; 1054 g = ((val >> 5) & 0x1F) << 3; 1055 b = (val & 0x1F) << 3; 1056 r |= (r >> 5); g |= (g >> 5); b |= (b >> 5); 1057 } else if (rh.fmt == 23) { 1058 r = ((val >> 11) & 0x1F) << 3; 1059 g = ((val >> 5) & 0x3F) << 2; 1060 b = (val & 0x1F) << 3; 1061 r |= (r >> 5); g |= (g >> 6); b |= (b >> 5); 1062 a_v = 255; 1063 } 1064 pixels[i] = (a_v << 24) | (r << 16) | (g << 8) | b; 1065 } 1066 free(src16); 1067 } 1068 } else if (rh.d == 24) { 1069 src = malloc(mip_size); 1070 if (src) { 1071 mread(src, 1, mip_size, &ms); 1072 for (i = 0; (uint32_t)i < p_size; i++) { 1073 pixels[i] = (255U << 24) | 1074 (src[i*3+2] << 16) | 1075 (src[i*3+1] << 8) | src[i*3+0]; 1076 } 1077 free(src); 1078 } 1079 } 1080 1081 for (k = 0; k < 31 && rh.n[k]; k++) { 1082 t_name[k] = tolower((unsigned char)rh.n[k]); 1083 } 1084 t_name[k] = '\0'; 1085 if (t_name[0] == '\0') { 1086 strncpy(t_name, name, 31); 1087 t_name[31] = '\0'; 1088 } 1089 to_lower_str(t_name); 1090 1091 if (strstr(t_name, "waterclear256")) { 1092 blur_pixels(pixels, rh.w, rh.h); 1093 blur_pixels(pixels, rh.w, rh.h); 1094 } 1095 1096 new_w = nearest_pow2(rh.w); 1097 new_h = nearest_pow2(rh.h); 1098 final_pixels = pixels; 1099 1100 if (new_w != rh.w || new_h != rh.h) { 1101 final_pixels = malloc(new_w * new_h * 4); 1102 if (final_pixels) { 1103 for (y = 0; y < new_h; y++) { 1104 sy = (y * rh.h) / new_h; 1105 if (sy >= rh.h) { 1106 sy = rh.h - 1; 1107 } 1108 for (x = 0; x < new_w; x++) { 1109 sx = (x * rh.w) / new_w; 1110 if (sx >= rh.w) { 1111 sx = rh.w - 1; 1112 } 1113 final_pixels[y * new_w + x] = pixels[sy * rh.w + sx]; 1114 } 1115 } 1116 } else { 1117 final_pixels = pixels; 1118 new_w = rh.w; 1119 new_h = rh.h; 1120 } 1121 } 1122 1123 snprintf(out_name, sizeof(out_name), "assets/textures/%s.tga", t_name); 1124 out = fopen(out_name, "wb"); 1125 if (out) { 1126 memset(&out_hdr, 0, sizeof(out_hdr)); 1127 out_hdr.image_type = 2; 1128 out_hdr.width = new_w; 1129 out_hdr.height = new_h; 1130 out_hdr.pixel_depth = 32; 1131 out_hdr.image_descriptor = 8; 1132 1133 fwrite(&out_hdr, sizeof(out_hdr), 1, out); 1134 fwrite(final_pixels, 4, new_w * new_h, out); 1135 fclose(out); 1136 } 1137 1138 if (final_pixels != pixels) { 1139 free(final_pixels); 1140 } 1141 } 1142 ms.pos = chunk_end; 1143 } 1144 } 1145 1146 static void 1147 process_particle_txd(const char *root, struct arena *a) 1148 { 1149 FILE *f; 1150 size_t sz; 1151 uint8_t *buf; 1152 1153 f = fopen_simple(root, "models/particle.txd"); 1154 if (!f) { 1155 return; 1156 } 1157 fseek(f, 0, SEEK_END); 1158 sz = ftell(f); 1159 fseek(f, 0, SEEK_SET); 1160 buf = malloc(sz); 1161 if (fread(buf, 1, sz, f) == sz) { 1162 a->pos = 0; 1163 convert_txd(buf, sz, "particle", a); 1164 } 1165 free(buf); 1166 fclose(f); 1167 } 1168 1169 struct frame { struct mat4 abs; int32_t parent; }; 1170 struct geom { float *v, *u; uint8_t *c; uint16_t *i, *m; uint32_t nv, ni, nm; struct tex_name *t; }; 1171 1172 static int 1173 is_container(uint32_t type) 1174 { 1175 switch (type) { 1176 case 0x03: case 0x06: case 0x07: case 0x08: case 0x0E: case 0x0F: 1177 case 0x10: case 0x14: case 0x1A: case 0x1B: 1178 return (1); 1179 } 1180 return (0); 1181 } 1182 1183 static int 1184 is_skin(const char *name) 1185 { 1186 int i; 1187 1188 for (i = 0; i < 313; i++) { 1189 if (skin_names[i] && skin_names[i][0] != '\0' && 1190 strcasecmp(skin_names[i], name) == 0) { 1191 return (1); 1192 } 1193 } 1194 for (i = 0; i < (int)(sizeof(special_actors) / sizeof(special_actors[0])); i++) { 1195 if (strcasecmp(special_actors[i].model, name) == 0) { 1196 return (1); 1197 } 1198 } 1199 return (0); 1200 } 1201 1202 static void 1203 convert_dff(const uint8_t *data, size_t size, const char *name, struct arena *a) 1204 { 1205 struct mstream ms = { data, size, 0 }; 1206 struct rw_header h; 1207 struct frame *frames = NULL; 1208 struct geom *geoms = NULL; 1209 struct atomic_entry *atomics; 1210 uint32_t n_frames = 0, n_geoms = 0, n_atomics = 0; 1211 uint32_t last_cont = 0; 1212 int32_t cur_g = -1, cur_m = -1, wait_tex = 0; 1213 size_t end; 1214 int is_ped; 1215 1216 is_ped = is_skin(name); 1217 1218 atomics = A_ALLOC(a, struct atomic_entry, 256); 1219 1220 while (mread(&h, sizeof(h), 1, &ms) == 1) { 1221 end = ms.pos + h.size; 1222 1223 if (is_container(h.type)) { 1224 last_cont = h.type; 1225 if (h.type == 0x0F) cur_g++; 1226 if (h.type == 0x08) cur_m = -1; 1227 if (h.type == 0x07) cur_m++; 1228 if (h.type == 0x06) wait_tex = 1; 1229 continue; 1230 } 1231 1232 if (h.type == 0x01) { 1233 if (last_cont == 0x0E) { 1234 mread(&n_frames, 4, 1, &ms); 1235 frames = A_ALLOC(a, struct frame, n_frames); 1236 for (uint32_t i = 0; i < n_frames; i++) { 1237 float rot[9], pos[3]; int32_t parent, flags; 1238 mread(rot, 4, 9, &ms); mread(pos, 4, 3, &ms); 1239 mread(&parent, 4, 1, &ms); mread(&flags, 4, 1, &ms); 1240 1241 struct mat4 l; memset(&l, 0, sizeof(l)); 1242 l.m[0][0] = rot[0]; l.m[0][1] = rot[3]; l.m[0][2] = rot[6]; 1243 l.m[1][0] = rot[1]; l.m[1][1] = rot[4]; l.m[1][2] = rot[7]; 1244 l.m[2][0] = rot[2]; l.m[2][1] = rot[5]; l.m[2][2] = rot[8]; 1245 l.m[0][3] = pos[0]; l.m[1][3] = pos[1]; l.m[2][3] = pos[2]; l.m[3][3] = 1.0f; 1246 1247 if (parent >= 0 && parent < (int32_t)i) { 1248 mat_mul(&frames[i].abs, &frames[parent].abs, &l); 1249 } else { 1250 float sx = sqrtf(l.m[0][0]*l.m[0][0] + l.m[1][0]*l.m[1][0] + l.m[2][0]*l.m[2][0]); 1251 float sy = sqrtf(l.m[0][1]*l.m[0][1] + l.m[1][1]*l.m[1][1] + l.m[2][1]*l.m[2][1]); 1252 float sz = sqrtf(l.m[0][2]*l.m[0][2] + l.m[1][2]*l.m[1][2] + l.m[2][2]*l.m[2][2]); 1253 mat_identity(&frames[i].abs); 1254 frames[i].abs.m[0][0] = sx; 1255 frames[i].abs.m[1][1] = sy; 1256 frames[i].abs.m[2][2] = sz; 1257 } 1258 } 1259 } else if (last_cont == 0x1A) { 1260 mread(&n_geoms, 4, 1, &ms); 1261 if (n_geoms) { 1262 geoms = A_ALLOC(a, struct geom, n_geoms); 1263 } 1264 cur_g = -1; 1265 } else if (last_cont == 0x0F && cur_g >= 0) { 1266 struct geom *g = &geoms[cur_g]; 1267 uint32_t fmt, morphs; 1268 mread(&fmt, 4, 1, &ms); mread(&g->ni, 4, 1, &ms); 1269 mread(&g->nv, 4, 1, &ms); mread(&morphs, 4, 1, &ms); 1270 1271 if (g->nv > 0 && g->ni > 0) { 1272 uint16_t flg = fmt & 0xFFFF, tex_c = (fmt & 0x00FF0000) >> 16; 1273 if (tex_c == 0 && (flg & 0x0004)) { 1274 tex_c = 1; 1275 } 1276 1277 g->c = NULL; 1278 if (flg & 0x0008) { 1279 g->c = A_ALLOC(a, uint8_t, g->nv * 4); 1280 mread(g->c, 1, g->nv * 4, &ms); 1281 } 1282 1283 g->u = A_ALLOC(a, float, g->nv * 2); 1284 if (tex_c > 0) { 1285 mread(g->u, sizeof(float) * 2, g->nv, &ms); 1286 if (tex_c > 1) { 1287 ms.pos += (tex_c - 1) * sizeof(float) * 2 * g->nv; 1288 } 1289 } 1290 1291 struct rw_triangle *tris = A_ALLOC(a, struct rw_triangle, g->ni); 1292 mread(tris, sizeof(*tris), g->ni, &ms); 1293 ms.pos += sizeof(float) * 4; 1294 1295 int32_t has_v, has_n; 1296 mread(&has_v, 4, 1, &ms); mread(&has_n, 4, 1, &ms); 1297 if (has_v) { 1298 g->v = A_ALLOC(a, float, g->nv * 3); 1299 mread(g->v, sizeof(float) * 3, g->nv, &ms); 1300 } 1301 1302 g->i = A_ALLOC(a, uint16_t, g->ni * 3); 1303 g->m = A_ALLOC(a, uint16_t, g->ni); 1304 for (uint32_t j = 0; j < g->ni; j++) { 1305 g->i[j*3+0] = tris[j].v1; 1306 g->i[j*3+1] = tris[j].v2; 1307 g->i[j*3+2] = tris[j].v3; 1308 g->m[j] = tris[j].m; 1309 } 1310 } 1311 } else if (last_cont == 0x08 && cur_g >= 0) { 1312 mread(&geoms[cur_g].nm, 4, 1, &ms); 1313 if (geoms[cur_g].nm > 0) { 1314 geoms[cur_g].t = A_ALLOC(a, struct tex_name, geoms[cur_g].nm); 1315 } 1316 } else if (last_cont == 0x14) { 1317 uint32_t f_idx, g_idx, flg, unused; 1318 mread(&f_idx, 4, 1, &ms); mread(&g_idx, 4, 1, &ms); 1319 mread(&flg, 4, 1, &ms); mread(&unused, 4, 1, &ms); 1320 if (n_atomics < 256) { 1321 atomics[n_atomics].f = f_idx; 1322 atomics[n_atomics].g = g_idx; 1323 n_atomics++; 1324 } 1325 } 1326 last_cont = 0; 1327 } else if (h.type == 0x02 && wait_tex && cur_g >= 0) { 1328 struct geom *g = &geoms[cur_g]; 1329 if (cur_m >= 0 && (uint32_t)cur_m < g->nm) { 1330 size_t len = h.size < 31 ? h.size : 31; 1331 mread(g->t[cur_m].name, 1, len, &ms); 1332 for (size_t k = 0; k < len; k++) { 1333 g->t[cur_m].name[k] = tolower((unsigned char)g->t[cur_m].name[k]); 1334 } 1335 } 1336 wait_tex = 0; 1337 } 1338 1339 ms.pos = end; 1340 } 1341 1342 uint32_t t_nv = 0, t_ni = 0, t_nm = 0; 1343 int has_any_colors = 0; 1344 for (uint32_t i = 0; i < n_atomics; i++) { 1345 if (atomics[i].g < n_geoms) { 1346 t_nv += geoms[atomics[i].g].nv; 1347 t_ni += geoms[atomics[i].g].ni; 1348 t_nm += geoms[atomics[i].g].nm; 1349 if (geoms[atomics[i].g].c) { 1350 has_any_colors = 1; 1351 } 1352 } 1353 } 1354 1355 if (t_nv > 0 && t_ni > 0) { 1356 float *f_v = A_ALLOC(a, float, t_nv * 3); 1357 float *f_u = A_ALLOC(a, float, t_nv * 2); 1358 uint8_t *f_c = A_ALLOC(a, uint8_t, t_nv * 4); 1359 uint16_t *f_i = A_ALLOC(a, uint16_t, t_ni * 3); 1360 uint16_t *f_m = A_ALLOC(a, uint16_t, t_ni); 1361 struct tex_name *f_t = t_nm > 0 ? A_ALLOC(a, struct tex_name, t_nm) : NULL; 1362 1363 uint32_t vo = 0, to = 0, mo = 0; 1364 for (uint32_t i = 0; i < n_atomics; i++) { 1365 if (atomics[i].g >= n_geoms || atomics[i].f >= n_frames) { 1366 continue; 1367 } 1368 struct geom *g = &geoms[atomics[i].g]; 1369 struct frame *fr = &frames[atomics[i].f]; 1370 1371 for (uint32_t j = 0; j < g->nv; j++) { 1372 float x = g->v[j*3+0], y = g->v[j*3+1], z = g->v[j*3+2]; 1373 f_v[(vo+j)*3+0] = fr->abs.m[0][0]*x + fr->abs.m[0][1]*y + fr->abs.m[0][2]*z + fr->abs.m[0][3]; 1374 f_v[(vo+j)*3+1] = fr->abs.m[1][0]*x + fr->abs.m[1][1]*y + fr->abs.m[1][2]*z + fr->abs.m[1][3]; 1375 f_v[(vo+j)*3+2] = fr->abs.m[2][0]*x + fr->abs.m[2][1]*y + fr->abs.m[2][2]*z + fr->abs.m[2][3]; 1376 f_u[(vo+j)*2+0] = g->u[j*2+0]; 1377 f_u[(vo+j)*2+1] = g->u[j*2+1]; 1378 if (g->c) { 1379 f_c[(vo+j)*4+0] = g->c[j*4+0]; 1380 f_c[(vo+j)*4+1] = g->c[j*4+1]; 1381 f_c[(vo+j)*4+2] = g->c[j*4+2]; 1382 f_c[(vo+j)*4+3] = g->c[j*4+3]; 1383 } else { 1384 f_c[(vo+j)*4+0] = 255; 1385 f_c[(vo+j)*4+1] = 255; 1386 f_c[(vo+j)*4+2] = 255; 1387 f_c[(vo+j)*4+3] = 255; 1388 } 1389 } 1390 for (uint32_t j = 0; j < g->ni; j++) { 1391 f_i[(to+j)*3+0] = g->i[j*3+0] + vo; 1392 f_i[(to+j)*3+1] = g->i[j*3+1] + vo; 1393 f_i[(to+j)*3+2] = g->i[j*3+2] + vo; 1394 f_m[to+j] = g->m[j] + mo; 1395 } 1396 for (uint32_t j = 0; j < g->nm; j++) { 1397 memcpy(f_t[mo+j].name, g->t[j].name, 32); 1398 } 1399 vo += g->nv; 1400 to += g->ni; 1401 mo += g->nm; 1402 } 1403 1404 float b_cx = 0, b_cy = 0, b_cz = 0, b_r = 0; 1405 float minx = f_v[0], maxx = f_v[0], miny = f_v[1], maxy = f_v[1], minz = f_v[2], maxz = f_v[2]; 1406 for (uint32_t i = 1; i < t_nv; i++) { 1407 if (f_v[i*3+0] < minx) minx = f_v[i*3+0]; 1408 if (f_v[i*3+0] > maxx) maxx = f_v[i*3+0]; 1409 if (f_v[i*3+1] < miny) miny = f_v[i*3+1]; 1410 if (f_v[i*3+1] > maxy) maxy = f_v[i*3+1]; 1411 if (f_v[i*3+2] < minz) minz = f_v[i*3+2]; 1412 if (f_v[i*3+2] > maxz) maxz = f_v[i*3+2]; 1413 } 1414 b_cx = (minx+maxx)*0.5f; 1415 b_cy = (miny+maxy)*0.5f; 1416 b_cz = (minz+maxz)*0.5f; 1417 for (uint32_t i = 0; i < t_nv; i++) { 1418 float dx = f_v[i*3+0] - b_cx, dy = f_v[i*3+1] - b_cy, dz = f_v[i*3+2] - b_cz; 1419 float d2 = dx*dx + dy*dy + dz*dz; 1420 if (d2 > b_r) { 1421 b_r = d2; 1422 } 1423 } 1424 b_r = sqrtf(b_r); 1425 1426 char out_name[256]; 1427 snprintf(out_name, sizeof(out_name), "assets/models/%s.ply", name); 1428 FILE *out = fopen(out_name, "wb"); 1429 if (out) { 1430 fprintf(out, "ply\n"); 1431 fprintf(out, "format binary_little_endian 1.0\n"); 1432 fprintf(out, "comment spr_cx %f\n", b_cx); 1433 fprintf(out, "comment spr_cy %f\n", b_cy); 1434 fprintf(out, "comment spr_cz %f\n", b_cz); 1435 fprintf(out, "comment spr_r %f\n", b_r); 1436 fprintf(out, "comment flags %u\n", has_any_colors ? 1 : 0); 1437 for (uint32_t i = 0; i < t_nm; i++) { 1438 fprintf(out, "comment texture %s\n", f_t[i].name); 1439 } 1440 fprintf(out, "element vertex %u\n", t_nv); 1441 fprintf(out, "property float x\n"); 1442 fprintf(out, "property float y\n"); 1443 fprintf(out, "property float z\n"); 1444 fprintf(out, "property float s\n"); 1445 fprintf(out, "property float t\n"); 1446 fprintf(out, "property uchar red\n"); 1447 fprintf(out, "property uchar green\n"); 1448 fprintf(out, "property uchar blue\n"); 1449 fprintf(out, "property uchar alpha\n"); 1450 fprintf(out, "element face %u\n", t_ni); 1451 fprintf(out, "property list uchar int vertex_indices\n"); 1452 fprintf(out, "property ushort material_index\n"); 1453 fprintf(out, "end_header\n"); 1454 1455 for (uint32_t i = 0; i < t_nv; i++) { 1456 float vx = f_v[i*3+0], vy = f_v[i*3+1], vz = f_v[i*3+2]; 1457 float tu = f_u[i*2+0], tv = f_u[i*2+1]; 1458 uint8_t cr = f_c[i*4+0], cg = f_c[i*4+1], cb = f_c[i*4+2], ca = f_c[i*4+3]; 1459 1460 if (is_ped) { 1461 vx = -vx; 1462 } 1463 1464 fwrite(&vx, 4, 1, out); 1465 fwrite(&vy, 4, 1, out); 1466 fwrite(&vz, 4, 1, out); 1467 fwrite(&tu, 4, 1, out); 1468 fwrite(&tv, 4, 1, out); 1469 fwrite(&cr, 1, 1, out); 1470 fwrite(&cg, 1, 1, out); 1471 fwrite(&cb, 1, 1, out); 1472 fwrite(&ca, 1, 1, out); 1473 } 1474 1475 for (uint32_t i = 0; i < t_ni; i++) { 1476 uint8_t count = 3; 1477 int32_t idx[3] = { f_i[i*3+0], f_i[i*3+1], f_i[i*3+2] }; 1478 uint16_t mat = f_m[i]; 1479 fwrite(&count, 1, 1, out); 1480 fwrite(idx, 4, 3, out); 1481 fwrite(&mat, 2, 1, out); 1482 } 1483 fclose(out); 1484 } 1485 } 1486 } 1487 1488 static void 1489 process_local_ipl(const char *root, const char *rel, FILE *out, struct file_list *fl) 1490 { 1491 FILE *f; 1492 size_t sz; 1493 char *buf; 1494 1495 f = fopen_simple(root, rel); 1496 if (!f) { 1497 return; 1498 } 1499 fseek(f, 0, SEEK_END); 1500 sz = ftell(f); 1501 fseek(f, 0, SEEK_SET); 1502 buf = malloc(sz); 1503 if (fread(buf, 1, sz, f) == sz) { 1504 parse_text_ipl(buf, sz, out, fl); 1505 } 1506 free(buf); 1507 fclose(f); 1508 } 1509 1510 static void 1511 process_gta_dat_ide(const char *root, const char *dat_path, struct file_list *fl) 1512 { 1513 FILE *f; 1514 char line[512]; 1515 char *p; 1516 1517 f = fopen_simple(root, dat_path); 1518 if (!f) { 1519 return; 1520 } 1521 1522 while (fgets(line, sizeof(line), f)) { 1523 p = line; 1524 line[strcspn(line, "\r\n")] = '\0'; 1525 while (*p == ' ' || *p == '\t') { 1526 p++; 1527 } 1528 if (*p == '\0' || *p == '#') { 1529 continue; 1530 } 1531 1532 if (strncasecmp(p, "IDE ", 4) == 0) { 1533 char rel[512]; 1534 char *src = p + 4; 1535 while (*src == ' ' || *src == '\t') { 1536 src++; 1537 } 1538 for (size_t i = 0; i < sizeof(rel) - 1 && src[i]; i++) { 1539 if (src[i] == '\\') { 1540 rel[i] = '/'; 1541 } else { 1542 rel[i] = src[i]; 1543 } 1544 rel[i+1] = '\0'; 1545 } 1546 trim_spaces(rel); 1547 preparse_ide(root, rel, fl); 1548 } 1549 } 1550 fclose(f); 1551 } 1552 1553 static void 1554 process_gta_dat_ipl(const char *root, const char *dat_path, FILE *map_out, struct file_list *fl) 1555 { 1556 FILE *f; 1557 char line[512]; 1558 char *p; 1559 1560 f = fopen_simple(root, dat_path); 1561 if (!f) { 1562 return; 1563 } 1564 1565 while (fgets(line, sizeof(line), f)) { 1566 p = line; 1567 line[strcspn(line, "\r\n")] = '\0'; 1568 while (*p == ' ' || *p == '\t') { 1569 p++; 1570 } 1571 if (*p == '\0' || *p == '#') { 1572 continue; 1573 } 1574 1575 if (strncasecmp(p, "IPL ", 4) == 0) { 1576 char rel[512]; 1577 char *src = p + 4; 1578 while (*src == ' ' || *src == '\t') { 1579 src++; 1580 } 1581 for (size_t i = 0; i < sizeof(rel) - 1 && src[i]; i++) { 1582 if (src[i] == '\\') { 1583 rel[i] = '/'; 1584 } else { 1585 rel[i] = src[i]; 1586 } 1587 rel[i+1] = '\0'; 1588 } 1589 trim_spaces(rel); 1590 process_local_ipl(root, rel, map_out, fl); 1591 } 1592 } 1593 fclose(f); 1594 } 1595 1596 static void 1597 process_water(const char *root) 1598 { 1599 FILE *f, *out; 1600 char line[512], *p, *tok, *save; 1601 char *tokens[32]; 1602 int t_count, i, j, k, collapsed; 1603 uint32_t count; 1604 float limit = 2980.0f; 1605 float ax_min, ax_max, ay_min, ay_max, az; 1606 float bx_min, bx_max, by_min, by_max; 1607 struct water_face *a, *b, *face; 1608 1609 f = fopen_simple(root, "data/water.dat"); 1610 if (f == NULL) { 1611 return; 1612 } 1613 1614 out = fopen("assets/water.bin", "wb"); 1615 if (out == NULL) { 1616 fclose(f); 1617 return; 1618 } 1619 1620 count = 0; 1621 water_face_count = 0; 1622 1623 while (fgets(line, sizeof(line), f)) { 1624 p = line; 1625 while (*p == ' ' || *p == '\t') { 1626 p++; 1627 } 1628 if (*p == '\0' || *p == '#' || *p == '*' || *p == '\r' || 1629 *p == '\n' || strncasecmp(p, "processed", 9) == 0) { 1630 continue; 1631 } 1632 1633 t_count = 0; 1634 tok = strtok_r(p, " \t\r\n", &save); 1635 while (tok && t_count < 32) { 1636 tokens[t_count++] = tok; 1637 tok = strtok_r(NULL, " \t\r\n", &save); 1638 } 1639 1640 if ((t_count == 29 || t_count == 22) && water_face_count < 8192) { 1641 face = &water_db[water_face_count]; 1642 k = atoi(tokens[t_count - 1]); 1643 if (k == 1 || k == 3) { 1644 face->num = t_count == 29 ? 4 : 3; 1645 for (j = 0; j < face->num; j++) { 1646 face->x[j] = strtof(tokens[j * 7 + 0], NULL); 1647 face->y[j] = strtof(tokens[j * 7 + 1], NULL); 1648 1649 face->z[j] = strtof(tokens[j * 7 + 2], NULL); 1650 face->z[j] = roundf(face->z[j] * 10.0f) / 10.0f; 1651 1652 face->u[j] = strtof(tokens[j * 7 + 3], NULL); 1653 face->v[j] = strtof(tokens[j * 7 + 4], NULL); 1654 face->h[j] = strtof(tokens[j * 7 + 6], NULL); 1655 1656 if (face->x[j] > limit) { 1657 face->x[j] = limit; 1658 } 1659 if (face->x[j] < -limit) { 1660 face->x[j] = -limit; 1661 } 1662 if (face->y[j] > limit) { 1663 face->y[j] = limit; 1664 } 1665 if (face->y[j] < -limit) { 1666 face->y[j] = -limit; 1667 } 1668 } 1669 water_face_count++; 1670 } 1671 } 1672 } 1673 1674 for (i = 0; i < water_face_count; i++) { 1675 a = &water_db[i]; 1676 if (a->num == 0) { 1677 continue; 1678 } 1679 1680 ax_min = a->x[0]; 1681 ax_max = a->x[0]; 1682 ay_min = a->y[0]; 1683 ay_max = a->y[0]; 1684 az = a->z[0]; 1685 for (k = 1; k < a->num; k++) { 1686 if (a->x[k] < ax_min) { 1687 ax_min = a->x[k]; 1688 } 1689 if (a->x[k] > ax_max) { 1690 ax_max = a->x[k]; 1691 } 1692 if (a->y[k] < ay_min) { 1693 ay_min = a->y[k]; 1694 } 1695 if (a->y[k] > ay_max) { 1696 ay_max = a->y[k]; 1697 } 1698 } 1699 1700 for (j = 0; j < water_face_count; j++) { 1701 if (i == j) { 1702 continue; 1703 } 1704 b = &water_db[j]; 1705 if (b->num == 0) { 1706 continue; 1707 } 1708 1709 if (fabsf(b->z[0] - az) > 0.01f) { 1710 continue; 1711 } 1712 1713 bx_min = b->x[0]; 1714 bx_max = b->x[0]; 1715 by_min = b->y[0]; 1716 by_max = b->y[0]; 1717 for (k = 1; k < b->num; k++) { 1718 if (b->x[k] < bx_min) { 1719 bx_min = b->x[k]; 1720 } 1721 if (b->x[k] > bx_max) { 1722 bx_max = b->x[k]; 1723 } 1724 if (b->y[k] < by_min) { 1725 by_min = b->y[k]; 1726 } 1727 if (b->y[k] > by_max) { 1728 by_max = b->y[k]; 1729 } 1730 } 1731 1732 if (bx_max > ax_min && bx_min < ax_max && by_max > ay_min && by_min < ay_max) { 1733 if (bx_min < ax_max && bx_max > ax_max && bx_min > ax_min) { 1734 for (k = 0; k < b->num; k++) { 1735 if (fabsf(b->x[k] - bx_min) < 0.1f) { 1736 b->x[k] = ax_max; 1737 } 1738 } 1739 } else if (bx_max > ax_min && bx_min < ax_min && bx_max < ax_max) { 1740 for (k = 0; k < b->num; k++) { 1741 if (fabsf(b->x[k] - bx_max) < 0.1f) { 1742 b->x[k] = ax_min; 1743 } 1744 } 1745 } else if (by_min < ay_max && by_max > ay_max && by_min > ay_min) { 1746 for (k = 0; k < b->num; k++) { 1747 if (fabsf(b->y[k] - by_min) < 0.1f) { 1748 b->y[k] = ay_max; 1749 } 1750 } 1751 } else if (by_max > ay_min && by_min < ay_min && by_max < ay_max) { 1752 for (k = 0; k < b->num; k++) { 1753 if (fabsf(b->y[k] - by_max) < 0.1f) { 1754 b->y[k] = ay_min; 1755 } 1756 } 1757 } 1758 } 1759 } 1760 } 1761 1762 fwrite(&count, sizeof(count), 1, out); 1763 for (i = 0; i < water_face_count; i++) { 1764 face = &water_db[i]; 1765 collapsed = 0; 1766 1767 if (face->num == 4) { 1768 if (fabsf(face->x[0] - face->x[2]) < 0.1f && fabsf(face->y[0] - face->y[2]) < 0.1f) { 1769 collapsed = 1; 1770 } 1771 } else if (face->num == 3) { 1772 if (fabsf(face->x[0] - face->x[1]) < 0.1f && fabsf(face->y[0] - face->y[1]) < 0.1f) { 1773 collapsed = 1; 1774 } 1775 } 1776 1777 if (collapsed == 0) { 1778 fwrite(face, sizeof(struct water_face), 1, out); 1779 count++; 1780 } 1781 } 1782 1783 fseek(out, 0, SEEK_SET); 1784 fwrite(&count, sizeof(count), 1, out); 1785 fclose(out); 1786 fclose(f); 1787 } 1788 1789 static void 1790 mat_translate(struct mat4 *m, float x, float y, float z) 1791 { 1792 mat_identity(m); 1793 m->m[0][3] = x; 1794 m->m[1][3] = y; 1795 m->m[2][3] = z; 1796 } 1797 1798 static void 1799 mat_from_quat(struct mat4 *m, float qx, float qy, float qz, float qw) 1800 { 1801 float len; 1802 1803 qw = -qw; 1804 len = sqrtf(qx * qx + qy * qy + qz * qz + qw * qw); 1805 if (len > 0.0f) { 1806 qx /= len; 1807 qy /= len; 1808 qz /= len; 1809 qw /= len; 1810 } 1811 mat_identity(m); 1812 m->m[0][0] = 1.0f - 2.0f * (qy * qy + qz * qz); 1813 m->m[0][1] = 2.0f * (qx * qy - qz * qw); 1814 m->m[0][2] = 2.0f * (qx * qz + qy * qw); 1815 m->m[1][0] = 2.0f * (qx * qy + qz * qw); 1816 m->m[1][1] = 1.0f - 2.0f * (qx * qx + qz * qz); 1817 m->m[1][2] = 2.0f * (qy * qz - qx * qw); 1818 m->m[2][0] = 2.0f * (qx * qz - qy * qw); 1819 m->m[2][1] = 2.0f * (qy * qz + qx * qw); 1820 m->m[2][2] = 1.0f - 2.0f * (qx * qx + qy * qy); 1821 } 1822 1823 static inline void 1824 mat_transform(float dst[3], float *w_out, const struct mat4 *m, const float v[3]) 1825 { 1826 dst[0] = m->m[0][0] * v[0] + m->m[0][1] * v[1] + m->m[0][2] * v[2] + m->m[0][3]; 1827 dst[1] = m->m[1][0] * v[0] + m->m[1][1] * v[1] + m->m[1][2] * v[2] + m->m[1][3]; 1828 dst[2] = m->m[2][0] * v[0] + m->m[2][1] * v[1] + m->m[2][2] * v[2] + m->m[2][3]; 1829 *w_out = m->m[3][0] * v[0] + m->m[3][1] * v[1] + m->m[3][2] * v[2] + m->m[3][3]; 1830 } 1831 1832 static uint32_t 1833 str_hash(const char *s) 1834 { 1835 uint32_t h; 1836 1837 h = 5381; 1838 while (*s) { 1839 h = ((h << 5) + h) + (unsigned char)*s; 1840 s++; 1841 } 1842 return (h); 1843 } 1844 1845 static void 1846 col_db_insert(struct col_model *cm) 1847 { 1848 uint32_t slot; 1849 1850 slot = str_hash(cm->name) % COL_HASH_SZ; 1851 while (col_hash[slot] != 0) { 1852 slot = (slot + 1) % COL_HASH_SZ; 1853 } 1854 col_hash[slot] = col_db_count; 1855 } 1856 1857 static void 1858 parse_col_data(const uint8_t *data, size_t size) 1859 { 1860 const struct col_header *h; 1861 const uint8_t *base; 1862 const struct raw_col_vertex *verts; 1863 const struct raw_col_face *faces; 1864 const struct raw_col_box *boxes; 1865 struct col_model *cm; 1866 struct col_triangle *t; 1867 size_t pos; 1868 uint32_t total_tris, i, b; 1869 int k; 1870 float x0, y0, z0, x1, y1, z1; 1871 uint8_t surf; 1872 float p[8][3]; 1873 static const int box_idx[12][3] = { 1874 {0, 1, 2}, {0, 2, 3}, {4, 6, 5}, {4, 7, 6}, 1875 {0, 4, 5}, {0, 5, 1}, {3, 2, 6}, {3, 6, 7}, 1876 {0, 3, 7}, {0, 7, 4}, {1, 5, 6}, {1, 6, 2} 1877 }; 1878 1879 pos = 0; 1880 while (pos + sizeof(struct col_header) <= size) { 1881 h = (const struct col_header *)(data + pos); 1882 if (memcmp(h->magic, "COL2", 4) != 0 && 1883 memcmp(h->magic, "COL3", 4) != 0 && 1884 memcmp(h->magic, "COLL", 4) != 0) { 1885 break; 1886 } 1887 if (col_db_count >= MAX_COL_MODELS) { 1888 break; 1889 } 1890 1891 cm = &col_db[col_db_count]; 1892 strncpy(cm->name, h->model_name, sizeof(cm->name) - 1); 1893 cm->name[sizeof(cm->name) - 1] = '\0'; 1894 trim_spaces(cm->name); 1895 to_lower_str(cm->name); 1896 1897 total_tris = h->num_faces + (h->num_boxes * 12); 1898 if (total_tris > 0) { 1899 cm->tris = malloc(total_tris * sizeof(struct col_triangle)); 1900 if (!cm->tris) { 1901 break; 1902 } 1903 cm->num_tris = 0; 1904 base = data + pos + 4; 1905 1906 if (h->num_faces > 0 && h->vertices_offset && h->faces_offset) { 1907 verts = (const struct raw_col_vertex *)(base + h->vertices_offset); 1908 faces = (const struct raw_col_face *)(base + h->faces_offset); 1909 for (i = 0; i < h->num_faces; i++) { 1910 t = &cm->tris[cm->num_tris++]; 1911 t->v0[0] = verts[faces[i].a].x / 128.0f; 1912 t->v0[1] = verts[faces[i].a].y / 128.0f; 1913 t->v0[2] = verts[faces[i].a].z / 128.0f; 1914 1915 t->v1[0] = verts[faces[i].b].x / 128.0f; 1916 t->v1[1] = verts[faces[i].b].y / 128.0f; 1917 t->v1[2] = verts[faces[i].b].z / 128.0f; 1918 1919 t->v2[0] = verts[faces[i].c].x / 128.0f; 1920 t->v2[1] = verts[faces[i].c].y / 128.0f; 1921 t->v2[2] = verts[faces[i].c].z / 128.0f; 1922 1923 t->surface = faces[i].surface; 1924 } 1925 } 1926 1927 if (h->num_boxes > 0 && h->boxes_offset) { 1928 boxes = (const struct raw_col_box *)(base + h->boxes_offset); 1929 for (b = 0; b < h->num_boxes; b++) { 1930 x0 = boxes[b].min[0]; 1931 y0 = boxes[b].min[1]; 1932 z0 = boxes[b].min[2]; 1933 x1 = boxes[b].max[0]; 1934 y1 = boxes[b].max[1]; 1935 z1 = boxes[b].max[2]; 1936 surf = boxes[b].surface; 1937 1938 p[0][0] = x0; p[0][1] = y0; p[0][2] = z0; 1939 p[1][0] = x1; p[1][1] = y0; p[1][2] = z0; 1940 p[2][0] = x1; p[2][1] = y1; p[2][2] = z0; 1941 p[3][0] = x0; p[3][1] = y1; p[3][2] = z0; 1942 p[4][0] = x0; p[4][1] = y0; p[4][2] = z1; 1943 p[5][0] = x1; p[5][1] = y0; p[5][2] = z1; 1944 p[6][0] = x1; p[6][1] = y1; p[6][2] = z1; 1945 p[7][0] = x0; p[7][1] = y1; p[7][2] = z1; 1946 1947 for (k = 0; k < 12; k++) { 1948 t = &cm->tris[cm->num_tris++]; 1949 memcpy(t->v0, p[box_idx[k][0]], sizeof(float) * 3); 1950 memcpy(t->v1, p[box_idx[k][1]], sizeof(float) * 3); 1951 memcpy(t->v2, p[box_idx[k][2]], sizeof(float) * 3); 1952 t->surface = surf; 1953 } 1954 } 1955 } 1956 col_db_count++; 1957 col_db_insert(cm); 1958 } 1959 pos += 8 + h->size; 1960 } 1961 } 1962 1963 static void 1964 process_gta_dat_col(const char *root, const char *dat_path) 1965 { 1966 FILE *f; 1967 FILE *cf; 1968 char line[512]; 1969 char rel[512]; 1970 char *p; 1971 char *src; 1972 uint8_t *buf; 1973 size_t sz, i; 1974 1975 f = fopen_simple(root, dat_path); 1976 if (!f) { 1977 return; 1978 } 1979 1980 while (fgets(line, sizeof(line), f)) { 1981 p = line; 1982 while (*p == ' ' || *p == '\t') { 1983 p++; 1984 } 1985 if (strncasecmp(p, "COLFILE ", 8) == 0) { 1986 src = p + 8; 1987 while (*src == ' ' || *src == '\t') { 1988 src++; 1989 } 1990 while (*src >= '0' && *src <= '9') { 1991 src++; 1992 } 1993 while (*src == ' ' || *src == '\t') { 1994 src++; 1995 } 1996 for (i = 0; i < sizeof(rel) - 1 && src[i]; i++) { 1997 if (src[i] == '\\') { 1998 rel[i] = '/'; 1999 } else { 2000 rel[i] = src[i]; 2001 } 2002 rel[i + 1] = '\0'; 2003 } 2004 trim_spaces(rel); 2005 2006 cf = fopen_simple(root, rel); 2007 if (cf) { 2008 fseek(cf, 0, SEEK_END); 2009 sz = ftell(cf); 2010 fseek(cf, 0, SEEK_SET); 2011 buf = malloc(sz); 2012 if (buf && fread(buf, 1, sz, cf) == sz) { 2013 parse_col_data(buf, sz); 2014 } 2015 free(buf); 2016 fclose(cf); 2017 } 2018 } 2019 } 2020 fclose(f); 2021 } 2022 2023 static struct col_model * 2024 col_lookup(const char *name) 2025 { 2026 uint32_t slot; 2027 int idx; 2028 2029 slot = str_hash(name) % COL_HASH_SZ; 2030 while (col_hash[slot] != 0) { 2031 idx = col_hash[slot] - 1; 2032 if (strcmp(col_db[idx].name, name) == 0) { 2033 return (&col_db[idx]); 2034 } 2035 slot = (slot + 1) % COL_HASH_SZ; 2036 } 2037 return (NULL); 2038 } 2039 2040 static void 2041 instantiate_collision(const char *model_name, const struct mat4 *world_mat) 2042 { 2043 struct col_model *cm; 2044 struct col_triangle wt; 2045 struct col_cell *c; 2046 float w, min_x, max_x, min_z, max_z, e1[3], e2[3], len; 2047 uint32_t i; 2048 int gx0, gx1, gz0, gz1, gx, gz; 2049 2050 cm = col_lookup(model_name); 2051 if (!cm || cm->num_tris == 0) { 2052 return; 2053 } 2054 2055 for (i = 0; i < cm->num_tris; i++) { 2056 mat_transform(wt.v0, &w, world_mat, cm->tris[i].v0); 2057 mat_transform(wt.v1, &w, world_mat, cm->tris[i].v1); 2058 mat_transform(wt.v2, &w, world_mat, cm->tris[i].v2); 2059 wt.surface = cm->tris[i].surface; 2060 2061 e1[0] = wt.v1[0] - wt.v0[0]; 2062 e1[1] = wt.v1[1] - wt.v0[1]; 2063 e1[2] = wt.v1[2] - wt.v0[2]; 2064 2065 e2[0] = wt.v2[0] - wt.v0[0]; 2066 e2[1] = wt.v2[1] - wt.v0[1]; 2067 e2[2] = wt.v2[2] - wt.v0[2]; 2068 2069 wt.norm[0] = e1[1] * e2[2] - e1[2] * e2[1]; 2070 wt.norm[1] = e1[2] * e2[0] - e1[0] * e2[2]; 2071 wt.norm[2] = e1[0] * e2[1] - e1[1] * e2[0]; 2072 2073 len = sqrtf(wt.norm[0] * wt.norm[0] + 2074 wt.norm[1] * wt.norm[1] + 2075 wt.norm[2] * wt.norm[2]); 2076 if (len > 1e-6f) { 2077 wt.norm[0] /= len; 2078 wt.norm[1] /= len; 2079 wt.norm[2] /= len; 2080 } else { 2081 wt.norm[0] = 0.0f; 2082 wt.norm[1] = 1.0f; 2083 wt.norm[2] = 0.0f; 2084 } 2085 2086 min_x = fminf(wt.v0[0], fminf(wt.v1[0], wt.v2[0])); 2087 max_x = fmaxf(wt.v0[0], fmaxf(wt.v1[0], wt.v2[0])); 2088 min_z = fminf(wt.v0[2], fminf(wt.v1[2], wt.v2[2])); 2089 max_z = fmaxf(wt.v0[2], fmaxf(wt.v1[2], wt.v2[2])); 2090 2091 gx0 = (int)((min_x - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2092 gx1 = (int)((max_x - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2093 gz0 = (int)((min_z - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2094 gz1 = (int)((max_z - MAP_MIN) / ((MAP_MAX - MAP_MIN) / GRID_SZ)); 2095 2096 if (gx0 < 0) gx0 = 0; 2097 if (gx1 >= GRID_SZ) gx1 = GRID_SZ - 1; 2098 if (gz0 < 0) gz0 = 0; 2099 if (gz1 >= GRID_SZ) gz1 = GRID_SZ - 1; 2100 2101 for (gz = gz0; gz <= gz1; gz++) { 2102 for (gx = gx0; gx <= gx1; gx++) { 2103 c = &world_col_grid[gx][gz]; 2104 if (c->count >= c->capacity) { 2105 c->capacity = c->capacity == 0 ? 64 : c->capacity * 2; 2106 c->tris = realloc(c->tris, c->capacity * sizeof(struct col_triangle)); 2107 } 2108 c->tris[c->count++] = wt; 2109 } 2110 } 2111 } 2112 } 2113 2114 static void 2115 bake_world_collision(void) 2116 { 2117 FILE *f; 2118 char line[512]; 2119 char name[NAME_SZ]; 2120 char *p; 2121 struct mat4 rot, trans, sa2gl, world; 2122 int in_inst, id, interior, lod, time_on, time_off; 2123 float px, py, pz, qx, qy, qz, qw; 2124 2125 f = fopen("assets/map.ipl", "r"); 2126 if (!f) { 2127 return; 2128 } 2129 2130 in_inst = 0; 2131 while (fgets(line, sizeof(line), f)) { 2132 p = line; 2133 while (*p == ' ' || *p == '\t') { 2134 p++; 2135 } 2136 if (*p == '\0' || *p == '#') { 2137 continue; 2138 } 2139 if (strncasecmp(p, "inst", 4) == 0 || strncasecmp(p, "tobj", 4) == 0) { 2140 in_inst = 1; 2141 continue; 2142 } 2143 if (strncasecmp(p, "end", 3) == 0) { 2144 in_inst = 0; 2145 continue; 2146 } 2147 if (in_inst) { 2148 lod = -1; 2149 time_on = 0; 2150 time_off = 0; 2151 if (sscanf(p, "%d, %23[^,], %d, %f, %f, %f, %f, %f, %f, %f, %d, %d, %d", 2152 &id, name, &interior, &px, &py, &pz, &qx, &qy, &qz, &qw, 2153 &lod, &time_on, &time_off) >= 10) { 2154 trim_spaces(name); 2155 to_lower_str(name); 2156 2157 mat_from_quat(&rot, qx, qy, qz, qw); 2158 mat_translate(&trans, px, py, pz); 2159 mat_mul(&world, &trans, &rot); 2160 2161 memset(&sa2gl, 0, sizeof(sa2gl)); 2162 sa2gl.m[0][0] = 1.0f; 2163 sa2gl.m[1][2] = 1.0f; 2164 sa2gl.m[2][1] = 1.0f; 2165 sa2gl.m[3][3] = 1.0f; 2166 mat_mul(&world, &sa2gl, &world); 2167 2168 instantiate_collision(name, &world); 2169 } 2170 } 2171 } 2172 fclose(f); 2173 } 2174 2175 static void 2176 save_collision_bin(void) 2177 { 2178 FILE *out; 2179 uint32_t cnt; 2180 int gx, gz; 2181 2182 out = fopen("assets/collision.bin", "wb"); 2183 if (!out) { 2184 return; 2185 } 2186 2187 for (gz = 0; gz < GRID_SZ; gz++) { 2188 for (gx = 0; gx < GRID_SZ; gx++) { 2189 cnt = world_col_grid[gx][gz].count; 2190 fwrite(&cnt, sizeof(uint32_t), 1, out); 2191 if (cnt > 0) { 2192 fwrite(world_col_grid[gx][gz].tris, 2193 sizeof(struct col_triangle), cnt, out); 2194 } 2195 } 2196 } 2197 fclose(out); 2198 } 2199 2200 static void 2201 process_timecyc(const char *root) 2202 { 2203 FILE *f; 2204 FILE *out; 2205 char line[512]; 2206 struct timecyc_entry snaps[32 * 8]; 2207 int w_idx, s_idx, total_weathers; 2208 char *p; 2209 2210 f = fopen_simple(root, "data/timecycp.dat"); 2211 if (!f) { 2212 f = fopen_simple(root, "data/timecyc.dat"); 2213 } 2214 if (!f) { 2215 return; 2216 } 2217 2218 out = fopen("assets/timecyc.bin", "wb"); 2219 if (!out) { 2220 fclose(f); 2221 return; 2222 } 2223 2224 memset(snaps, 0, sizeof(snaps)); 2225 w_idx = 0; 2226 s_idx = 0; 2227 total_weathers = 0; 2228 2229 while (fgets(line, sizeof(line), f)) { 2230 p = line; 2231 while (*p == ' ' || *p == '\t') { 2232 p++; 2233 } 2234 if (*p == '\0' || *p == '\n' || *p == '\r' || 2235 strncmp(p, "//", 2) == 0) { 2236 continue; 2237 } 2238 2239 char *tok, *save; 2240 char *tokens[64]; 2241 int t = 0; 2242 2243 tok = strtok_r(p, " \t\r\n", &save); 2244 while (tok && t < 64) { 2245 tokens[t++] = tok; 2246 tok = strtok_r(NULL, " \t\r\n", &save); 2247 } 2248 2249 if (t >= 40) { 2250 struct timecyc_entry *e = &snaps[w_idx * 8 + s_idx]; 2251 e->amb[0] = atoi(tokens[3]); 2252 e->amb[1] = atoi(tokens[4]); 2253 e->amb[2] = atoi(tokens[5]); 2254 e->dir[0] = atoi(tokens[6]); 2255 e->dir[1] = atoi(tokens[7]); 2256 e->dir[2] = atoi(tokens[8]); 2257 e->sky_top[0] = atoi(tokens[9]); 2258 e->sky_top[1] = atoi(tokens[10]); 2259 e->sky_top[2] = atoi(tokens[11]); 2260 e->sky_bot[0] = atoi(tokens[12]); 2261 e->sky_bot[1] = atoi(tokens[13]); 2262 e->sky_bot[2] = atoi(tokens[14]); 2263 e->far_clp = strtof(tokens[27], NULL); 2264 e->fog_st = strtof(tokens[28], NULL); 2265 e->water[0] = atoi(tokens[36]); 2266 e->water[1] = atoi(tokens[37]); 2267 e->water[2] = atoi(tokens[38]); 2268 e->water[3] = (t >= 40) ? atoi(tokens[39]) : 255; 2269 2270 s_idx++; 2271 if (s_idx == 8) { 2272 s_idx = 0; 2273 w_idx++; 2274 if (w_idx > total_weathers) { 2275 total_weathers = w_idx; 2276 } 2277 if (w_idx >= 32) { 2278 break; 2279 } 2280 } 2281 } 2282 } 2283 fwrite(&total_weathers, sizeof(int), 1, out); 2284 fwrite(snaps, sizeof(struct timecyc_entry), total_weathers * 8, out); 2285 fclose(out); 2286 fclose(f); 2287 } 2288 2289 static void * 2290 build_worker(void *arg) 2291 { 2292 struct thread_arg *ta; 2293 uint32_t i; 2294 2295 ta = arg; 2296 ta->arena.size = 128 * 1024 * 1024; 2297 ta->arena.mem = malloc(ta->arena.size); 2298 2299 for (i = ta->start; i < ta->end; i++) { 2300 char n[NAME_SZ + 1]; 2301 size_t j; 2302 for (j = 0; j < sizeof(ta->entries[i].name) && ta->entries[i].name[j]; j++) { 2303 n[j] = tolower((unsigned char)ta->entries[i].name[j]); 2304 } 2305 n[j] = '\0'; 2306 2307 if (list_has(ta->fl, n)) { 2308 uint32_t size = ta->entries[i].size * 2048; 2309 const uint8_t *buf = ta->img_data + ta->entries[i].offset * 2048; 2310 char *ext = strrchr(n, '.'); 2311 if (ext) { 2312 *ext = '\0'; 2313 } 2314 2315 ta->arena.pos = 0; 2316 2317 if (strstr(ta->entries[i].name, ".dff") || strstr(ta->entries[i].name, ".DFF")) { 2318 convert_dff(buf, size, n, &ta->arena); 2319 } else if (strstr(ta->entries[i].name, ".txd") || strstr(ta->entries[i].name, ".TXD")) { 2320 convert_txd(buf, size, n, &ta->arena); 2321 } 2322 } 2323 } 2324 free(ta->arena.mem); 2325 return (NULL); 2326 } 2327 2328 static void 2329 tar_add_file(FILE *tar, const char *path, const char *tar_name) 2330 { 2331 FILE *src; 2332 size_t sz, n, padding; 2333 struct tar_header th; 2334 unsigned int sum; 2335 uint8_t *p; 2336 char buf[4096]; 2337 2338 src = fopen(path, "rb"); 2339 if (!src) { 2340 return; 2341 } 2342 2343 fseek(src, 0, SEEK_END); 2344 sz = ftell(src); 2345 fseek(src, 0, SEEK_SET); 2346 2347 memset(&th, 0, sizeof(th)); 2348 strncpy(th.name, tar_name, sizeof(th.name) - 1); 2349 snprintf(th.mode, sizeof(th.mode), "%07o", 0644); 2350 snprintf(th.size, sizeof(th.size), "%011lo", (unsigned long)sz); 2351 snprintf(th.magic, sizeof(th.magic), "ustar"); 2352 2353 /* Simple checksum calculation. */ 2354 memset(th.chksum, ' ', 8); 2355 sum = 0; 2356 p = (uint8_t *)&th; 2357 for (size_t i = 0; i < sizeof(th); i++) { 2358 sum += p[i]; 2359 } 2360 snprintf(th.chksum, sizeof(th.chksum), "%06o", sum); 2361 2362 fwrite(&th, sizeof(th), 1, tar); 2363 2364 while ((n = fread(buf, 1, sizeof(buf), src)) > 0) { 2365 fwrite(buf, 1, n, tar); 2366 } 2367 fclose(src); 2368 2369 padding = (512 - (sz % 512)) % 512; 2370 if (padding > 0) { 2371 char pad[512] = {0}; 2372 fwrite(pad, 1, padding, tar); 2373 } 2374 } 2375 2376 static void 2377 pack_directory(FILE *tar, const char *dir_path, const char *prefix) 2378 { 2379 DIR *dir; 2380 struct dirent *de; 2381 char path[1024]; 2382 char tar_name[1024]; 2383 struct stat st; 2384 2385 dir = opendir(dir_path); 2386 if (!dir) { 2387 return; 2388 } 2389 while ((de = readdir(dir))) { 2390 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) { 2391 continue; 2392 } 2393 snprintf(path, sizeof(path), "%s/%s", dir_path, de->d_name); 2394 snprintf(tar_name, sizeof(tar_name), "%s%s", prefix, de->d_name); 2395 2396 if (stat(path, &st) == 0) { 2397 if (S_ISDIR(st.st_mode)) { 2398 char new_prefix[1024]; 2399 snprintf(new_prefix, sizeof(new_prefix), "%s/", tar_name); 2400 pack_directory(tar, path, new_prefix); 2401 } else { 2402 tar_add_file(tar, path, tar_name); 2403 } 2404 } 2405 } 2406 closedir(dir); 2407 } 2408 2409 static void 2410 process_img_file(const char *root, const char *rel_path, struct file_list *fl, int num_threads, pthread_t *threads, struct thread_arg *args) 2411 { 2412 char img_path[1024]; 2413 int img_fd; 2414 struct stat st; 2415 uint8_t *img_data; 2416 struct img_header *hdr; 2417 struct img_entry *entries; 2418 uint32_t chunk; 2419 int i; 2420 2421 if (!resolve_simple(root, rel_path, img_path, sizeof(img_path))) { 2422 warnx("failed to resolve %s", rel_path); 2423 return; 2424 } 2425 2426 img_fd = open(img_path, O_RDONLY); 2427 if (img_fd < 0) { 2428 warn("failed to open %s", rel_path); 2429 return; 2430 } 2431 2432 if (fstat(img_fd, &st) < 0) { 2433 close(img_fd); 2434 return; 2435 } 2436 2437 img_data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, img_fd, 0); 2438 if (img_data == MAP_FAILED) { 2439 close(img_fd); 2440 return; 2441 } 2442 2443 hdr = (struct img_header *)img_data; 2444 if (memcmp(hdr->magic, "VER2", 4) != 0) { 2445 munmap(img_data, st.st_size); 2446 close(img_fd); 2447 return; 2448 } 2449 entries = (struct img_entry *)(img_data + sizeof(struct img_header)); 2450 2451 printf("build: processing %s (%u entries)...\n", rel_path, hdr->entries); 2452 2453 chunk = hdr->entries / num_threads; 2454 for (i = 0; i < num_threads; i++) { 2455 args[i].img_data = img_data; 2456 args[i].entries = entries; 2457 args[i].start = i * chunk; 2458 args[i].end = (i == num_threads - 1) ? hdr->entries : (i + 1) * chunk; 2459 args[i].fl = fl; 2460 pthread_create(&threads[i], NULL, build_worker, &args[i]); 2461 } 2462 2463 for (i = 0; i < num_threads; i++) { 2464 pthread_join(threads[i], NULL); 2465 } 2466 2467 munmap(img_data, st.st_size); 2468 close(img_fd); 2469 } 2470 2471 int 2472 main(int argc, char *argv[]) 2473 { 2474 struct file_list fl; 2475 struct arena shared_arena; 2476 FILE *map_out; 2477 char img_path[1024]; 2478 int img_fd; 2479 struct stat st; 2480 uint8_t *img_data; 2481 struct img_header *hdr; 2482 struct img_entry *entries; 2483 struct file_list missing_fl; 2484 int num_threads; 2485 pthread_t *threads; 2486 struct thread_arg *args; 2487 FILE *tar; 2488 2489 if (argc < 2) { 2490 return (1); 2491 } 2492 2493 mkdir("assets", 0777); 2494 mkdir("assets/models", 0777); 2495 mkdir("assets/textures", 0777); 2496 2497 scan_existing_assets(); 2498 memset(&fl, 0, sizeof(fl)); 2499 2500 map_out = fopen("assets/map.ipl", "w"); 2501 if (!map_out) { 2502 err(1, "failed to create map.ipl"); 2503 } 2504 2505 process_gta_dat_ide(argv[1], "data/default.dat", &fl); 2506 process_gta_dat_ide(argv[1], "data/gta.dat", &fl); 2507 2508 for (int i = 0; i < (int)(sizeof(special_actors) / sizeof(special_actors[0])); i++) { 2509 char d_name[64], t_name[64]; 2510 snprintf(d_name, sizeof(d_name), "%s.dff", special_actors[i].model); 2511 snprintf(t_name, sizeof(t_name), "%s.txd", special_actors[i].txd); 2512 list_add(&fl, d_name); 2513 list_add(&fl, t_name); 2514 } 2515 2516 for (int i = 0; i < 313; i++) { 2517 if (skin_names[i][0] != '\0') { 2518 char d_name[64], t_name[64]; 2519 snprintf(d_name, sizeof(d_name), "%s.dff", skin_names[i]); 2520 snprintf(t_name, sizeof(t_name), "%s.txd", skin_names[i]); 2521 list_add(&fl, d_name); 2522 list_add(&fl, t_name); 2523 } 2524 } 2525 2526 process_gta_dat_ipl(argv[1], "data/default.dat", map_out, &fl); 2527 process_gta_dat_ipl(argv[1], "data/gta.dat", map_out, &fl); 2528 2529 if (!resolve_simple(argv[1], "models/gta3.img", img_path, sizeof(img_path))) { 2530 errx(1, "failed to resolve gta3.img"); 2531 } 2532 2533 img_fd = open(img_path, O_RDONLY); 2534 if (img_fd < 0) { 2535 err(1, "failed to open gta3.img"); 2536 } 2537 2538 fstat(img_fd, &st); 2539 img_data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, img_fd, 0); 2540 if (img_data == MAP_FAILED) { 2541 err(1, "mmap failed"); 2542 } 2543 2544 hdr = (struct img_header *)img_data; 2545 if (memcmp(hdr->magic, "VER2", 4) != 0) { 2546 errx(1, "invalid img"); 2547 } 2548 entries = (struct img_entry *)(img_data + sizeof(struct img_header)); 2549 2550 for (uint32_t i = 0; i < hdr->entries; i++) { 2551 char name_lower[NAME_SZ + 1]; 2552 size_t j; 2553 for (j = 0; j < sizeof(entries[i].name) && entries[i].name[j]; j++) { 2554 name_lower[j] = tolower((unsigned char)entries[i].name[j]); 2555 } 2556 name_lower[j] = '\0'; 2557 2558 if (strstr(name_lower, ".ipl") != NULL) { 2559 uint32_t size = entries[i].size * 2048; 2560 const uint8_t *buf = img_data + entries[i].offset * 2048; 2561 if (size >= 4 && memcmp(buf, "bnry", 4) == 0) { 2562 parse_binary_ipl(buf, size, map_out, &fl); 2563 } else { 2564 parse_text_ipl((char *)buf, size, map_out, &fl); 2565 } 2566 } 2567 2568 if (strstr(name_lower, ".col") != NULL) { 2569 uint32_t size = entries[i].size * 2048; 2570 const uint8_t *buf = img_data + entries[i].offset * 2048; 2571 parse_col_data(buf, size); 2572 } 2573 } 2574 fclose(map_out); 2575 2576 memset(&missing_fl, 0, sizeof(missing_fl)); 2577 for (int i = 0; i < fl.count; i++) { 2578 if (!asset_exists(fl.names[i])) { 2579 list_add(&missing_fl, fl.names[i]); 2580 } 2581 } 2582 printf("Total map files: %d, missing/rebuilding: %d\n", fl.count, missing_fl.count); 2583 fl = missing_fl; 2584 2585 munmap(img_data, st.st_size); 2586 close(img_fd); 2587 2588 shared_arena.size = 128 * 1024 * 1024; 2589 shared_arena.mem = malloc(shared_arena.size); 2590 process_particle_txd(argv[1], &shared_arena); 2591 free(shared_arena.mem); 2592 2593 process_water(argv[1]); 2594 process_timecyc(argv[1]); 2595 2596 num_threads = sysconf(_SC_NPROCESSORS_ONLN); 2597 if (num_threads < 1) { 2598 num_threads = 4; 2599 } 2600 2601 threads = malloc(num_threads * sizeof(pthread_t)); 2602 args = malloc(num_threads * sizeof(struct thread_arg)); 2603 2604 process_img_file(argv[1], "models/gta3.img", &fl, num_threads, threads, args); 2605 2606 process_img_file(argv[1], "models/gta_int.img", &fl, num_threads, threads, args); 2607 2608 process_img_file(argv[1], "models/cutscene.img", &fl, num_threads, threads, args); 2609 process_gta_dat_col(argv[1], "data/default.dat"); 2610 process_gta_dat_col(argv[1], "data/gta.dat"); 2611 printf("Loaded %d collision models into memory\n", col_db_count); 2612 bake_world_collision(); 2613 save_collision_bin(); 2614 2615 free(threads); 2616 free(args); 2617 2618 printf("Packing assets.tar...\n"); 2619 tar = fopen("assets.tar", "wb"); 2620 if (tar) { 2621 pack_directory(tar, "assets", "assets/"); 2622 char empty[1024] = {0}; 2623 fwrite(empty, 1, sizeof(empty), tar); 2624 fclose(tar); 2625 system("rm -rf assets"); 2626 } 2627 2628 return (0); 2629 }