Changeset 5522 for trunk/tools/wrc/newstruc.c
- Timestamp:
- Apr 16, 2001, 7:11:03 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/wrc/newstruc.c
r3426 r5522 13 13 #include <string.h> 14 14 #include <assert.h> 15 #include <ctype.h> 15 16 16 17 #include "wrc.h" … … 18 19 #include "utils.h" 19 20 #include "parser.h" 21 22 #include "wingdi.h" /* for BITMAPINFOHEADER */ 20 23 21 24 /* Generate new_* functions that have no parameters (NOTE: no ';') */ … … 41 44 __NEW_STRUCT_FUNC(string) 42 45 __NEW_STRUCT_FUNC(toolbar_item) 46 __NEW_STRUCT_FUNC(ani_any) 43 47 44 48 /* New instances for all types of structures */ … … 145 149 } 146 150 else 147 fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_ PURE;151 fnt->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; 148 152 return fnt; 149 153 } 154 155 fontdir_t *new_fontdir(raw_data_t *rd, int *memopt) 156 { 157 fontdir_t *fnd = (fontdir_t *)xmalloc(sizeof(fontdir_t)); 158 fnd->data = rd; 159 if(memopt) 160 { 161 fnd->memopt = *memopt; 162 free(memopt); 163 } 164 else 165 fnd->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; 166 return fnd; 167 } 168 169 170 /* 171 * Convert bitmaps to proper endian 172 */ 173 static void convert_bitmap_swap_v3(BITMAPINFOHEADER *bih) 174 { 175 bih->biSize = BYTESWAP_DWORD(bih->biSize); 176 bih->biWidth = BYTESWAP_DWORD(bih->biWidth); 177 bih->biHeight = BYTESWAP_DWORD(bih->biHeight); 178 bih->biPlanes = BYTESWAP_WORD(bih->biPlanes); 179 bih->biBitCount = BYTESWAP_WORD(bih->biBitCount); 180 bih->biCompression = BYTESWAP_DWORD(bih->biCompression); 181 bih->biSizeImage = BYTESWAP_DWORD(bih->biSizeImage); 182 bih->biXPelsPerMeter = BYTESWAP_DWORD(bih->biXPelsPerMeter); 183 bih->biYPelsPerMeter = BYTESWAP_DWORD(bih->biYPelsPerMeter); 184 bih->biClrUsed = BYTESWAP_DWORD(bih->biClrUsed); 185 bih->biClrImportant = BYTESWAP_DWORD(bih->biClrImportant); 186 } 187 188 static void convert_bitmap_swap_v4(BITMAPV4HEADER *b4h) 189 { 190 convert_bitmap_swap_v3((BITMAPINFOHEADER *)b4h); 191 b4h->bV4RedMask = BYTESWAP_DWORD(b4h->bV4RedMask); 192 b4h->bV4GreenMask = BYTESWAP_DWORD(b4h->bV4GreenMask); 193 b4h->bV4BlueMask = BYTESWAP_DWORD(b4h->bV4BlueMask); 194 b4h->bV4AlphaMask = BYTESWAP_DWORD(b4h->bV4AlphaMask); 195 b4h->bV4CSType = BYTESWAP_DWORD(b4h->bV4CSType); 196 b4h->bV4Endpoints.ciexyzRed.ciexyzX = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzX); 197 b4h->bV4Endpoints.ciexyzRed.ciexyzY = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzY); 198 b4h->bV4Endpoints.ciexyzRed.ciexyzZ = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzRed.ciexyzZ); 199 b4h->bV4Endpoints.ciexyzGreen.ciexyzX = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzX); 200 b4h->bV4Endpoints.ciexyzGreen.ciexyzY = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzY); 201 b4h->bV4Endpoints.ciexyzGreen.ciexyzZ = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzGreen.ciexyzZ); 202 b4h->bV4Endpoints.ciexyzBlue.ciexyzX = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzX); 203 b4h->bV4Endpoints.ciexyzBlue.ciexyzY = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzY); 204 b4h->bV4Endpoints.ciexyzBlue.ciexyzZ = BYTESWAP_DWORD(b4h->bV4Endpoints.ciexyzBlue.ciexyzZ); 205 b4h->bV4GammaRed = BYTESWAP_DWORD(b4h->bV4GammaRed); 206 b4h->bV4GammaGreen = BYTESWAP_DWORD(b4h->bV4GammaGreen); 207 b4h->bV4GammaBlue = BYTESWAP_DWORD(b4h->bV4GammaBlue); 208 } 209 210 #define FL_SIGBE 0x01 211 #define FL_SIZEBE 0x02 212 #define FL_V4 0x04 213 static int convert_bitmap(char *data, int size) 214 { 215 BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)data; 216 BITMAPV4HEADER *b4h = (BITMAPV4HEADER *)data; 217 int type = 0; 218 #ifdef WORDS_BIGENDIAN 219 DWORD bisizel = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER)); 220 DWORD b4sizel = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER)); 221 DWORD bisizeb = sizeof(BITMAPINFOHEADER); 222 DWORD b4sizeb = sizeof(BITMAPV4HEADER); 223 #else 224 DWORD bisizel = sizeof(BITMAPINFOHEADER); 225 DWORD b4sizel = sizeof(BITMAPV4HEADER); 226 DWORD bisizeb = BYTESWAP_DWORD(sizeof(BITMAPINFOHEADER)); 227 DWORD b4sizeb = BYTESWAP_DWORD(sizeof(BITMAPV4HEADER)); 228 #endif 229 230 if(data[0] == 'B' && data[1] == 'M') 231 { 232 /* Little endian signature */ 233 bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER)); 234 b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER)); 235 } 236 else if(data[0] == 'M' && data[1] == 'B') 237 { 238 type |= FL_SIGBE; /* Big endian signature */ 239 bih = (BITMAPINFOHEADER *)(data + sizeof(BITMAPFILEHEADER)); 240 b4h = (BITMAPV4HEADER *)(data + sizeof(BITMAPFILEHEADER)); 241 } 242 243 if(bih->biSize == bisizel) 244 { 245 /* Little endian */ 246 } 247 else if(bih->biSize == b4sizel) 248 { 249 type |= FL_V4; 250 } 251 else if(bih->biSize == bisizeb) 252 { 253 type |= FL_SIZEBE; 254 } 255 else if(bih->biSize == b4sizeb) 256 { 257 type |= FL_SIZEBE | FL_V4; 258 } 259 #ifdef __EMX__ 260 else if(bih->biSize == sizeof(BITMAPCOREHEADER)) 261 { 262 /* Little endian */ 263 } 264 #endif 265 else 266 type = -1; 267 268 switch(type) 269 { 270 default: 271 break; 272 case FL_SIZEBE: 273 case FL_SIZEBE | FL_V4: 274 yywarning("Bitmap v%c signature little-endian, but size big-endian", type & FL_V4 ? '4' : '3'); 275 break; 276 case FL_SIGBE: 277 case FL_SIGBE | FL_V4: 278 yywarning("Bitmap v%c signature big-endian, but size little-endian", type & FL_V4 ? '4' : '3'); 279 break; 280 case -1: 281 yyerror("Invalid bitmap format"); 282 break; 283 } 284 285 switch(byteorder) 286 { 287 #ifdef WORDS_BIGENDIAN 288 default: 289 #endif 290 case WRC_BO_BIG: 291 if(!(type & FL_SIZEBE)) 292 { 293 if(type & FL_V4) 294 convert_bitmap_swap_v4(b4h); 295 else 296 convert_bitmap_swap_v3(bih); 297 } 298 break; 299 #ifndef WORDS_BIGENDIAN 300 default: 301 #endif 302 case WRC_BO_LITTLE: 303 if(type & FL_SIZEBE) 304 { 305 if(type & FL_V4) 306 convert_bitmap_swap_v4(b4h); 307 else 308 convert_bitmap_swap_v3(bih); 309 } 310 break; 311 } 312 313 if(size && (void *)data != (void *)bih) 314 { 315 /* We have the fileheader still attached, remove it */ 316 memmove(data, data+sizeof(BITMAPFILEHEADER), size - sizeof(BITMAPFILEHEADER)); 317 return sizeof(BITMAPFILEHEADER); 318 } 319 return 0; 320 } 321 #undef FL_SIGBE 322 #undef FL_SIZEBE 323 #undef FL_V4 324 325 /* 326 * Cursor and icon splitter functions used when allocating 327 * cursor- and icon-groups. 328 */ 329 typedef struct { 330 language_t lan; 331 int id; 332 } id_alloc_t; 333 334 static int get_new_id(id_alloc_t **list, int *n, language_t *lan) 335 { 336 int i; 337 assert(lan != NULL); 338 assert(list != NULL); 339 assert(n != NULL); 340 341 if(!*list) 342 { 343 *list = (id_alloc_t *)xmalloc(sizeof(id_alloc_t)); 344 *n = 1; 345 (*list)[0].lan = *lan; 346 (*list)[0].id = 1; 347 return 1; 348 } 349 350 for(i = 0; i < *n; i++) 351 { 352 if((*list)[i].lan.id == lan->id && (*list)[i].lan.sub == lan->sub) 353 return ++((*list)[i].id); 354 } 355 356 *list = (id_alloc_t *)xrealloc(*list, sizeof(id_alloc_t) * (*n+1)); 357 (*list)[*n].lan = *lan; 358 (*list)[*n].id = 1; 359 *n += 1; 360 return 1; 361 } 362 363 static int alloc_icon_id(language_t *lan) 364 { 365 static id_alloc_t *idlist = NULL; 366 static int nid = 0; 367 368 return get_new_id(&idlist, &nid, lan); 369 } 370 371 static int alloc_cursor_id(language_t *lan) 372 { 373 static id_alloc_t *idlist = NULL; 374 static int nid = 0; 375 376 return get_new_id(&idlist, &nid, lan); 377 } 378 379 static void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico) 380 { 381 int cnt; 382 int i; 383 icon_t *ico; 384 icon_t *list = NULL; 385 icon_header_t *ih = (icon_header_t *)rd->data; 386 int swap = 0; 387 388 if(ih->type == 1) 389 swap = 0; 390 else if(BYTESWAP_WORD(ih->type) == 1) 391 swap = 1; 392 else 393 yyerror("Icon resource data has invalid type id %d", ih->type); 394 395 cnt = swap ? BYTESWAP_WORD(ih->count) : ih->count; 396 for(i = 0; i < cnt; i++) 397 { 398 icon_dir_entry_t ide; 399 BITMAPINFOHEADER info; 400 memcpy(&ide, rd->data + sizeof(icon_header_t) 401 + i*sizeof(icon_dir_entry_t), sizeof(ide)); 402 403 ico = new_icon(); 404 ico->id = alloc_icon_id(icog->lvc.language); 405 ico->lvc = icog->lvc; 406 if(swap) 407 { 408 ide.offset = BYTESWAP_DWORD(ide.offset); 409 ide.ressize= BYTESWAP_DWORD(ide.ressize); 410 } 411 if(ide.offset > rd->size 412 || ide.offset + ide.ressize > rd->size) 413 yyerror("Icon resource data corrupt"); 414 ico->width = ide.width; 415 ico->height = ide.height; 416 ico->nclr = ide.nclr; 417 ico->planes = swap ? BYTESWAP_WORD(ide.planes) : ide.planes; 418 ico->bits = swap ? BYTESWAP_WORD(ide.bits) : ide.bits; 419 convert_bitmap((char *)rd->data + ide.offset, 0); 420 memcpy(&info, rd->data + ide.offset, sizeof(info)); 421 if(!ico->planes) 422 { 423 /* Argh! They did not fill out the resdir structure */ 424 /* The bitmap is in destination byteorder. We want native for our structures */ 425 switch(byteorder) 426 { 427 #ifdef WORDS_BIGENDIAN 428 case WRC_BO_LITTLE: 429 #else 430 case WRC_BO_BIG: 431 #endif 432 ico->planes = BYTESWAP_WORD(info.biPlanes); 433 break; 434 default: 435 ico->planes = info.biPlanes; 436 } 437 } 438 if(!ico->bits) 439 { 440 /* Argh! They did not fill out the resdir structure */ 441 /* The bitmap is in destination byteorder. We want native for our structures */ 442 switch(byteorder) 443 { 444 #ifdef WORDS_BIGENDIAN 445 case WRC_BO_LITTLE: 446 #else 447 case WRC_BO_BIG: 448 #endif 449 ico->bits = BYTESWAP_WORD(info.biBitCount); 450 break; 451 default: 452 ico->bits = info.biBitCount; 453 } 454 } 455 ico->data = new_raw_data(); 456 copy_raw_data(ico->data, rd, ide.offset, ide.ressize); 457 if(!list) 458 { 459 list = ico; 460 } 461 else 462 { 463 ico->next = list; 464 list->prev = ico; 465 list = ico; 466 } 467 } 468 icog->iconlist = list; 469 *nico = cnt; 470 } 471 472 static void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur) 473 { 474 int cnt; 475 int i; 476 cursor_t *cur; 477 cursor_t *list = NULL; 478 cursor_header_t *ch = (cursor_header_t *)rd->data; 479 int swap = 0; 480 481 if(ch->type == 2) 482 swap = 0; 483 else if(BYTESWAP_WORD(ch->type) == 2) 484 swap = 1; 485 else 486 yyerror("Cursor resource data has invalid type id %d", ch->type); 487 cnt = swap ? BYTESWAP_WORD(ch->count) : ch->count; 488 for(i = 0; i < cnt; i++) 489 { 490 cursor_dir_entry_t cde; 491 BITMAPINFOHEADER info; 492 memcpy(&cde, rd->data + sizeof(cursor_header_t) 493 + i*sizeof(cursor_dir_entry_t), sizeof(cde)); 494 495 cur = new_cursor(); 496 cur->id = alloc_cursor_id(curg->lvc.language); 497 cur->lvc = curg->lvc; 498 if(swap) 499 { 500 cde.offset = BYTESWAP_DWORD(cde.offset); 501 cde.ressize= BYTESWAP_DWORD(cde.ressize); 502 } 503 if(cde.offset > rd->size 504 || cde.offset + cde.ressize > rd->size) 505 yyerror("Cursor resource data corrupt"); 506 cur->width = cde.width; 507 cur->height = cde.height; 508 cur->nclr = cde.nclr; 509 convert_bitmap((char *)rd->data + cde.offset, 0); 510 memcpy(&info, rd->data + cde.offset, sizeof(info)); 511 /* The bitmap is in destination byteorder. We want native for our structures */ 512 switch(byteorder) 513 { 514 #ifdef WORDS_BIGENDIAN 515 case WRC_BO_LITTLE: 516 #else 517 case WRC_BO_BIG: 518 #endif 519 cur->planes = BYTESWAP_WORD(info.biPlanes); 520 cur->bits = BYTESWAP_WORD(info.biBitCount); 521 break; 522 default: 523 cur->planes = info.biPlanes; 524 cur->bits = info.biBitCount; 525 } 526 if(!win32 && (cur->planes != 1 || cur->bits != 1)) 527 yywarning("Win16 cursor contains colors"); 528 cur->xhot = swap ? BYTESWAP_WORD(cde.xhot) : cde.xhot; 529 cur->yhot = swap ? BYTESWAP_WORD(cde.yhot) : cde.yhot; 530 cur->data = new_raw_data(); 531 copy_raw_data(cur->data, rd, cde.offset, cde.ressize); 532 if(!list) 533 { 534 list = cur; 535 } 536 else 537 { 538 cur->next = list; 539 list->prev = cur; 540 list = cur; 541 } 542 } 543 curg->cursorlist = list; 544 *ncur = cnt; 545 } 546 150 547 151 548 icon_group_t *new_icon_group(raw_data_t *rd, int *memopt) … … 159 556 else 160 557 icog->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; 161 icog->lvc .language = dup_language(currentlanguage);558 icog->lvc = rd->lvc; 162 559 split_icons(rd, icog, &(icog->nicon)); 163 560 free(rd->data); … … 176 573 else 177 574 curg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; 178 curg->lvc .language = dup_language(currentlanguage);575 curg->lvc = rd->lvc; 179 576 split_cursors(rd, curg, &(curg->ncursor)); 180 577 free(rd->data); … … 183 580 } 184 581 582 /* 583 * Animated cursors and icons 584 * 585 * The format of animated cursors and icons is yet another example 586 * of bad design by "The Company". The entire RIFF structure is 587 * flawed by design because it is inconsistent and single minded: 588 * - some tags have lengths attached, others don't. The use of these 589 * non-length tags is absolutely unclear; 590 * - the content of "icon" tags can be both icons and cursors; 591 * - tags lack proper alignment constraints. It seems that everything 592 * is 16bit aligned, but I could not find that in any docu. Just be 593 * prepared to eat anything; 594 * - there are no strict constraints on tag-nesting and the organization 595 * is highly illogical; 596 * 597 * Anyhow, here is the basic structure: 598 * "RIFF" { dword taglength } 599 * "ACON" // What does it do? 600 * "LIST" { dword taglength } 601 * "INFO" // And what does this do? 602 * "INAM" { dword taglength } // Icon/cursor name 603 * {inam data} 604 * "IART" { dword taglength } // The artist 605 * {iart data} 606 * "fram" // Is followed by "icon"s 607 * "icon" { dword taglength } // First frame 608 * { icon/cursor data } 609 * "icon" { dword taglength } // Second frame 610 * { icon/cursor data } 611 * ... // ... 612 * "anih" { dword taglength } // Header structure 613 * { aniheader_t structure } 614 * "rate" { dword taglength } // The rate for each frame 615 * { `steps' dwords } 616 * "seq " { dword taglength } // The frame blit-order 617 * { `steps' dwords } 618 * 619 * Tag length are bytelength without the header and length field (i.e. -8). 620 * The "LIST" tag may occur several times and may encapsulate different 621 * tags. The `steps' is the number of "icon" tags found (actually the 622 * number of steps specified in the aniheader_t structure). The "seq "uence 623 * tag can be ommitted, in which case the sequence is equal to the sequence 624 * of "icon"s found in the file. Also "rate" may be ommitted, in which case 625 * the default from the aniheader_t structure is used. 626 * 627 * An animated cursor puts `.cur' formatted files into each "icon" tag, 628 * whereas animated icons contain `.ico' formatted files. 629 * 630 * Note about the code: Yes, it can be shorter/compressed. Some tags can be 631 * dealt with in the same code. However, this version shows what is going on 632 * and is better debug-able. 633 */ 634 static const char riff[4] = "RIFF"; 635 static const char acon[4] = "ACON"; 636 static const char list[4] = "LIST"; 637 static const char info[4] = "INFO"; 638 static const char inam[4] = "INAM"; 639 static const char iart[4] = "IART"; 640 static const char fram[4] = "fram"; 641 static const char icon[4] = "icon"; 642 static const char anih[4] = "anih"; 643 static const char rate[4] = "rate"; 644 static const char seq[4] = "seq "; 645 646 #define NEXT_TAG(p) ((riff_tag_t *)(((char *)p) + (isswapped ? BYTESWAP_DWORD(p->size) : p->size) + sizeof(*p))) 647 648 static void handle_ani_icon(riff_tag_t *rtp, enum res_e type, int isswapped) 649 { 650 cursor_dir_entry_t *cdp; 651 cursor_header_t *chp; 652 int count; 653 int ctype; 654 int i; 655 static int once = 0; /* This will trigger only once per file! */ 656 const char *anistr = type == res_aniico ? "icon" : "cursor"; 657 /* Notes: 658 * Both cursor and icon directories are similar 659 * Both cursor and icon headers are similar 660 */ 661 662 chp = (cursor_header_t *)(rtp+1); 663 cdp = (cursor_dir_entry_t *)(chp+1); 664 count = isswapped ? BYTESWAP_WORD(chp->count) : chp->count; 665 ctype = isswapped ? BYTESWAP_WORD(chp->type) : chp->type; 666 chp->reserved = BYTESWAP_WORD(chp->reserved); 667 chp->type = BYTESWAP_WORD(chp->type); 668 chp->count = BYTESWAP_WORD(chp->count); 669 670 if(type == res_anicur && ctype != 2 && !once) 671 { 672 yywarning("Animated cursor contains invalid \"icon\" tag cursor-file (%d->%s)", 673 ctype, 674 ctype == 1 ? "icontype" : "?"); 675 once++; 676 } 677 else if(type == res_aniico && ctype != 1 && !once) 678 { 679 yywarning("Animated icon contains invalid \"icon\" tag icon-file (%d->%s)", 680 ctype, 681 ctype == 2 ? "cursortype" : "?"); 682 once++; 683 } 684 else if(ctype != 1 && ctype != 2 && !once) 685 { 686 yywarning("Animated %s contains invalid \"icon\" tag file-type (%d; neither icon nor cursor)", anistr, ctype); 687 once++; 688 } 689 690 for(i = 0; i < count; i++) 691 { 692 DWORD ofs = isswapped ? BYTESWAP_DWORD(cdp[i].offset) : cdp[i].offset; 693 DWORD sze = isswapped ? BYTESWAP_DWORD(cdp[i].ressize) : cdp[i].ressize; 694 if(ofs > rtp->size || ofs+sze > rtp->size) 695 yyerror("Animated %s's data corrupt", anistr); 696 convert_bitmap((char *)chp + ofs, 0); 697 cdp[i].xhot = BYTESWAP_WORD(cdp->xhot); 698 cdp[i].yhot = BYTESWAP_WORD(cdp->yhot); 699 cdp[i].ressize = BYTESWAP_DWORD(cdp->ressize); 700 cdp[i].offset = BYTESWAP_DWORD(cdp->offset); 701 } 702 } 703 704 static void handle_ani_list(riff_tag_t *lst, enum res_e type, int isswapped) 705 { 706 riff_tag_t *rtp = lst+1; /* Skip the "LIST" tag */ 707 708 while((char *)rtp < (char *)lst + lst->size + sizeof(*lst)) 709 { 710 if(!memcmp(rtp->tag, info, sizeof(info))) 711 { 712 rtp = (riff_tag_t *)(((char *)rtp) + 4); 713 } 714 else if(!memcmp(rtp->tag, inam, sizeof(inam))) 715 { 716 /* Ignore the icon/cursor name; its a string */ 717 rtp = NEXT_TAG(rtp); 718 } 719 else if(!memcmp(rtp->tag, iart, sizeof(iart))) 720 { 721 /* Ignore the author's name; its a string */ 722 rtp = NEXT_TAG(rtp); 723 } 724 else if(!memcmp(rtp->tag, fram, sizeof(fram))) 725 { 726 /* This should be followed by "icon"s, but we 727 * simply ignore this because it is pure 728 * non-information. 729 */ 730 rtp = (riff_tag_t *)(((char *)rtp) + 4); 731 } 732 else if(!memcmp(rtp->tag, icon, sizeof(icon))) 733 { 734 handle_ani_icon(rtp, type, isswapped); 735 rtp = NEXT_TAG(rtp); 736 } 737 else 738 internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file", 739 isprint(rtp->tag[0]) ? rtp->tag[0] : '.', 740 isprint(rtp->tag[1]) ? rtp->tag[1] : '.', 741 isprint(rtp->tag[2]) ? rtp->tag[2] : '.', 742 isprint(rtp->tag[3]) ? rtp->tag[3] : '.'); 743 744 /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */ 745 if((DWORD)rtp & 1) 746 ((char *)rtp)++; 747 } 748 } 749 750 ani_curico_t *new_ani_curico(enum res_e type, raw_data_t *rd, int *memopt) 751 { 752 ani_curico_t *ani = (ani_curico_t *)xmalloc(sizeof(ani_curico_t)); 753 riff_tag_t *rtp; 754 int isswapped = 0; 755 int doswap; 756 const char *anistr = type == res_aniico ? "icon" : "cursor"; 757 758 assert(!memcmp(rd->data, riff, sizeof(riff))); 759 assert(type == res_anicur || type == res_aniico); 760 761 rtp = (riff_tag_t *)rd->data; 762 763 if(BYTESWAP_DWORD(rtp->size) + 2*sizeof(DWORD) == rd->size) 764 isswapped = 1; 765 else if(rtp->size + 2*sizeof(DWORD) == rd->size) 766 isswapped = 0; 767 else 768 yyerror("Animated %s has an invalid RIFF length", anistr); 769 770 switch(byteorder) 771 { 772 #ifdef WORDS_BIGENDIAN 773 case WRC_BO_LITTLE: 774 #else 775 case WRC_BO_BIG: 776 #endif 777 doswap = !isswapped; 778 break; 779 default: 780 doswap = isswapped; 781 } 782 783 /* 784 * When to swap what: 785 * isswapped | doswap | 786 * ----------+--------+--------------------------------- 787 * 0 | 0 | read native; don't convert 788 * 1 | 0 | read swapped size; don't convert 789 * 0 | 1 | read native; convert 790 * 1 | 1 | read swapped size; convert 791 * Reading swapped size if necessary to calculate in native 792 * format. E.g. a little-endian source on a big-endian 793 * processor. 794 */ 795 if(doswap) 796 { 797 /* We only go through the RIFF file if we need to swap 798 * bytes in words/dwords. Else we couldn't care less 799 * what the file contains. This is consistent with 800 * MS' rc.exe, which doesn't complain at all, eventhough 801 * the fileformat might not be entirely correct. 802 */ 803 rtp++; /* Skip the "RIFF" tag */ 804 805 while((char *)rtp < (char *)rd->data + rd->size) 806 { 807 if(!memcmp(rtp->tag, acon, sizeof(acon))) 808 { 809 rtp = (riff_tag_t *)(((char *)rtp) + 4); 810 } 811 else if(!memcmp(rtp->tag, list, sizeof(list))) 812 { 813 handle_ani_list(rtp, type, isswapped); 814 rtp = NEXT_TAG(rtp); 815 } 816 else if(!memcmp(rtp->tag, anih, sizeof(anih))) 817 { 818 aniheader_t *ahp = (aniheader_t *)((char *)(rtp+1)); 819 ahp->structsize = BYTESWAP_DWORD(ahp->structsize); 820 ahp->frames = BYTESWAP_DWORD(ahp->frames); 821 ahp->steps = BYTESWAP_DWORD(ahp->steps); 822 ahp->cx = BYTESWAP_DWORD(ahp->cx); 823 ahp->cy = BYTESWAP_DWORD(ahp->cy); 824 ahp->bitcount = BYTESWAP_DWORD(ahp->bitcount); 825 ahp->planes = BYTESWAP_DWORD(ahp->planes); 826 ahp->rate = BYTESWAP_DWORD(ahp->rate); 827 ahp->flags = BYTESWAP_DWORD(ahp->flags); 828 rtp = NEXT_TAG(rtp); 829 } 830 else if(!memcmp(rtp->tag, rate, sizeof(rate))) 831 { 832 int cnt = rtp->size / sizeof(DWORD); 833 DWORD *dwp = (DWORD *)(rtp+1); 834 int i; 835 for(i = 0; i < cnt; i++) 836 dwp[i] = BYTESWAP_DWORD(dwp[i]); 837 rtp = NEXT_TAG(rtp); 838 } 839 else if(!memcmp(rtp->tag, seq, sizeof(seq))) 840 { 841 int cnt = rtp->size / sizeof(DWORD); 842 DWORD *dwp = (DWORD *)(rtp+1); 843 int i; 844 for(i = 0; i < cnt; i++) 845 dwp[i] = BYTESWAP_DWORD(dwp[i]); 846 rtp = NEXT_TAG(rtp); 847 } 848 else 849 internal_error(__FILE__, __LINE__, "Unknown tag \"%c%c%c%c\" in RIFF file", 850 isprint(rtp->tag[0]) ? rtp->tag[0] : '.', 851 isprint(rtp->tag[1]) ? rtp->tag[1] : '.', 852 isprint(rtp->tag[2]) ? rtp->tag[2] : '.', 853 isprint(rtp->tag[3]) ? rtp->tag[3] : '.'); 854 855 /* FIXME: This relies in sizeof(DWORD) == sizeof(pointer_type) */ 856 if((DWORD)rtp & 1) 857 ((char *)rtp)++; 858 } 859 860 /* We must end correctly here */ 861 if((char *)rtp != (char *)rd->data + rd->size) 862 yyerror("Animated %s contains invalid field size(s)", anistr); 863 } 864 865 ani->data = rd; 866 if(memopt) 867 { 868 ani->memopt = *memopt; 869 free(memopt); 870 } 871 else 872 ani->memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE; 873 return ani; 874 } 875 #undef NEXT_TAG 876 877 /* Bitmaps */ 185 878 bitmap_t *new_bitmap(raw_data_t *rd, int *memopt) 186 879 { 187 880 bitmap_t *bmp = (bitmap_t *)xmalloc(sizeof(bitmap_t)); 881 188 882 bmp->data = rd; 189 883 if(memopt) … … 194 888 else 195 889 bmp->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; 890 rd->size -= convert_bitmap(rd->data, rd->size); 196 891 return bmp; 197 892 } … … 214 909 } 215 910 216 messagetable_t *new_messagetable(raw_data_t *rd) 911 #define MSGTAB_BAD_PTR(p, b, l, r) (((l) - ((char *)(p) - (char *)(b))) > (r)) 912 messagetable_t *new_messagetable(raw_data_t *rd, int *memopt) 217 913 { 218 914 messagetable_t *msg = (messagetable_t *)xmalloc(sizeof(messagetable_t)); 915 msgtab_block_t *mbp; 916 DWORD nblk; 917 DWORD i; 918 WORD lo; 919 WORD hi; 920 219 921 msg->data = rd; 922 if(memopt) 923 { 924 msg->memopt = *memopt; 925 free(memopt); 926 } 927 else 928 msg->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; 929 930 if(rd->size < sizeof(DWORD)) 931 yyerror("Invalid messagetable, size too small"); 932 933 nblk = *(DWORD *)rd->data; 934 lo = WRC_LOWORD(nblk); 935 hi = WRC_HIWORD(nblk); 936 937 /* FIXME: 938 * This test will fail for all n*2^16 blocks in the messagetable. 939 * However, no sane person would want to have so many blocks 940 * and have a table of megabytes attached. 941 * So, I will assume that we have less than 2^16 blocks in the table 942 * and all will just work out fine. Otherwise, we would need to test 943 * the ID, offset and length (and flag) fields to be very sure. 944 */ 945 if(hi && lo) 946 internal_error(__FILE__, __LINE__, "Messagetable contains more than 65535 blocks; cannot determine endian"); 947 if(!hi && !lo) 948 yyerror("Invalid messagetable block count 0"); 949 950 if(!hi && lo) /* Messagetable byteorder == native byteorder */ 951 { 952 #ifdef WORDS_BIGENDIAN 953 if(byteorder != WRC_BO_LITTLE) goto out; 954 #else 955 if(byteorder != WRC_BO_BIG) goto out; 956 #endif 957 /* Resource byteorder != native byteorder */ 958 959 mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]); 960 if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp))) 961 yyerror("Messagetable's blocks are outside of defined data"); 962 for(i = 0; i < nblk; i++) 963 { 964 msgtab_entry_t *mep, *next_mep; 965 DWORD id; 966 967 mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset); 968 969 for(id = mbp[i].idlo; id <= mbp[i].idhi; id++) 970 { 971 if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length)) 972 yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id); 973 if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */ 974 { 975 WORD *wp = (WORD *)&mep[1]; 976 int l = mep->length/2 - 2; /* Length included header */ 977 int n; 978 979 if(mep->length & 1) 980 yyerror("Message 0x%08lx is unicode (block %d), but has odd length (%d)", id, (int)i, mep->length); 981 for(n = 0; n < l; n++) 982 wp[n] = BYTESWAP_WORD(wp[n]); 983 984 } 985 next_mep = (msgtab_entry_t *)(((char *)mep) + mep->length); 986 mep->length = BYTESWAP_WORD(mep->length); 987 mep->flags = BYTESWAP_WORD(mep->flags); 988 mep = next_mep; 989 } 990 991 mbp[i].idlo = BYTESWAP_DWORD(mbp[i].idlo); 992 mbp[i].idhi = BYTESWAP_DWORD(mbp[i].idhi); 993 mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset); 994 } 995 } 996 if(hi && !lo) /* Messagetable byteorder != native byteorder */ 997 { 998 #ifdef WORDS_BIGENDIAN 999 if(byteorder == WRC_BO_LITTLE) goto out; 1000 #else 1001 if(byteorder == WRC_BO_BIG) goto out; 1002 #endif 1003 /* Resource byteorder == native byteorder */ 1004 1005 mbp = (msgtab_block_t *)&(((DWORD *)rd->data)[1]); 1006 nblk = BYTESWAP_DWORD(nblk); 1007 if(MSGTAB_BAD_PTR(mbp, rd->data, rd->size, nblk * sizeof(*mbp))) 1008 yyerror("Messagetable's blocks are outside of defined data"); 1009 for(i = 0; i < nblk; i++) 1010 { 1011 msgtab_entry_t *mep; 1012 DWORD id; 1013 1014 mbp[i].idlo = BYTESWAP_DWORD(mbp[i].idlo); 1015 mbp[i].idhi = BYTESWAP_DWORD(mbp[i].idhi); 1016 mbp[i].offset = BYTESWAP_DWORD(mbp[i].offset); 1017 mep = (msgtab_entry_t *)(((char *)rd->data) + mbp[i].offset); 1018 1019 for(id = mbp[i].idlo; id <= mbp[i].idhi; id++) 1020 { 1021 mep->length = BYTESWAP_WORD(mep->length); 1022 mep->flags = BYTESWAP_WORD(mep->flags); 1023 1024 if(MSGTAB_BAD_PTR(mep, rd->data, rd->size, mep->length)) 1025 yyerror("Messagetable's data for block %d, ID 0x%08lx is outside of defined data", (int)i, id); 1026 if(mep->flags == 1) /* Docu says 'flags == 0x0001' for unicode */ 1027 { 1028 WORD *wp = (WORD *)&mep[1]; 1029 int l = mep->length/2 - 2; /* Length included header */ 1030 int n; 1031 1032 if(mep->length & 1) 1033 yyerror("Message 0x%08lx is unicode (block %d), but has odd length (%d)", id, (int)i, mep->length); 1034 for(n = 0; n < l; n++) 1035 wp[n] = BYTESWAP_WORD(wp[n]); 1036 1037 } 1038 mep = (msgtab_entry_t *)(((char *)mep) + mep->length); 1039 } 1040 } 1041 } 1042 1043 out: 220 1044 return msg; 221 1045 } 222 223 void copy_raw_data(raw_data_t *dst, raw_data_t *src, int offs, int len) 1046 #undef MSGTAB_BAD_PTR 1047 1048 void copy_raw_data(raw_data_t *dst, raw_data_t *src, unsigned int offs, int len) 224 1049 { 225 1050 assert(offs <= src->size); … … 294 1119 return st; 295 1120 } 1121
Note:
See TracChangeset
for help on using the changeset viewer.