diff --git a/src/Common/Xbe.cpp b/src/Common/Xbe.cpp index dee7364c1..0e3293f98 100644 --- a/src/Common/Xbe.cpp +++ b/src/Common/Xbe.cpp @@ -37,11 +37,13 @@ #include "CxbxVersion.h" #include "CxbxUtil.h" -#include -#include #include -#include -#include +#include +#include +#include +#include +#include +#include #define PAGE_SIZE 0x1000 @@ -548,281 +550,32 @@ static char *BetterTime(uint32 x_timeDate) return x_ctime; } -// dump Xbe information to text file -void Xbe::DumpInformation(FILE *x_file) +bool Xbe::DumpInformationToFile(std::string out_filename) +{ + if(HasError()) { + return false; + } + + bool success = false; + XbePrinter printer(this); + std::ofstream out_file(out_filename); + if(out_file.is_open()) { + out_file << printer.GenXbeInfo(); + out_file.close(); + success = true; + } + return success; +} + +void Xbe::DumpInformationToConsole() { if(HasError()) return; - fprintf(x_file, "XBE information generated by Cxbx-Reloaded (Version " _CXBX_VERSION ")\n"); - fprintf(x_file, "\n"); - fprintf(x_file, "Title identified as \"%s\"\n", m_szAsciiTitle); - fprintf(x_file, "\n"); - fprintf(x_file, "Dumping XBE file header...\n"); - fprintf(x_file, "\n"); - fprintf(x_file, "Magic Number : XBEH\n"); - - // print digital signature - { - fprintf(x_file, "Digitial Signature : "); - for(int y=0;y<16;y++) - { - fprintf(x_file, "\n "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Header.pbDigitalSignature[y*16+x]); - } - fprintf(x_file, "\n \n"); - } - - fprintf(x_file, "Base Address : 0x%.08X\n", m_Header.dwBaseAddr); - fprintf(x_file, "Size of Headers : 0x%.08X\n", m_Header.dwSizeofHeaders); - fprintf(x_file, "Size of Image : 0x%.08X\n", m_Header.dwSizeofImage); - fprintf(x_file, "Size of Image Header : 0x%.08X\n", m_Header.dwSizeofImageHeader); - fprintf(x_file, "TimeDate Stamp : 0x%.08X (%s)\n", m_Header.dwTimeDate, BetterTime(m_Header.dwTimeDate)); - fprintf(x_file, "Certificate Address : 0x%.08X\n", m_Header.dwCertificateAddr); - fprintf(x_file, "Number of Sections : 0x%.08X\n", m_Header.dwSections); - fprintf(x_file, "Section Headers Address : 0x%.08X\n", m_Header.dwSectionHeadersAddr); - - // print init flags - { - fprintf(x_file, "Init Flags : 0x%.08X ", m_Header.dwInitFlags_value); - - if(m_Header.dwInitFlags.bMountUtilityDrive) - fprintf(x_file, "[Mount Utility Drive] "); - - if(m_Header.dwInitFlags.bFormatUtilityDrive) - fprintf(x_file, "[Format Utility Drive] "); - - if(m_Header.dwInitFlags.bLimit64MB) - fprintf(x_file, "[Limit Devkit Run Time Memory to 64MB] "); - - if(!m_Header.dwInitFlags.bDontSetupHarddisk) - fprintf(x_file, "[Setup Harddisk] "); - - fprintf(x_file, "\n"); - } - - char AsciiFilename[40]; - - setlocale( LC_ALL, "English" ); - - const wchar_t *wszFilename = (const wchar_t *)GetAddr(m_Header.dwDebugUnicodeFilenameAddr); - - if(wszFilename != NULL) - wcstombs(AsciiFilename, wszFilename, 40); - else - AsciiFilename[0] = '\0'; - - fprintf(x_file, "Entry Point : 0x%.08X (Retail: 0x%.08X, Debug: 0x%.08X)\n", m_Header.dwEntryAddr, m_Header.dwEntryAddr ^ XOR_EP_RETAIL, m_Header.dwEntryAddr ^ XOR_EP_DEBUG); - fprintf(x_file, "TLS Address : 0x%.08X\n", m_Header.dwTLSAddr); - fprintf(x_file, "(PE) Stack Commit : 0x%.08X\n", m_Header.dwPeStackCommit); - fprintf(x_file, "(PE) Heap Reserve : 0x%.08X\n", m_Header.dwPeHeapReserve); - fprintf(x_file, "(PE) Heap Commit : 0x%.08X\n", m_Header.dwPeHeapCommit); - fprintf(x_file, "(PE) Base Address : 0x%.08X\n", m_Header.dwPeBaseAddr); - fprintf(x_file, "(PE) Size of Image : 0x%.08X\n", m_Header.dwPeSizeofImage); - fprintf(x_file, "(PE) Checksum : 0x%.08X\n", m_Header.dwPeChecksum); - fprintf(x_file, "(PE) TimeDate Stamp : 0x%.08X (%s)\n", m_Header.dwPeTimeDate, BetterTime(m_Header.dwPeTimeDate)); - fprintf(x_file, "Debug Pathname Address : 0x%.08X (\"%s\")\n", m_Header.dwDebugPathnameAddr, GetAddr(m_Header.dwDebugPathnameAddr)); - fprintf(x_file, "Debug Filename Address : 0x%.08X (\"%s\")\n", m_Header.dwDebugFilenameAddr, GetAddr(m_Header.dwDebugFilenameAddr)); - fprintf(x_file, "Debug Unicode filename Address : 0x%.08X (L\"%s\")\n", m_Header.dwDebugUnicodeFilenameAddr, AsciiFilename); - fprintf(x_file, "Kernel Image Thunk Address : 0x%.08X (Retail: 0x%.08X, Debug: 0x%.08X)\n", m_Header.dwKernelImageThunkAddr, m_Header.dwKernelImageThunkAddr ^ XOR_KT_RETAIL, m_Header.dwKernelImageThunkAddr ^ XOR_KT_DEBUG); - fprintf(x_file, "NonKernel Import Dir Address : 0x%.08X\n", m_Header.dwNonKernelImportDirAddr); - fprintf(x_file, "Library Versions : 0x%.08X\n", m_Header.dwLibraryVersions); - fprintf(x_file, "Library Versions Address : 0x%.08X\n", m_Header.dwLibraryVersionsAddr); - fprintf(x_file, "Kernel Library Version Address : 0x%.08X\n", m_Header.dwKernelLibraryVersionAddr); - fprintf(x_file, "XAPI Library Version Address : 0x%.08X\n", m_Header.dwXAPILibraryVersionAddr); - fprintf(x_file, "Logo Bitmap Address : 0x%.08X\n", m_Header.dwLogoBitmapAddr); - fprintf(x_file, "Logo Bitmap Size : 0x%.08X\n", m_Header.dwSizeofLogoBitmap); - fprintf(x_file, "\n"); - fprintf(x_file, "Dumping XBE Certificate...\n"); - fprintf(x_file, "\n"); - fprintf(x_file, "Size of Certificate : 0x%.08X\n", m_Certificate.dwSize); - fprintf(x_file, "TimeDate Stamp : 0x%.08X (%s)\n", m_Certificate.dwTimeDate, BetterTime(m_Certificate.dwTimeDate)); - fprintf(x_file, "Title ID : 0x%.08X\n", m_Certificate.dwTitleId); - fprintf(x_file, "Title : L\"%s\"\n", m_szAsciiTitle); - - // print alternate title IDs - { - fprintf(x_file, "Alternate Titles IDs : "); - - for(int v=0;v<0x10;v++) - { - if(v != 0) - fprintf(x_file, " "); - fprintf(x_file, "0x%.08X", m_Certificate.dwAlternateTitleId[v]); - if(v != 0x0F) - fprintf(x_file, "\n"); - } - - fprintf(x_file, "\n"); - } - - fprintf(x_file, "Allowed Media : 0x%.08X (%s)\n", m_Certificate.dwAllowedMedia, AllowedMediaToString().c_str()); - fprintf(x_file, "Game Region : 0x%.08X (%s)\n", m_Certificate.dwGameRegion, GameRegionToString()); - fprintf(x_file, "Game Ratings : 0x%.08X\n", m_Certificate.dwGameRatings); - fprintf(x_file, "Disk Number : 0x%.08X\n", m_Certificate.dwDiskNumber); - fprintf(x_file, "Version : 0x%.08X\n", m_Certificate.dwVersion); - - // print LAN key - { - fprintf(x_file, "LAN Key : "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Certificate.bzLanKey[x]); - fprintf(x_file, "\n"); - } - - // print signature key - { - fprintf(x_file, "Signature Key : "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Certificate.bzSignatureKey[x]); - fprintf(x_file, "\n"); - } - - // print alternate signature keys - { - fprintf(x_file, "Title Alternate Signature Keys : "); - for(int y=0;y<16;y++) - { - fprintf(x_file, "\n "); - for(int x=0;x<16;x++) - fprintf(x_file, "%.02X", m_Certificate.bzTitleAlternateSignatureKey[y][x]); - } - fprintf(x_file, "\n \n"); - } - - fprintf(x_file, "\n"); - fprintf(x_file, "Dumping XBE Section Headers...\n"); - fprintf(x_file, "\n"); - - // print section headers - { - for(uint32 v=0;vdwDataStartAddr); - fprintf(x_file, "Data End Address : 0x%.08X\n", m_TLS->dwDataEndAddr); - fprintf(x_file, "TLS Index Address : 0x%.08X\n", m_TLS->dwTLSIndexAddr); - fprintf(x_file, "TLS Callback Address : 0x%.08X\n", m_TLS->dwTLSCallbackAddr); - fprintf(x_file, "Size of Zero Fill : 0x%.08X\n", m_TLS->dwSizeofZeroFill); - fprintf(x_file, "Characteristics : 0x%.08X\n", m_TLS->dwCharacteristics); - } - else - { - fprintf(x_file, "(This XBE contains no TLS)\n"); - } + XbePrinter printer(this); + std::cout << printer.GenXbeInfo(); } - // import logo bitmap from raw monochrome data void Xbe::ImportLogoBitmap(const uint08 x_Gray[100*17]) { @@ -1037,9 +790,56 @@ const char *Xbe::GameRegionToString() return Region_text[index]; } -std::string Xbe::AllowedMediaToString() +const wchar_t *Xbe::GetUnicodeFilenameAddr() { - const uint32 dwAllowedMedia = m_Certificate.dwAllowedMedia; + return (const wchar_t *)GetAddr(m_Header.dwDebugUnicodeFilenameAddr); +} + +#define SSTREAM_SET_HEX(stream_name) stream_name << std::setfill('0') << std::uppercase << std::hex; + +XbePrinter::XbePrinter(Xbe* Xbe_object) +{ + Xbe_to_print = Xbe_object; + Xbe_header = &(Xbe_object->m_Header); + Xbe_certificate = &(Xbe_object->m_Certificate); +} + +std::string XbePrinter::GenXbeInfo() +{ + std::string info; + info.append(GenDumpHeader()); + info.append(GenXbeHeaderInfo()); + info.append(GenXbeCertificateInfo()); + info.append(GenSectionInfo()); + info.append(GenLibraryVersions()); + info.append(GenTLS()); + return info; +} + +std::string XbePrinter::GenHexRow( + uint08 *signature, const uint08 row, const uint08 row_size +) +{ + const uint16 offset = row * row_size; + std::stringstream text; + SSTREAM_SET_HEX(text); + for(uint08 x = 0; x < row_size; x++) { + text << std::setw(2) << static_cast(signature[offset + x]); + } + return text.str(); +} + +// https://stackoverflow.com/questions/4786292/converting-unicode-strings-and-vice-versa +std::string XbePrinter::utf8_to_ascii(const wchar_t* utf8_string) +{ + std::wstring_convert> utf8_to_ascii; + const std::wstring utf8_filename(utf8_string); + return utf8_to_ascii.to_bytes(utf8_filename); +} + +std::string XbePrinter::AllowedMediaToString() +{ + const uint32 dwAllowedMedia = Xbe_certificate->dwAllowedMedia; std::string text = "Media Types:"; if(dwAllowedMedia & XBEIMAGE_MEDIA_TYPE_MEDIA_MASK) { @@ -1076,3 +876,377 @@ std::string Xbe::AllowedMediaToString() } return text; } + +std::string XbePrinter::GameRatingToString() +{ + std::string text; + // Info from: http://xboxdevwiki.net/EEPROM + switch(Xbe_certificate->dwGameRatings) { + case 0x0: + text.append("(RP) Rating Pending"); + break; + case 0x1: + text.append("(AO) Adults Only"); + break; + case 0x2: + text.append("(M) Mature"); + break; + case 0x3: + text.append("(T) Teen"); + break; + case 0x4: + text.append("(E) Everyone"); + break; + case 0x5: + text.append("(K-A) Kids to Adults"); + break; + case 0x6: + text.append("(EC) Early Childhood"); + break; + default: + text.append("ERROR: no rating"); + break; + } + return text; +} + +std::string XbePrinter::GenDumpHeader() +{ + std::string text; + text.append("XBE information generated by Cxbx-Reloaded (Version " _CXBX_VERSION ")\n\n"); + text.append("Title identified as \""); + text.append(Xbe_to_print->m_szAsciiTitle); + text.append("\"\n\n"); + text.append("Dumping XBE file header...\n\n"); + text.append("Magic Number : XBEH\n"); + return text; +} + +std::string XbePrinter::GenXbeHeaderInfo() +{ + std::string text; + text.append(GenDigitalSignature()); + text.append(GenGeneralHeaderInfo1()); + text.append(GenInitFlags()); + text.append(GenGeneralHeaderInfo2()); + return text; +} + +std::string XbePrinter::GenDigitalSignature() +{ + const uint08 row_size = 16; + std::string text; + text.append("Digital Signature : "); + for(int row = 0; row < 16; row++) { + text.append("\n "); + text.append(GenHexRow(&(Xbe_header->pbDigitalSignature[0]), row, row_size)); + } + text.append("\n \n"); + return text; +} + +std::string XbePrinter::GenGeneralHeaderInfo1() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Base Address : 0x" << std::setw(8) << Xbe_header->dwBaseAddr << "\n"; + text << "Size of Headers : 0x" << std::setw(8) << Xbe_header->dwSizeofHeaders << "\n"; + text << "Size of Image : 0x" << std::setw(8) << Xbe_header->dwSizeofImage << "\n"; + text << "Size of Image Header : 0x" << std::setw(8) << Xbe_header->dwSizeofImageHeader << "\n"; + text << "TimeDate Stamp : 0x" << std::setw(8) << Xbe_header->dwTimeDate << " (" << BetterTime(Xbe_header->dwTimeDate) << ")\n"; + text << "Certificate Address : 0x" << std::setw(8) << Xbe_header->dwCertificateAddr << "\n"; + text << "Number of Sections : 0x" << std::setw(8) << Xbe_header->dwSections << "\n"; + text << "Section Headers Address : 0x" << std::setw(8) << Xbe_header->dwSectionHeadersAddr << "\n"; + return text.str(); +} + +std::string XbePrinter::GenInitFlags() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Init Flags : 0x" << std::setw(8) << Xbe_header->dwInitFlags_value << " "; + + if(Xbe_header->dwInitFlags.bMountUtilityDrive) { + text << "[Mount Utility Drive] "; + } + if(Xbe_header->dwInitFlags.bFormatUtilityDrive) { + text << "[Format Utility Drive] "; + } + if(Xbe_header->dwInitFlags.bLimit64MB) { + text << "[Limit Devkit Run Time Memory to 64MB] "; + } + if(!Xbe_header->dwInitFlags.bDontSetupHarddisk) { + text << "[Setup Harddisk] "; + } + text << "\n"; + return text.str(); +} + +std::string XbePrinter::GenGeneralHeaderInfo2() +{ + const uint32 retail_entry_point = Xbe_header->dwEntryAddr ^ XOR_EP_RETAIL; + const uint32 debug_entry_point = Xbe_header->dwEntryAddr ^ XOR_EP_DEBUG; + const uint32 retail_thunk_addr = Xbe_header->dwKernelImageThunkAddr ^ XOR_KT_RETAIL; + const uint32 debug_thunk_addr = Xbe_header->dwKernelImageThunkAddr ^ XOR_KT_DEBUG; + const std::string AsciiFilename = utf8_to_ascii(Xbe_to_print->GetUnicodeFilenameAddr()); + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Entry Point : 0x" << std::setw(8) << Xbe_header->dwEntryAddr << " (Retail: 0x" << std::setw(8) << retail_entry_point << ", Debug: 0x" << std::setw(8) << debug_entry_point << ")\n"; + text << "TLS Address : 0x" << std::setw(8) << Xbe_header->dwTLSAddr << "\n"; + text << "(PE) Stack Commit : 0x" << std::setw(8) << Xbe_header->dwPeStackCommit << "\n"; + text << "(PE) Heap Reserve : 0x" << std::setw(8) << Xbe_header->dwPeHeapReserve << "\n"; + text << "(PE) Heap Commit : 0x" << std::setw(8) << Xbe_header->dwPeHeapCommit << "\n"; + text << "(PE) Base Address : 0x" << std::setw(8) << Xbe_header->dwPeBaseAddr << "\n"; + text << "(PE) Size of Image : 0x" << std::setw(8) << Xbe_header->dwPeSizeofImage << "\n"; + text << "(PE) Checksum : 0x" << std::setw(8) << Xbe_header->dwPeChecksum << "\n"; + text << "(PE) TimeDate Stamp : 0x" << std::setw(8) << Xbe_header->dwPeTimeDate << " (" << BetterTime(Xbe_header->dwPeTimeDate) << ")\n"; + text << "Debug Pathname Address : 0x" << std::setw(8) << Xbe_header->dwDebugPathnameAddr << " (\"" << Xbe_to_print->GetAddr(Xbe_header->dwDebugPathnameAddr) << "\")\n"; + text << "Debug Filename Address : 0x" << std::setw(8) << Xbe_header->dwDebugFilenameAddr << " (\"" << Xbe_to_print->GetAddr(Xbe_header->dwDebugFilenameAddr) << "\")\n"; + text << "Debug Unicode filename Address : 0x" << std::setw(8) << Xbe_header->dwDebugUnicodeFilenameAddr << " (L\"" << AsciiFilename << "\")\n"; + text << "Kernel Image Thunk Address : 0x" << std::setw(8) << Xbe_header->dwKernelImageThunkAddr << " (Retail: 0x" << std::setw(8) << retail_thunk_addr << ", Debug: 0x" << std::setw(8) << debug_thunk_addr << ")\n"; + text << "NonKernel Import Dir Address : 0x" << std::setw(8) << Xbe_header->dwNonKernelImportDirAddr << "\n"; + text << "Library Versions : 0x" << std::setw(8) << Xbe_header->dwLibraryVersions << "\n"; + text << "Library Versions Address : 0x" << std::setw(8) << Xbe_header->dwLibraryVersionsAddr << "\n"; + text << "Kernel Library Version Address : 0x" << std::setw(8) << Xbe_header->dwKernelLibraryVersionAddr << "\n"; + text << "XAPI Library Version Address : 0x" << std::setw(8) << Xbe_header->dwXAPILibraryVersionAddr << "\n"; + text << "Logo Bitmap Address : 0x" << std::setw(8) << Xbe_header->dwLogoBitmapAddr << "\n"; + text << "Logo Bitmap Size : 0x" << std::setw(8) << Xbe_header->dwSizeofLogoBitmap << "\n\n"; + return text.str(); +} + +std::string XbePrinter::GenXbeCertificateInfo() +{ + std::string text; + text.append(GenCertificateHeader()); + text.append(GenAlternateTitleIDs()); + text.append(GenMediaInfo()); + text.append(GenLANKey()); + text.append(GenSignatureKey()); + text.append(GenAlternateSignatureKeys()); + return text; +} + +std::string XbePrinter::GenCertificateHeader() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Dumping XBE Certificate...\n\n"; + text << "Size of Certificate : 0x" << std::setw(8) << Xbe_certificate->dwSize << "\n"; + text << "TimeDate Stamp : 0x" << std::setw(8) << Xbe_certificate->dwTimeDate << " (" << BetterTime(Xbe_certificate->dwTimeDate) << ")\n"; + text << "Title ID : 0x" << std::setw(8) << Xbe_certificate->dwTitleId << "\n"; + text << "Title : L\"" << Xbe_to_print->m_szAsciiTitle << "\"\n"; + return text.str(); +} + +std::string XbePrinter::GenAlternateTitleIDs() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Alternate Titles IDs : "; + + for(int v = 0; v < 0x10; v++) { + if(v != 0) { + text << " "; + } + text << "0x" << std::setw(8) << Xbe_certificate->dwAlternateTitleId[v]; + if(v != 0x0F) { + text << "\n"; + } + } + text << "\n"; + return text.str(); +} + +std::string XbePrinter::GenMediaInfo() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Allowed Media : 0x" << std::setw(8) << Xbe_certificate->dwAllowedMedia << " (" << AllowedMediaToString() << ")\n"; + text << "Game Region : 0x" << std::setw(8) << Xbe_certificate->dwGameRegion << " (" << Xbe_to_print->GameRegionToString() << ")\n"; + text << "Game Ratings : 0x" << std::setw(8) << Xbe_certificate->dwGameRatings << " (" << GameRatingToString() << ")\n"; + text << "Disk Number : 0x" << std::setw(8) << Xbe_certificate->dwDiskNumber << "\n"; + text << "Version : 0x" << std::setw(8) << Xbe_certificate->dwVersion << "\n"; + return text.str(); +} + +std::string XbePrinter::GenLANKey() +{ + const uint08 row = 0; + const uint08 row_size = 16; + std::string text; + text.append("LAN Key : "); + text.append(GenHexRow(&(Xbe_certificate->bzLanKey[0]), row, row_size)); + text.append("\n"); + return text; +} + +std::string XbePrinter::GenSignatureKey() +{ + const uint08 row = 0; + const uint08 row_size = 16; + std::string text; + text.append("Signature Key : "); + text.append(GenHexRow(&(Xbe_certificate->bzSignatureKey[0]), row, row_size)); + text.append("\n"); + return text; +} + +std::string XbePrinter::GenAlternateSignatureKeys() +{ + const uint08 row = 0; + const uint08 row_size = 16; + std::string text; + + text.append("Title Alternate Signature Keys : "); + for(int row = 0; row < 16; row++) + { + text.append("\n "); + text.append(GenHexRow(&(Xbe_certificate->bzTitleAlternateSignatureKey[0][0]), row, row_size)); + } + text.append("\n \n"); + return text; +} + +std::string XbePrinter::GenSectionInfo() +{ + std::string text; + text.append("\nDumping XBE Section Headers...\n\n"); + text.append(GenSectionHeaders()); + return text; +} + +std::string XbePrinter::GenSectionHeaders() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + for(uint32 v=0; v < Xbe_header->dwSections; v++) { + text << "Section Name : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwSectionNameAddr << " (\"" << Xbe_to_print->m_szSectionName[v] << "\")\n"; + text << GenSectionFlags(Xbe_to_print->m_SectionHeader[v]); + text << "Virtual Address : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwVirtualAddr << "\n"; + text << "Virtual Size : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwVirtualSize << "\n"; + text << "Raw Address : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwRawAddr << "\n"; + text << "Size of Raw : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwSizeofRaw << "\n"; + text << "Section Name Address : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwSectionNameAddr << "\n"; + text << "Section Reference Count : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwSectionRefCount << "\n"; + text << "Head Shared Reference Count Addr : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwHeadSharedRefCountAddr << "\n"; + text << "Tail Shared Reference Count Addr : 0x" << std::setw(8) << Xbe_to_print->m_SectionHeader[v].dwTailSharedRefCountAddr << "\n"; + text << GenSectionDigest(Xbe_to_print->m_SectionHeader[v]) << "\n"; + } + return text.str(); +} + +std::string XbePrinter::GenSectionFlags(Xbe::SectionHeader section_header) +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Flags : 0x" << std::setw(8) << section_header.dwFlags_value << " "; + + if(section_header.dwFlags.bWritable) { + text << "(Writable) "; + } + if(section_header.dwFlags.bPreload) { + text << "(Preload) "; + } + if(section_header.dwFlags.bExecutable) { + text << "(Executable) "; + } + if(section_header.dwFlags.bInsertedFile) { + text << "(Inserted File) "; + } + if(section_header.dwFlags.bHeadPageRO) { + text << "(Head Page RO) "; + } + if(section_header.dwFlags.bTailPageRO) { + text << "(Tail Page RO) "; + } + text << "\n"; + return text.str(); +} + +std::string XbePrinter::GenSectionDigest(Xbe::SectionHeader section_header) +{ + std::string text; + text.append("Section Digest : "); + text.append(GenHexRow(§ion_header.bzSectionDigest[0], 0, 20)); + text.append("\n"); + return text; +} + +std::string XbePrinter::GenLibraryVersions() +{ + std::stringstream text; + text << "Dumping XBE Library Versions...\n\n"; + + if(Xbe_to_print->m_LibraryVersion == 0 || Xbe_header->dwLibraryVersions == 0) { + text << "(This XBE contains no Library Versions)\n\n"; + } + else { + for(uint32 v = 0; v < Xbe_header->dwLibraryVersions; v++) { + char libname[9]; + for(uint32 c=0;c<8;c++) { + libname[c] = Xbe_to_print->m_LibraryVersion[v].szName[c]; + } + libname[8] = '\0'; + + text << "Library Name : " << libname << "\n"; + text << "Version : " + << Xbe_to_print->m_LibraryVersion[v].wMajorVersion << "." + << Xbe_to_print->m_LibraryVersion[v].wMinorVersion << "." + << Xbe_to_print->m_LibraryVersion[v].wBuildVersion << "\n"; + text << GenLibraryFlags(Xbe_to_print->m_LibraryVersion[v]); + text << "\n"; + } + } + return text.str(); +} + +std::string XbePrinter::GenLibraryFlags(Xbe::LibraryVersion libver) +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + text << "Flags : 0x" << std::setw(4) << libver.wFlags_value << " "; + text << "QFEVersion : 0x" << std::setw(4) << libver.wFlags.QFEVersion << ", "; + + if(libver.wFlags.bDebugBuild) { + text << "Debug, "; + } + else { + text << "Retail, "; + } + + switch(libver.wFlags.Approved) { + case 0: + text << "Unapproved"; + break; + case 1: + text << "Possibly Approved"; + break; + case 2: + text << "Approved"; + break; + } + text << "\n"; + return text.str(); +} + +std::string XbePrinter::GenTLS() +{ + std::stringstream text; + SSTREAM_SET_HEX(text); + Xbe::TLS *local_TLS = Xbe_to_print->m_TLS; + + text << "Dumping XBE TLS...\n\n"; + // print thread local storage + if(local_TLS != 0) { + text << "Data Start Address : 0x" << std::setw(8) << local_TLS->dwDataStartAddr << "\n"; + text << "Data End Address : 0x" << std::setw(8) << local_TLS->dwDataEndAddr << "\n"; + text << "TLS Index Address : 0x" << std::setw(8) << local_TLS->dwTLSIndexAddr << "\n"; + text << "TLS Callback Address : 0x" << std::setw(8) << local_TLS->dwTLSCallbackAddr << "\n"; + text << "Size of Zero Fill : 0x" << std::setw(8) << local_TLS->dwSizeofZeroFill << "\n"; + text << "Characteristics : 0x" << std::setw(8) << local_TLS->dwCharacteristics << "\n"; + } + else { + text << "(This XBE contains no TLS)\n"; + } + return text.str(); +} diff --git a/src/Common/Xbe.h b/src/Common/Xbe.h index 344ee4a49..756b770d4 100644 --- a/src/Common/Xbe.h +++ b/src/Common/Xbe.h @@ -62,8 +62,8 @@ class Xbe : public Error // export to Xbe file void Export(const char *x_szXbeFilename); - // dump Xbe information to text file - void DumpInformation(FILE *x_file); + bool DumpInformationToFile(std::string); + void DumpInformationToConsole(); // import logo bitmap from raw monochrome data void ImportLogoBitmap(const uint08 x_Gray[100*17]); @@ -255,17 +255,17 @@ class Xbe : public Error // retrieve thread local storage index address uint32 *GetTLSIndex() { if(m_TLS == 0) return 0; else return (uint32*)GetAddr(m_TLS->dwTLSIndexAddr); } + // return a modifiable pointer inside this structure that corresponds to a virtual address + uint08 *GetAddr(uint32 x_dwVirtualAddress); + + const wchar_t *GetUnicodeFilenameAddr(); private: // constructor initialization void ConstructorInit(); - // return a modifiable pointer inside this structure that corresponds to a virtual address - uint08 *GetAddr(uint32 x_dwVirtualAddress); - // return a modifiable pointer to logo bitmap data uint08 *GetLogoBitmap(uint32 x_dwSize); - std::string AllowedMediaToString(); // used to encode/decode logo bitmap data union LogoRLE @@ -346,6 +346,49 @@ class Xbe : public Error *m_xprImage; }; +class XbePrinter +{ + public: + XbePrinter(Xbe*); + std::string GenXbeInfo(); + + private: + Xbe *Xbe_to_print; + Xbe::Header *Xbe_header; + Xbe::Certificate *Xbe_certificate; + + std::string GenHexRow(uint08*, const uint08, const uint08); + std::string utf8_to_ascii(const wchar_t*); + std::string AllowedMediaToString(); + std::string GameRatingToString(); + + std::string GenDumpHeader(); + + std::string GenXbeHeaderInfo(); + std::string GenDigitalSignature(); + std::string GenGeneralHeaderInfo1(); + std::string GenInitFlags(); + std::string GenGeneralHeaderInfo2(); + + std::string GenXbeCertificateInfo(); + std::string GenCertificateHeader(); + std::string GenAlternateTitleIDs(); + std::string GenMediaInfo(); + std::string GenLANKey(); + std::string GenSignatureKey(); + std::string GenAlternateSignatureKeys(); + + std::string GenSectionInfo(); + std::string GenSectionHeaders(); + std::string GenSectionFlags(Xbe::SectionHeader); + std::string GenSectionDigest(Xbe::SectionHeader); + + std::string GenLibraryVersions(); + std::string GenLibraryFlags(Xbe::LibraryVersion); + + std::string GenTLS(); +}; + // debug/retail XOR keys const uint32 XOR_EP_DEBUG = 0x94859D4B; // Entry Point (Debug) const uint32 XOR_EP_RETAIL = 0xA8FC57AB; // Entry Point (Retail) diff --git a/src/Cxbx/WndMain.cpp b/src/Cxbx/WndMain.cpp index db200becb..e853f8cc4 100644 --- a/src/Cxbx/WndMain.cpp +++ b/src/Cxbx/WndMain.cpp @@ -1006,32 +1006,21 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP // dump xbe information to file { - FILE *TxtFile = fopen(ofn.lpstrFile, "wt"); - - // verify file was opened - if (TxtFile == 0) - MessageBox(m_hwnd, "Could not open text file.", "Cxbx-Reloaded", MB_ICONSTOP | MB_OK); - else - { - m_Xbe->DumpInformation(TxtFile); - - fclose(TxtFile); - - if (m_Xbe->HasError()) - { - MessageBox(m_hwnd, m_Xbe->GetError().c_str(), "Cxbx-Reloaded", MB_ICONSTOP | MB_OK); - } - else - { - char buffer[255]; - - sprintf(buffer, "%s's .xbe info was successfully dumped.", m_Xbe->m_szAsciiTitle); - - printf("WndMain: %s\n", buffer); - - MessageBox(m_hwnd, buffer, "Cxbx-Reloaded", MB_ICONINFORMATION | MB_OK); - } - } + bool success = m_Xbe->DumpInformationToFile(ofn.lpstrFile); + if (m_Xbe->HasError()) { + MessageBox(m_hwnd, m_Xbe->GetError().c_str(), "Cxbx-Reloaded", MB_ICONSTOP | MB_OK); + } + else { + if(success) { + char buffer[255]; + sprintf(buffer, "%s's .xbe info was successfully dumped.", m_Xbe->m_szAsciiTitle); + printf("WndMain: %s\n", buffer); + MessageBox(m_hwnd, buffer, "Cxbx-Reloaded", MB_ICONINFORMATION | MB_OK); + } + else { + MessageBox(m_hwnd, "Could not open Xbe text file.", "Cxbx-Reloaded", MB_ICONSTOP | MB_OK); + } + } } } } @@ -1039,8 +1028,7 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP case ID_EDIT_DUMPXBEINFOTO_DEBUGCONSOLE: { - // dump xbe information to debug console - m_Xbe->DumpInformation(stdout); + m_Xbe->DumpInformationToConsole(); if (m_Xbe->HasError()) { @@ -1050,7 +1038,7 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP { char buffer[255]; - sprintf(buffer, "%s's .xbe info was successfully dumped.", m_Xbe->m_szAsciiTitle); + sprintf(buffer, "%s's .xbe info was successfully dumped to console.", m_Xbe->m_szAsciiTitle); printf("WndMain: %s\n", buffer); }