Ticket #2679: res-endian.patch
File res-endian.patch, 18.1 KB (added by , 18 years ago) |
---|
-
resource_he.cpp
40 40 41 41 namespace Scumm { 42 42 43 #define LE16(x) ((x) = TO_LE_16(x)) 44 #define LE32(x) ((x) = TO_LE_32(x)) 45 46 43 47 ResExtractor::ResExtractor(ScummEngine_v70he *scumm) 44 48 : _vm(scumm) { 45 49 … … 353 357 /* calculate total size of output file */ 354 358 RETURN_IF_BAD_POINTER(NULL, icondir->count); 355 359 skipped = 0; 356 for (c = 0 ; c < icondir->count; c++) {360 for (c = 0 ; c < FROM_LE_16(icondir->count) ; c++) { 357 361 int level; 358 362 int iconsize; 359 363 char name[14]; 360 364 WinResource *fwr; 361 365 362 366 RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]); 363 /*printf("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d\n", c,364 icondir->entries[c].bytes_in_res,365 (is_icon ? icondir->entries[c].res_info.icon.width : icondir->entries[c].res_info.cursor.width),366 (is_icon ? icondir->entries[c].res_info.icon.height : icondir->entries[c].res_info.cursor.height),367 icondir->entries[c].plane_count,368 icondir->entries[c].bit_count);*/367 printf("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d\n", c, 368 FROM_LE_32(icondir->entries[c].bytes_in_res), 369 (is_icon ? icondir->entries[c].res_info.icon.width : FROM_LE_16(icondir->entries[c].res_info.cursor.width)), 370 (is_icon ? icondir->entries[c].res_info.icon.height : FROM_LE_16(icondir->entries[c].res_info.cursor.height)), 371 FROM_LE_16(icondir->entries[c].plane_count), 372 FROM_LE_16(icondir->entries[c].bit_count)); 369 373 370 374 /* find the corresponding icon resource */ 371 snprintf(name, sizeof(name)/sizeof(char), "-%d", icondir->entries[c].res_id);375 snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id)); 372 376 fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level); 373 377 if (fwr == NULL) { 374 378 error("%s: could not find `%s' in `%s' resource.", … … 382 386 skipped++; 383 387 continue; 384 388 } 385 if ((uint32)iconsize != icondir->entries[c].bytes_in_res) {389 if ((uint32)iconsize != FROM_LE_32(icondir->entries[c].bytes_in_res)) { 386 390 debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)", 387 fi->file->name(), name, iconsize, icondir->entries[c].bytes_in_res);391 fi->file->name(), name, iconsize, FROM_LE_32(icondir->entries[c].bytes_in_res)); 388 392 } 389 size += iconsize; /* size += icondir->entries[c].bytes_in_res; */393 size += iconsize; /* size += FROM_LE_32(icondir->entries[c].bytes_in_res); */ 390 394 391 395 /* cursor resources have two additional WORDs that contain 392 396 * hotspot info */ … … 394 398 size -= sizeof(uint16)*2; 395 399 } 396 400 } 397 offset = sizeof(Win32CursorIconFileDir) + ( icondir->count-skipped) * sizeof(Win32CursorIconFileDirEntry);401 offset = sizeof(Win32CursorIconFileDir) + (FROM_LE_16(icondir->count)-skipped) * sizeof(Win32CursorIconFileDirEntry); 398 402 size += offset; 399 403 *ressize = size; 400 404 … … 405 409 /* transfer Win32CursorIconDir structure members */ 406 410 fileicondir->reserved = icondir->reserved; 407 411 fileicondir->type = icondir->type; 408 fileicondir->count = icondir->count - skipped;412 fileicondir->count = TO_LE_16(FROM_LE_16(icondir->count) - skipped); 409 413 410 414 /* transfer each cursor/icon: Win32CursorIconDirEntry and data */ 411 415 skipped = 0; 412 for (c = 0 ; c < icondir->count; c++) {416 for (c = 0 ; c < FROM_LE_16(icondir->count) ; c++) { 413 417 int level; 414 418 char name[14]; 415 419 WinResource *fwr; 416 420 byte *data; 417 421 418 422 /* find the corresponding icon resource */ 419 snprintf(name, sizeof(name)/sizeof(char), "-%d", icondir->entries[c].res_id);423 snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(icondir->entries[c].res_id)); 420 424 fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level); 421 425 if (fwr == NULL) { 422 426 error("%s: could not find `%s' in `%s' resource.", … … 430 434 /* get_resource_entry has printed error */ 431 435 return NULL; 432 436 } 433 437 if (size == 0) { 434 438 skipped++; 435 439 continue; 436 440 } … … 442 446 /* special treatment for cursors */ 443 447 if (!is_icon) { 444 448 fileicondir->entries[c-skipped].width = icondir->entries[c].res_info.cursor.width; 445 fileicondir->entries[c-skipped].height = icondir->entries[c].res_info.cursor.height / 2;449 fileicondir->entries[c-skipped].height = TO_LE_16(FROM_LE_16(icondir->entries[c].res_info.cursor.height) / 2); 446 450 fileicondir->entries[c-skipped].color_count = 0; 447 451 fileicondir->entries[c-skipped].reserved = 0; 448 452 } 449 453 450 454 /* set image offset and increase it */ 451 fileicondir->entries[c-skipped].dib_offset = offset;455 fileicondir->entries[c-skipped].dib_offset = TO_LE_32(offset); 452 456 453 457 /* transfer resource into file memory */ 454 458 if (is_icon) { 455 memcpy(&memory[offset], data, icondir->entries[c].bytes_in_res);459 memcpy(&memory[offset], data, FROM_LE_32(icondir->entries[c].bytes_in_res)); 456 460 } else { 457 461 fileicondir->entries[c-skipped].hotspot_x = ((uint16 *) data)[0]; 458 462 fileicondir->entries[c-skipped].hotspot_y = ((uint16 *) data)[1]; 459 463 memcpy(&memory[offset], data+sizeof(uint16)*2, 460 icondir->entries[c].bytes_in_res-sizeof(uint16)*2);464 FROM_LE_32(icondir->entries[c].bytes_in_res)-sizeof(uint16)*2); 461 465 offset -= sizeof(uint16)*2; 462 466 } 463 467 464 468 /* increase the offset pointer */ 465 offset += icondir->entries[c].bytes_in_res;469 offset += FROM_LE_32(icondir->entries[c].bytes_in_res); 466 470 } 467 471 468 472 return memory; … … 579 583 580 584 /* copy each char of the string, and terminate it */ 581 585 RETURN_IF_BAD_POINTER(false, *mem); 582 len = mem[0];586 len = FROM_LE_16(mem[0]); 583 587 RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len); 584 588 585 len = MIN( mem[0], (uint16)WINRES_ID_MAXLEN);589 len = MIN(FROM_LE_16(mem[0]), (uint16)WINRES_ID_MAXLEN); 586 590 for (c = 0 ; c < len ; c++) 587 wr->id[c] = mem[c+1]& 0x00FF;591 wr->id[c] = FROM_LE_16(mem[c+1]) & 0x00FF; 588 592 wr->id[len] = '\0'; 593 wr->numeric_id = false; 589 594 } else { /* Unicode string id */ 590 595 /* translate id into a string */ 591 596 snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value); 597 wr->numeric_id = true; 592 598 } 593 599 594 wr->numeric_id = (value & IMAGE_RESOURCE_NAME_IS_STRING ? false:true);595 600 return true; 596 601 } 597 602 598 603 byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) { 604 byte *result; 605 599 606 if (fi->is_PE_binary) { 600 607 Win32ImageResourceDataEntry *dataent; 601 608 602 609 dataent = (Win32ImageResourceDataEntry *) wr->children; 603 610 RETURN_IF_BAD_POINTER(NULL, *dataent); 604 *size = dataent->size;605 RETURN_IF_BAD_OFFSET(NULL, fi->memory + dataent->offset_to_data, *size);611 *size = FROM_LE_32(dataent->size); 612 printf("get_resource_entry(PE): size %d, offset_to_data %d\n", *size, FROM_LE_32(dataent->offset_to_data)); 606 613 607 re turn fi->memory + dataent->offset_to_data;614 result = fi->memory + FROM_LE_32(dataent->offset_to_data); 608 615 } else { 609 616 Win16NENameInfo *nameinfo; 610 617 int sizeshift; 611 618 612 619 nameinfo = (Win16NENameInfo *) wr->children; 613 620 sizeshift = *((uint16 *) fi->first_resource - 1); 614 *size = nameinfo->length << sizeshift; 615 RETURN_IF_BAD_OFFSET(NULL, fi->memory + (nameinfo->offset << sizeshift), *size); 621 *size = FROM_LE_16(nameinfo->length) << sizeshift; 622 printf("get_resource_entry(NE): sizeshift %d, size %d, nameinfo->length %d, nameinfo->offset %d\n", 623 sizeshift, *size, FROM_LE_16(nameinfo->length), FROM_LE_16(nameinfo->offset)); 616 624 617 re turn fi->memory + (nameinfo->offset<< sizeshift);625 result = fi->memory + (FROM_LE_16(nameinfo->offset) << sizeshift); 618 626 } 627 628 RETURN_IF_BAD_OFFSET(NULL, result, *size); 629 630 return result; 619 631 } 620 632 621 633 bool Win32ResExtractor::decode_ne_resource_id(WinLibrary *fi, WinResource *wr, uint16 value) { 622 634 if (value & NE_RESOURCE_NAME_IS_NUMERIC) { /* numeric id */ 623 635 /* translate id into a string */ 624 636 snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value & ~NE_RESOURCE_NAME_IS_NUMERIC); 637 wr->numeric_id = true; 625 638 } else { /* ASCII string id */ 626 639 int len; 627 640 char *mem = (char *)NE_HEADER(fi->memory) … … 630 643 631 644 /* copy each char of the string, and terminate it */ 632 645 RETURN_IF_BAD_POINTER(false, *mem); 633 len = mem[0];646 len = FROM_LE_16(mem[0]); 634 647 RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(char) * len); 635 648 memcpy(wr->id, &mem[1], len); 636 649 wr->id[len] = '\0'; 650 wr->numeric_id = false; 637 651 } 638 652 639 wr->numeric_id = (value & NE_RESOURCE_NAME_IS_NUMERIC ? true:false);640 653 return true; 641 654 } 642 655 … … 648 661 649 662 /* count number of `type' resources */ 650 663 RETURN_IF_BAD_POINTER(NULL, *dirent); 651 rescnt = pe_res->number_of_named_entries + pe_res->number_of_id_entries;664 rescnt = FROM_LE_16(pe_res->number_of_named_entries) + FROM_LE_16(pe_res->number_of_id_entries); 652 665 *count = rescnt; 666 printf("list_pe_resources: level %d, count %d\n", level, rescnt); 653 667 654 668 /* allocate WinResource's */ 655 669 wr = (WinResource *)malloc(sizeof(WinResource) * rescnt); … … 659 673 RETURN_IF_BAD_POINTER(NULL, dirent[c]); 660 674 wr[c].this_ = pe_res; 661 675 wr[c].level = level; 662 wr[c].is_directory = ( dirent[c].u2.s.data_is_directory);663 wr[c].children = fi->first_resource + dirent[c].u2.s.offset_to_directory;676 wr[c].is_directory = (FROM_LE_32(dirent[c].offset_to_data) & IMAGE_RESOURCE_DATA_IS_DIRECTORY); 677 wr[c].children = fi->first_resource + (FROM_LE_32(dirent[c].offset_to_data) & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY); 664 678 665 679 /* fill in wr->id, wr->numeric_id */ 666 if (!decode_pe_resource_id (fi, wr + c, dirent[c].u1.name))680 if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name))) 667 681 return NULL; 668 682 } 669 683 … … 678 692 679 693 /* count number of `type' resources */ 680 694 RETURN_IF_BAD_POINTER(NULL, typeinfo->count); 681 *count = rescnt = typeinfo->count;695 *count = rescnt = FROM_LE_16(typeinfo->count); 682 696 683 697 /* allocate WinResource's */ 684 698 wr = (WinResource *)malloc(sizeof(WinResource) * rescnt); … … 692 706 wr[c].level = 1; 693 707 694 708 /* fill in wr->id, wr->numeric_id */ 695 if (!decode_ne_resource_id(fi, wr + c, (nameinfo+c)->id))709 if (!decode_ne_resource_id(fi, wr + c, FROM_LE_16(nameinfo[c].id))) 696 710 return NULL; 697 711 } 698 712 … … 725 739 wr[c].level = 0; 726 740 727 741 /* fill in wr->id, wr->numeric_id */ 728 if (!decode_ne_resource_id(fi, wr + c, typeinfo->type_id))742 if (!decode_ne_resource_id(fi, wr + c, FROM_LE_16(typeinfo->type_id))) 729 743 return NULL; 730 744 731 745 typeinfo = NE_TYPEINFO_NEXT(typeinfo); … … 762 776 bool Win32ResExtractor::read_library(WinLibrary *fi) { 763 777 /* check for DOS header signature `MZ' */ 764 778 RETURN_IF_BAD_POINTER(false, MZ_HEADER(fi->memory)->magic); 765 if (MZ_HEADER(fi->memory)->magic == IMAGE_DOS_SIGNATURE) { 779 if (FROM_LE_16(MZ_HEADER(fi->memory)->magic) == IMAGE_DOS_SIGNATURE) { 780 printf("Found DOS MZ header...\n"); 766 781 DOSImageHeader *mz_header = MZ_HEADER(fi->memory); 767 782 768 783 RETURN_IF_BAD_POINTER(false, mz_header->lfanew); 784 785 // Apply endian fix (currently only lfanew is used from the DOSImageHeader, 786 // so we don't bother to 'fix' the rest). 787 LE32(mz_header->lfanew); 788 769 789 if (mz_header->lfanew < sizeof(DOSImageHeader)) { 770 790 error("%s: not a Windows library", fi->file->name()); 771 791 return false; … … 774 794 775 795 /* check for OS2 (Win16) header signature `NE' */ 776 796 RETURN_IF_BAD_POINTER(false, NE_HEADER(fi->memory)->magic); 777 if ( NE_HEADER(fi->memory)->magic== IMAGE_OS2_SIGNATURE) {797 if (FROM_LE_16(NE_HEADER(fi->memory)->magic) == IMAGE_OS2_SIGNATURE) { 778 798 OS2ImageHeader *header = NE_HEADER(fi->memory); 799 printf("Found OS/2 NE header...\n"); 779 800 780 801 RETURN_IF_BAD_POINTER(false, header->rsrctab); 781 802 RETURN_IF_BAD_POINTER(false, header->restab); 782 if (header->rsrctab >= header->restab) { 803 804 if (FROM_LE_16(header->rsrctab) >= FROM_LE_16(header->restab)) { 783 805 error("%s: no resource directory found", fi->file->name()); 784 806 return false; 785 807 } 786 808 809 // Apply endian fix 810 fix_os2_image_header_endian(header); 811 787 812 fi->is_PE_binary = false; 788 813 fi->first_resource = (byte *) NE_HEADER(fi->memory) 789 814 + header->rsrctab + sizeof(uint16); … … 794 819 795 820 /* check for NT header signature `PE' */ 796 821 RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature); 797 if (PE_HEADER(fi->memory)->signature == IMAGE_NT_SIGNATURE) { 798 Win32ImageSectionHeader *pe_sec; 799 Win32ImageDataDirectory *dir; 822 if (FROM_LE_32(PE_HEADER(fi->memory)->signature) == IMAGE_NT_SIGNATURE) { 823 printf("Found Win PE header...\n"); 800 824 Win32ImageNTHeaders *pe_header; 801 825 int d; 802 826 827 // Fix image header endianess 828 fix_win32_image_header_endian(PE_HEADER(fi->memory)); 829 803 830 /* allocate new memory */ 804 831 fi->total_size = calc_vma_size(fi); 832 printf("calc_vma_size returned %d\n", fi->total_size); 805 833 if (fi->total_size == 0) { 806 834 /* calc_vma_size has reported error */ 807 835 return false; … … 815 843 /* we don't need to do OFFSET checking for the sections. 816 844 * calc_vma_size has already done that */ 817 845 for (d = pe_header->file_header.number_of_sections - 1; d >= 0 ; d--) { 818 pe_sec = PE_SECTIONS(fi->memory) + d;846 Win32ImageSectionHeader *pe_sec = PE_SECTIONS(fi->memory) + d; 819 847 820 821 848 if (pe_sec->characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) 849 continue; 822 850 823 851 //if (pe_sec->virtual_address + pe_sec->size_of_raw_data > fi->total_size) 824 852 825 826 827 if (pe_sec->virtual_address!= pe_sec->pointer_to_raw_data) {828 829 830 853 RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->virtual_address, pe_sec->size_of_raw_data); 854 RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->pointer_to_raw_data, pe_sec->size_of_raw_data); 855 if (FROM_LE_32(pe_sec->virtual_address) != pe_sec->pointer_to_raw_data) { 856 memmove(fi->memory + pe_sec->virtual_address, 857 fi->memory + pe_sec->pointer_to_raw_data, 858 pe_sec->size_of_raw_data); 831 859 } 832 860 } 833 861 834 862 /* find resource directory */ 835 863 RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]); 836 dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE;864 Win32ImageDataDirectory *dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE; 837 865 if (dir->size == 0) { 838 866 error("%s: file contains no resources", fi->file->name()); 839 867 return false; 840 868 } 869 870 fix_win32_image_data_directory(dir); 841 871 842 872 fi->first_resource = fi->memory + dir->virtual_address; 843 873 fi->is_PE_binary = true; … … 860 890 size = 0; 861 891 RETURN_IF_BAD_POINTER(-1, PE_HEADER(fi->memory)->file_header.number_of_sections); 862 892 segcount = PE_HEADER(fi->memory)->file_header.number_of_sections; 893 printf("calc_vma_size: segcount = %d\n", segcount); 863 894 864 895 /* If there are no segments, just process file like it is. 865 896 * This is (probably) not the right thing to do, but problems … … 872 903 RETURN_IF_BAD_POINTER(-1, *seg); 873 904 for (c = 0 ; c < segcount ; c++) { 874 905 RETURN_IF_BAD_POINTER(0, *seg); 906 fix_win32_image_section_header(seg); 875 907 876 908 size = MAX((uint32)size, seg->virtual_address + seg->size_of_raw_data); 877 909 /* I have no idea what misc.virtual_size is for... */ 878 879 910 size = MAX((uint32)size, seg->virtual_address + seg->misc.virtual_size); 911 seg++; 880 912 } 881 913 882 914 return size; … … 1113 1145 goto cleanup; 1114 1146 } else { 1115 1147 if (entries[c].dib_offset > offset) 1116 1148 min_offset = MIN(min_offset, entries[c].dib_offset); 1117 1149 } 1118 1150 } 1119 1151 … … 1122 1154 error("offset of bitmap header incorrect (too low)"); 1123 1155 goto cleanup; 1124 1156 } 1157 assert(min_offset != 0x7fffffff); 1125 1158 debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset); 1126 1159 in->seek(min_offset - offset, SEEK_CUR); 1127 1160 offset = min_offset; … … 1158 1191 return 0; 1159 1192 } 1160 1193 1161 #define LE16(x) ((x) = TO_LE_16(x))1162 #define LE32(x) ((x) = TO_LE_32(x))1163 1164 1194 void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) { 1165 1195 LE16(obj->reserved); 1166 1196 LE16(obj->type); … … 1241 1271 LE32(obj->file_header.number_of_symbols); 1242 1272 LE16(obj->file_header.size_of_optional_header); 1243 1273 LE16(obj->file_header.characteristics); 1274 1275 // FIXME: Does this assert ever trigger? If so, we should modify this function 1276 // to properly deal with it. 1277 assert(obj->file_header.size_of_optional_header >= sizeof(obj->optional_header)); 1244 1278 LE16(obj->optional_header.magic); 1245 1279 LE32(obj->optional_header.size_of_code); 1246 1280 LE32(obj->optional_header.size_of_initialized_data); -
resource_he.h
44 44 #define MZ_HEADER(x) ((DOSImageHeader *)(x)) 45 45 #define NE_HEADER(x) ((OS2ImageHeader *)PE_HEADER(x)) 46 46 #define NE_TYPEINFO_NEXT(x) ((Win16NETypeInfo *)((byte *)(x) + sizeof(Win16NETypeInfo) + \ 47 ((Win16NETypeInfo *)x)->count* sizeof(Win16NENameInfo)))47 FROM_LE_16(((Win16NETypeInfo *)x)->count) * sizeof(Win16NENameInfo))) 48 48 #define NE_RESOURCE_NAME_IS_NUMERIC (0x8000) 49 49 50 50 #define STRIP_RES_ID_FORMAT(x) (x != NULL && (x[0] == '-' || x[0] == '+') ? ++x : x) … … 264 264 }; 265 265 266 266 struct Win32ImageResourceDirectoryEntry { 267 union { 268 struct { 269 #ifdef SCUMM_BIGENDIAN 270 unsigned name_is_string:1; 271 unsigned name_offset:31; 272 #else 273 unsigned name_offset:31; 274 unsigned name_is_string:1; 275 #endif 276 } s1; 277 uint32 name; 278 struct { 279 #ifdef SCUMM_BIG_ENDIAN 280 uint16 __pad; 281 uint16 id; 282 #else 283 uint16 id; 284 uint16 __pad; 285 #endif 286 } s2; 287 } u1; 288 union { 289 uint32 offset_to_data; 290 struct { 291 #ifdef SCUMM_BIG_ENDIAN 292 unsigned data_is_directory:1; 293 unsigned offset_to_directory:31; 294 #else 295 unsigned offset_to_directory:31; 296 unsigned data_is_directory:1; 297 #endif 298 } s; 299 } u2; 267 uint32 name; 268 uint32 offset_to_data; 300 269 }; 301 270 302 271 struct Win16NETypeInfo {