Cxbx-Reloaded/Source/Core/Xbe.cpp

1651 lines
61 KiB
C++

// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Core->Xbe.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
// *
// * All rights reserved
// *
// ******************************************************************
#include "Xbe.h"
#include "Exe.h"
#include <memory.h>
#include <locale.h>
#include <stdlib.h>
#include <time.h>
// ******************************************************************
// * constructor
// ******************************************************************
Xbe::Xbe(const char *x_szFilename)
{
char szBuffer[255];
ConstructorInit();
printf("Xbe::Xbe: Opening Xbe file...");
FILE *XbeFile = fopen(x_szFilename, "rb");
// ******************************************************************
// * verify xbe file was opened
// ******************************************************************
if(XbeFile == 0)
{
SetError("Could not open Xbe file.", true);
return;
}
printf("OK\n");
// ******************************************************************
// * read xbe image header
// ******************************************************************
{
printf("Xbe::Xbe: Reading Image Header...");
if(fread(&m_Header, sizeof(m_Header), 1, XbeFile) != 1)
{
SetError("Unexpected end of file while reading Xbe Image Header", true);
goto cleanup;
}
if(m_Header.dwMagic != *(uint32 *)"XBEH")
{
SetError("Invalid magic number in Xbe file", true);
goto cleanup;
}
printf("OK\n");
}
// ******************************************************************
// * read xbe image header extra bytes
// ******************************************************************
if(m_Header.dwSizeofHeaders > sizeof(m_Header))
{
printf("Xbe::Xbe: Reading Image Header Extra Bytes...");
uint32 ExSize = RoundUp(m_Header.dwSizeofHeaders, 0x1000) - sizeof(m_Header);
m_HeaderEx = new char[ExSize];
if(fread(m_HeaderEx, ExSize, 1, XbeFile) != 1)
{
SetError("Unexpected end of file while reading Xbe Image Header (Ex)", true);
goto cleanup;
}
printf("OK\n");
}
// ******************************************************************
// * read xbe certificate
// ******************************************************************
{
printf("Xbe::Xbe: Reading Certificate...");
fseek(XbeFile, m_Header.dwCertificateAddr - m_Header.dwBaseAddr, SEEK_SET);
if(fread(&m_Certificate, sizeof(m_Certificate), 1, XbeFile) != 1)
{
SetError("Unexpected end of file while reading Xbe Certificate", true);
goto cleanup;
}
setlocale( LC_ALL, "English" );
wcstombs(m_szAsciiTitle, m_Certificate.wszTitleName, 40);
printf("OK\n");
printf("Xbe::Xbe: Title identified as %s\n", m_szAsciiTitle);
}
// ******************************************************************
// * read xbe section headers
// ******************************************************************
{
printf("Xbe::Xbe: Reading Section Headers...\n");
fseek(XbeFile, m_Header.dwSectionHeadersAddr - m_Header.dwBaseAddr, SEEK_SET);
m_SectionHeader = new SectionHeader[m_Header.dwSections];
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Xbe: Reading Section Header 0x%.04X...", v);
if(fread(&m_SectionHeader[v], sizeof(*m_SectionHeader), 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected end of file while reading Xbe Section Header %d (%Xh)", v, v);
SetError(szBuffer, true);
goto cleanup;
}
printf("OK\n");
}
}
// ******************************************************************
// * read xbe section names
// ******************************************************************
{
printf("Xbe::Xbe: Reading Section Names...\n");
m_szSectionName = new char[m_Header.dwSections][9];
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Xbe: Reading Section Name 0x%.04X...", v);
uint08 *sn = GetAddr(m_SectionHeader[v].dwSectionNameAddr);
memset(m_szSectionName[v], 0, 9);
if(sn != 0)
{
for(int b=0;b<8;b++)
{
m_szSectionName[v][b] = sn[b];
if(m_szSectionName[v][b] == '\0')
break;
}
}
printf("OK (%s)\n", m_szSectionName[v]);
}
}
// ******************************************************************
// * read xbe library versions
// ******************************************************************
if(m_Header.dwLibraryVersionsAddr != 0)
{
printf("Xbe::Xbe: Reading Library Versions...\n");
fseek(XbeFile, m_Header.dwLibraryVersionsAddr - m_Header.dwBaseAddr, SEEK_SET);
m_LibraryVersion = new LibraryVersion[m_Header.dwLibraryVersions];
for(uint32 v=0;v<m_Header.dwLibraryVersions;v++)
{
printf("Xbe::Xbe: Reading Library Version 0x%.04X...", v);
if(fread(&m_LibraryVersion[v], sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected end of file while reading Xbe Library Version %d (%Xh)", v, v);
SetError(szBuffer, true);
goto cleanup;
}
printf("OK\n");
}
// ******************************************************************
// * read xbe kernel library version
// ******************************************************************
{
printf("Xbe::Xbe: Reading Kernel Library Version...");
if(m_Header.dwKernelLibraryVersionAddr == 0)
{
SetError("Could not locate kernel library version", true);
goto cleanup;
}
fseek(XbeFile, m_Header.dwKernelLibraryVersionAddr - m_Header.dwBaseAddr, SEEK_SET);
m_KernelLibraryVersion = new LibraryVersion;
if(fread(m_KernelLibraryVersion, sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
SetError("Unexpected end of file while reading Xbe Kernel Version", true);
goto cleanup;
}
printf("OK\n");
}
// ******************************************************************
// * read xbe xapi library version
// ******************************************************************
{
printf("Xbe::Xbe: Reading Xapi Library Version...");
if(m_Header.dwXAPILibraryVersionAddr == 0)
{
SetError("Could not locate Xapi Library Version", true);
goto cleanup;
}
fseek(XbeFile, m_Header.dwXAPILibraryVersionAddr - m_Header.dwBaseAddr, SEEK_SET);
m_XAPILibraryVersion = new LibraryVersion;
if(fread(m_XAPILibraryVersion, sizeof(*m_LibraryVersion), 1, XbeFile) != 1)
{
SetError("Unexpected end of file while reading Xbe Xapi Version", true);
goto cleanup;
}
printf("OK\n");
}
}
// ******************************************************************
// * read xbe sections
// ******************************************************************
{
printf("Xbe::Xbe: Reading Sections...\n");
m_bzSection = new uint08*[m_Header.dwSections];
memset(m_bzSection, 0, m_Header.dwSections);
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Xbe: Reading Section 0x%.04X...", v);
uint32 RawSize = m_SectionHeader[v].dwSizeofRaw;
uint32 RawAddr = m_SectionHeader[v].dwRawAddr;
m_bzSection[v] = new uint08[RawSize];
fseek(XbeFile, RawAddr, SEEK_SET);
if(RawSize == 0)
{
printf("OK\n");
continue;
}
if(fread(m_bzSection[v], RawSize, 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected end of file while reading Xbe Section %d (%Xh) (%s)", v, v, m_szSectionName[v]);
SetError(szBuffer, true);
goto cleanup;
}
printf("OK\n");
}
}
// ******************************************************************
// * read xbe thread local storage
// ******************************************************************
if(m_Header.dwTLSAddr != 0)
{
printf("Xbe::Xbe: Reading Thread Local Storage...");
void *Addr = GetAddr(m_Header.dwTLSAddr);
if(Addr == 0)
{
SetError("Could not locate Thread Local Storage", true);
goto cleanup;
}
m_TLS = new TLS;
memcpy(m_TLS, Addr, sizeof(*m_TLS));
printf("OK\n");
}
cleanup:
if(GetError() != 0)
{
printf("FAILED!\n");
printf("Xbe::Xbe: ERROR -> %s\n", GetError());
}
fclose(XbeFile);
return;
}
// ******************************************************************
// * constructor
// ******************************************************************
Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail)
{
ConstructorInit();
time_t CurrentTime;
time(&CurrentTime);
printf("Xbe::Xbe: Pass 1 (Simple Pass)...");
// ******************************************************************
// * Pass 1
// ******************************************************************
{
// ******************************************************************
// * standard xbe magic number
// ******************************************************************
m_Header.dwMagic = *(uint32*)"XBEH";
// ******************************************************************
// * nobody has the private key yet, so zero this out
// ******************************************************************
memset(m_Header.pbDigitalSignature, 0, 256);
// ******************************************************************
// * we'll only allow 0x00010000 for now
// ******************************************************************
m_Header.dwBaseAddr = 0x00010000;
// ******************************************************************
// * this is a constant
// ******************************************************************
m_Header.dwSizeofImageHeader = sizeof(m_Header);
// ******************************************************************
// * we'll have the same number of sections as the .exe,
// ******************************************************************
m_Header.dwSections = x_Exe->m_Header.m_sections;
// ******************************************************************
// * TODO: allow configuration
// ******************************************************************
{
memset(&m_Header.dwInitFlags, 0, sizeof(m_Header.dwInitFlags));
m_Header.dwInitFlags.bLimit64MB = true;
m_Header.dwInitFlags.bDontSetupHarddisk = false;
m_Header.dwInitFlags.bMountUtilityDrive = true;
}
// ******************************************************************
// * various pe copies
// ******************************************************************
{
m_Header.dwPeStackCommit = 0x00010000; //x_Exe->m_OptionalHeader.m_sizeof_stack_commit;
m_Header.dwPeHeapReserve = x_Exe->m_OptionalHeader.m_sizeof_heap_reserve;
m_Header.dwPeHeapCommit = x_Exe->m_OptionalHeader.m_sizeof_heap_commit;
m_Header.dwPeSizeofImage = x_Exe->m_OptionalHeader.m_sizeof_image;
m_Header.dwPeChecksum = 0x00000000;
m_Header.dwPeTimeDate = x_Exe->m_Header.m_timedate;
}
// ******************************************************************
// * build time/date
// ******************************************************************
m_Header.dwTimeDate = CurrentTime;
// ******************************************************************
// * TODO: generate valid addr if necessary
// ******************************************************************
m_Header.dwNonKernelImportDirAddr = 0;
// ******************************************************************
// * TODO: generate these values
// ******************************************************************
m_Header.dwLibraryVersions = 0;
m_Header.dwLibraryVersionsAddr = 0;
m_Header.dwKernelLibraryVersionAddr = 0;
m_Header.dwXAPILibraryVersionAddr = 0;
}
printf("OK\n");
printf("Xbe::Xbe: Pass 2 (Calculating Requirements)...");
// ******************************************************************
// * Pass 2
// ******************************************************************
{
// ******************************************************************
// * make room cursor
// ******************************************************************
uint32 mrc = m_Header.dwBaseAddr + sizeof(m_Header);
// ******************************************************************
// * make room for certificate
// ******************************************************************
{
m_Header.dwCertificateAddr = mrc;
mrc += sizeof(m_Certificate);
}
// ******************************************************************
// * make room for section headers
// ******************************************************************
{
m_Header.dwSectionHeadersAddr = mrc;
mrc += m_Header.dwSections * (sizeof(*m_SectionHeader));
// ******************************************************************
// * make room for head / tail reference count words
// ******************************************************************
mrc += (m_Header.dwSections+1)*2;
// ******************************************************************
// * make room for section names
// ******************************************************************
for(uint32 v=0;v<m_Header.dwSections;v++)
{
uint32 s = 0;
while(s < 8 && x_Exe->m_SectionHeader[v].m_name[s] != '\0')
s++;
mrc += s + 1;
}
}
// ******************************************************************
// * TODO: make room for library versions
// ******************************************************************
{
}
// ******************************************************************
// * make room for debug path / debug file names
// ******************************************************************
{
// TODO: allow this to be configured, right now we will
// just null out these values
m_Header.dwDebugUnicodeFilenameAddr = mrc;
m_Header.dwDebugPathnameAddr = mrc;
m_Header.dwDebugFilenameAddr = mrc;
mrc += 2;
}
// ******************************************************************
// * make room for largest possible logo bitmap
// ******************************************************************
{
mrc = RoundUp(mrc, 0x10);
m_Header.dwLogoBitmapAddr = mrc;
m_Header.dwSizeofLogoBitmap = 100*17; // Max Possible
mrc += m_Header.dwSizeofLogoBitmap;
}
// ******************************************************************
// * update size of headers
// ******************************************************************
m_Header.dwSizeofHeaders = mrc - m_Header.dwBaseAddr;
}
printf("OK\n");
printf("Xbe::Xbe: Pass 3 (Generating Xbe)...\n");
// ******************************************************************
// * Pass 3
// ******************************************************************
{
m_Header.dwPeBaseAddr = m_Header.dwBaseAddr + RoundUp(m_Header.dwSizeofHeaders, 0x1000) - x_Exe->m_SectionHeader[0].m_virtual_addr;
// ******************************************************************
// * encode entry point
// ******************************************************************
{
printf("Xbe::Xbe: Encoding %s Entry Point...", x_bRetail?"Retail":"Debug");
uint32 ep = x_Exe->m_OptionalHeader.m_entry + m_Header.dwPeBaseAddr;
if(x_bRetail)
ep ^= XOR_EP_RETAIL;
else
ep ^= XOR_EP_DEBUG;
m_Header.dwEntryAddr = ep;
printf("OK (0x%.08X)\n", ep);
}
// ******************************************************************
// * header write cursor
// ******************************************************************
uint32 hwc = m_Header.dwBaseAddr + sizeof(m_Header);
// ******************************************************************
// * check if we need to store extra header bytes (we always will)
// ******************************************************************
if(m_Header.dwSizeofHeaders > sizeof(m_Header))
{
printf("Xbe::Xbe: Found Extra Header Bytes...");
uint32 ExSize = RoundUp(m_Header.dwSizeofHeaders - sizeof(m_Header), 0x1000);
m_HeaderEx = new char[ExSize];
printf("OK\n");
}
// ******************************************************************
// * start a write buffer inside header_ex
// ******************************************************************
char *szBuffer = m_HeaderEx;
// ******************************************************************
// * write certificate
// ******************************************************************
{
// ******************************************************************
// * certificate size is a constant
// ******************************************************************
m_Certificate.dwSize = sizeof(m_Certificate);
m_Certificate.dwTimeDate = CurrentTime;
// ******************************************************************
// * TODO: generate in the form CX-9999
// ******************************************************************
m_Certificate.dwTitleId = 0xFFFF0002;
// ******************************************************************
// * title name
// ******************************************************************
{
memset(m_Certificate.wszTitleName, 0, 40);
mbstowcs(m_Certificate.wszTitleName, x_szTitle, 40);
}
// ******************************************************************
// * zero out alternate ids
// ******************************************************************
{
for(uint32 c=0;c<0x10;c++)
m_Certificate.dwAlternateTitleId[c] = 0;
}
// ******************************************************************
// * for now we'll just allow any media you could want
// ******************************************************************
m_Certificate.dwAllowedMedia = XBEIMAGE_MEDIA_TYPE_HARD_DISK | XBEIMAGE_MEDIA_TYPE_DVD_CD | XBEIMAGE_MEDIA_TYPE_MEDIA_BOARD;
// ******************************************************************
// * TODO: allow configuration
// ******************************************************************
m_Certificate.dwGameRegion = XBEIMAGE_GAME_REGION_MANUFACTURING | XBEIMAGE_GAME_REGION_NA | XBEIMAGE_GAME_REGION_JAPAN | XBEIMAGE_GAME_REGION_RESTOFWORLD;
// ******************************************************************
// * TODO: allow configuration
// ******************************************************************
m_Certificate.dwGameRatings = 0xFFFFFFFF;
// ******************************************************************
// * always disk 0, AFAIK
// ******************************************************************
m_Certificate.dwDiskNumber = 0;
// ******************************************************************
// * TODO: allow configuration
// ******************************************************************
m_Certificate.dwVersion = 0;
// ******************************************************************
// * generate blank lan, signature, and alternate signature keys
// ******************************************************************
{
for(uint32 v=0;v<0x10;v++)
m_Certificate.bzLanKey[v] = m_Certificate.bzSignatureKey[v] = 0;
for(uint32 x=0;x<0x10;x++)
for(uint32 y=0;y<0x10;y++)
m_Certificate.bzTitleAlternateSignatureKey[x][y] = 0;
}
// ******************************************************************
// * write certificate
// ******************************************************************
{
memcpy(szBuffer, &m_Certificate, sizeof(m_Certificate));
szBuffer += sizeof(m_Certificate);
hwc += sizeof(m_Certificate);
}
}
// ******************************************************************
// * generate ascii title from certificate title name
// ******************************************************************
{
setlocale( LC_ALL, "English" );
wcstombs(m_szAsciiTitle, m_Certificate.wszTitleName, 40);
}
// ******************************************************************
// * write section headers / section names
// ******************************************************************
{
m_szSectionName = new char[m_Header.dwSections][9];
m_SectionHeader = new SectionHeader[m_Header.dwSections];
uint32 SectionCursor = RoundUp(m_Header.dwSizeofHeaders, 0x1000);
// ******************************************************************
// * head / tail reference count write buffer
// ******************************************************************
uint16 *htrc = (uint16*)(szBuffer + m_Header.dwSections*sizeof(*m_SectionHeader));
// ******************************************************************
// * section write buffer
// ******************************************************************
char *secn = (char*)((uint32)htrc + (m_Header.dwSections+1)*2);
// ******************************************************************
// * head / tail reference count write cursor
// ******************************************************************
uint32 hwc_htrc = hwc + m_Header.dwSections*sizeof(*m_SectionHeader);
// ******************************************************************
// * section write cursor
// ******************************************************************
uint32 hwc_secn = hwc_htrc + (m_Header.dwSections+1)*2;
printf("Xbe::Xbe: Generating Section Headers...\n");
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Xbe: Generating Section Header %.04X...", v);
uint32 characteristics = x_Exe->m_SectionHeader[v].m_characteristics;
memset(&m_SectionHeader[v].dwFlags, 0, sizeof(m_SectionHeader->dwFlags));
if(characteristics & IMAGE_SCN_MEM_WRITE)
m_SectionHeader[v].dwFlags.bWritable = true;
if( (characteristics & IMAGE_SCN_MEM_EXECUTE) || (characteristics & IMAGE_SCN_CNT_CODE) )
m_SectionHeader[v].dwFlags.bExecutable = true;
m_SectionHeader[v].dwFlags.bPreload = true;
m_SectionHeader[v].dwVirtualAddr = x_Exe->m_SectionHeader[v].m_virtual_addr + m_Header.dwPeBaseAddr;
if(v < m_Header.dwSections-1)
m_SectionHeader[v].dwVirtualSize = x_Exe->m_SectionHeader[v+1].m_virtual_addr - x_Exe->m_SectionHeader[v].m_virtual_addr;
else
m_SectionHeader[v].dwVirtualSize = RoundUp(x_Exe->m_SectionHeader[v].m_virtual_size, 4);
m_SectionHeader[v].dwRawAddr = SectionCursor;
// ******************************************************************
// * calculate sizeof_raw...this is done by locating the last non-
// * -zero value in the raw section data
// ******************************************************************
{
uint32 r = x_Exe->m_SectionHeader[v].m_sizeof_raw - 1;
while(r > 0)
{
if(x_Exe->m_bzSection[v][r--] != 0)
break;
}
// word aligned
m_SectionHeader[v].dwSizeofRaw = RoundUp(r+2, 4);
}
SectionCursor += RoundUp(m_SectionHeader[v].dwSizeofRaw, 0x1000);
// ******************************************************************
// * head / tail reference count
// ******************************************************************
{
m_SectionHeader[v].dwHeadSharedRefCountAddr = hwc_htrc;
htrc[v] = 0;
hwc_htrc += 2;
m_SectionHeader[v].dwTailSharedRefCountAddr = hwc_htrc;
htrc[v+1] = 0;
}
// ******************************************************************
// * section name
// ******************************************************************
{
uint32 s = 0;
memset(secn, 0, 8);
m_SectionHeader[v].dwSectionNameAddr = hwc_secn;
while(s < 8 && x_Exe->m_SectionHeader[v].m_name[s] != '\0')
{
m_szSectionName[v][s] = secn[s] = x_Exe->m_SectionHeader[v].m_name[s];
s++;
}
m_szSectionName[v][s] = '\0';
secn += s+1;
hwc_secn += s+1;
}
m_SectionHeader[v].dwSectionRefCount = 0;
// ******************************************************************
// * write section digest (just zeros)
// ******************************************************************
memset(m_SectionHeader[v].bzSectionDigest, 0, 20);
// ******************************************************************
// * write section header
// ******************************************************************
memcpy(szBuffer, &m_SectionHeader[v], sizeof(*m_SectionHeader));
szBuffer += sizeof(*m_SectionHeader);
printf("OK\n");
}
hwc = hwc_secn;
}
// ******************************************************************
// * write debug path / debug file names
// ******************************************************************
{
*(uint16*)szBuffer = 0x0000;
szBuffer += 2;
hwc += 2;
}
// ******************************************************************
// * write default "OpenXDK" logo bitmap
// ******************************************************************
{
printf("Xbe::Xbe: Generating \"OpenXDK\" Logo Bitmap...");
uint08 *RawAddr = GetAddr(m_Header.dwLogoBitmapAddr);
memset(RawAddr, 0, 100*17);
memcpy(RawAddr, OpenXDK, dwSizeOfOpenXDK);
m_Header.dwSizeofLogoBitmap = dwSizeOfOpenXDK;
printf("OK\n");
}
// ******************************************************************
// * write sections
// ******************************************************************
{
printf("Xbe::Xbe: Generating Sections...\n");
m_bzSection = new uint08*[m_Header.dwSections];
memset(m_bzSection, 0, m_Header.dwSections);
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Xbe: Generating Section %.04X...", v);
uint32 RawSize = m_SectionHeader[v].dwSizeofRaw;
m_bzSection[v] = new uint08[RawSize];
memcpy(m_bzSection[v], x_Exe->m_bzSection[v], RawSize);
printf("OK\n");
}
}
}
printf("Xbe::Xbe: Pass 4 (Finalizing)...\n");
// ******************************************************************
// * Pass 4
// ******************************************************************
{
m_Header.dwSizeofImage = m_SectionHeader[m_Header.dwSections-1].dwVirtualAddr + m_SectionHeader[m_Header.dwSections-1].dwVirtualSize - m_Header.dwBaseAddr;
m_Header.dwTLSAddr = 0;
// ******************************************************************
// * Relocate to base : 0x00010000
// ******************************************************************
{
printf("Xbe::Xbe: Relocating to Base 0x00010000...");
uint32 fixCount = 0;
uint32 relo_addr = x_Exe->m_OptionalHeader.m_image_data_directory[5].m_virtual_addr;
uint32 relo_size = x_Exe->m_OptionalHeader.m_image_data_directory[5].m_size;
uint32 dwBaseDiff = m_Header.dwPeBaseAddr - x_Exe->m_OptionalHeader.m_image_base;
uint08 *reloc = GetAddr(relo_addr + m_Header.dwPeBaseAddr);
// ******************************************************************
// * relocate, if necessary
// ******************************************************************
if(reloc != 0)
{
uint32 v = 0;
// ******************************************************************
// * relocate each relocation block
// ******************************************************************
while(v < relo_size)
{
uint32 block_addr = *(uint32 *)&reloc[v+0];
uint32 block_stop = *(uint32 *)&reloc[v+4] + v;
v += 8;
// ******************************************************************
// * relocate each rva
// ******************************************************************
while(v < block_stop && v < relo_size)
{
uint16 data = *(uint16 *)&reloc[v];
uint32 type = (data & 0xF000) >> 12;
if(type == 0)
{
v+=2;
break;
}
// ******************************************************************
// * 32-bit field relocation
// ******************************************************************
if(type == IMAGE_REL_BASED_HIGHLOW)
{
fixCount++;
uint32 dwFixAddr = block_addr + (data & 0x0FFF) + m_Header.dwPeBaseAddr;
uint08 *bzModRVA = GetAddr(dwFixAddr);
if(bzModRVA != 0)
*(uint32*)bzModRVA += dwBaseDiff;
}
else
{
SetError("Unsupported relocation type", true);
goto cleanup;
}
v+=2;
}
}
}
printf("OK (%d Fixups)\n", fixCount);
}
// ******************************************************************
// * Locate kernel thunk table
// ******************************************************************
{
uint32 kt = x_Exe->m_OptionalHeader.m_image_data_directory[12].m_virtual_addr + m_Header.dwPeBaseAddr;
if(x_bRetail)
kt ^= XOR_KT_RETAIL;
else
kt ^= XOR_KT_DEBUG;
m_Header.dwKernelImageThunkAddr = kt;
}
}
cleanup:
if(GetError() != 0)
{
printf("FAILED!\n");
printf("Xbe::Xbe: ERROR -> %s\n", GetError());
}
return;
}
// ******************************************************************
// * deconstructor
// ******************************************************************
Xbe::~Xbe()
{
if(m_bzSection != 0)
{
for(uint32 v=0;v<m_Header.dwSections;v++)
delete[] m_bzSection[v];
delete[] m_bzSection;
}
delete m_XAPILibraryVersion;
delete m_KernelLibraryVersion;
delete[] m_LibraryVersion;
delete m_TLS;
delete[] m_szSectionName;
delete[] m_SectionHeader;
delete[] m_HeaderEx;
}
// ******************************************************************
// * Export
// ******************************************************************
void Xbe::Export(const char *x_szXbeFilename)
{
if(GetError() != 0)
return;
char szBuffer[255];
printf("Xbe::Export: Writing Xbe file...");
FILE *XbeFile = fopen(x_szXbeFilename, "wb");
// ******************************************************************
// * verify xbe file was opened
// ******************************************************************
if(XbeFile == 0)
{
SetError("Could not open .xbe file.", false);
return;
}
printf("OK\n");
// ******************************************************************
// * write xbe image header
// ******************************************************************
{
printf("Xbe::Export: Writing Image Header...");
if(fwrite(&m_Header, sizeof(m_Header), 1, XbeFile) != 1)
{
SetError("Unexpected write error while writing Xbe Image Header", false);
goto cleanup;
}
printf("OK\n");
printf("Xbe::Export: Writing Image Header Extra Bytes...");
if(fwrite(m_HeaderEx, m_Header.dwSizeofHeaders, 1, XbeFile) != 1)
{
SetError("Unexpected write error while writing Xbe Image Header (Ex)", false);
goto cleanup;
}
printf("OK\n");
}
// ******************************************************************
// * write xbe certificate
// ******************************************************************
{
printf("Xbe::Export: Writing Certificate...");
fseek(XbeFile, m_Header.dwCertificateAddr - m_Header.dwBaseAddr, SEEK_SET);
if(fwrite(&m_Certificate, sizeof(m_Certificate), 1, XbeFile) != 1)
{
SetError("Unexpected write error while writing Xbe Certificate", false);
goto cleanup;
}
printf("OK\n");
}
// ******************************************************************
// * write xbe section headers
// ******************************************************************
{
printf("Xbe::Export: Writing Section Headers...\n");
fseek(XbeFile, m_Header.dwSectionHeadersAddr - m_Header.dwBaseAddr, SEEK_SET);
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Export: Writing Section Header 0x%.04X...", v);
if(fwrite(&m_SectionHeader[v], sizeof(*m_SectionHeader), 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected write error while writing Xbe Section %d (%Xh)", v, v);
SetError(szBuffer, false);
goto cleanup;
}
printf("OK\n");
}
}
// ******************************************************************
// * write xbe sections
// ******************************************************************
{
printf("Xbe::Export: Writing Sections...\n");
for(uint32 v=0;v<m_Header.dwSections;v++)
{
printf("Xbe::Export: Writing Section 0x%.04X (%s)...", v, m_szSectionName[v]);
uint32 RawSize = m_SectionHeader[v].dwSizeofRaw;
uint32 RawAddr = m_SectionHeader[v].dwRawAddr;
fseek(XbeFile, RawAddr, SEEK_SET);
if(RawSize == 0)
{
printf("OK\n");
continue;
}
if(fwrite(m_bzSection[v], RawSize, 1, XbeFile) != 1)
{
sprintf(szBuffer, "Unexpected write error while writing Xbe Section %d (%Xh) (%s)", v, v, m_szSectionName[v]);
SetError(szBuffer, false);
goto cleanup;
}
printf("OK\n");
}
}
// ******************************************************************
// * zero pad
// ******************************************************************
{
printf("Xbe::Export: Writing Zero Padding...");
fpos_t pos;
uint32 remaining = 0;
fgetpos(XbeFile, &pos);
remaining = (uint32)(0x1000 - ftell(XbeFile)%0x1000);
// ******************************************************************
// * write remaining bytes
// ******************************************************************
{
char *szBuffer = new char[remaining];
for(uint32 v=0;v<remaining;v++)
szBuffer[v] = 0;
fwrite(szBuffer, remaining, 1, XbeFile);
delete[] szBuffer;
}
printf("OK\n");
}
cleanup:
// ******************************************************************
// * if we came across an error, delete the file we were creating
// ******************************************************************
if(GetError() != 0)
{
remove(x_szXbeFilename);
printf("FAILED!\n");
printf("Xbe::Export: ERROR -> %s\n", GetError());
}
fclose(XbeFile);
}
// ******************************************************************
// * ConstructorInit
// ******************************************************************
void Xbe::ConstructorInit()
{
m_HeaderEx = 0;
m_SectionHeader = 0;
m_szSectionName = 0;
m_LibraryVersion = 0;
m_KernelLibraryVersion = 0;
m_XAPILibraryVersion = 0;
m_TLS = 0;
m_bzSection = 0;
}
// ******************************************************************
// * BetterTime
// ******************************************************************
static char *BetterTime(char *x_ctime)
{
int v=0;
for(v=0;x_ctime[v] != '\n';v++);
x_ctime[v] = '\0';
return x_ctime;
}
// ******************************************************************
// * DumpInformation
// ******************************************************************
void Xbe::DumpInformation(FILE *x_file)
{
if(GetError() != 0)
return;
fprintf(x_file, "XBE information generated by CXBX (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 : <Hex Dump>");
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 </Hex Dump>\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(ctime((const long*)&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);
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(ctime((time_t*)&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(ctime((time_t*)&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 titles
// ******************************************************************
{
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\n", m_Certificate.dwAllowedMedia);
fprintf(x_file, "Game Region : 0x%.08X\n", m_Certificate.dwGameRegion);
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 alternative signature keys
// ******************************************************************
{
fprintf(x_file, "Title Alternative Signature Keys : <Hex Dump>");
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 </Hex Dump>\n");
}
fprintf(x_file, "\n");
fprintf(x_file, "Dumping XBE Section Headers...\n");
fprintf(x_file, "\n");
// ******************************************************************
// * print section headers
// ******************************************************************
{
for(uint32 v=0;v<m_Header.dwSections;v++)
{
fprintf(x_file, "Section Name : 0x%.08X (\"%s\")\n", m_SectionHeader[v].dwSectionNameAddr, m_szSectionName[v]);
// ******************************************************************
// * print flags
// ******************************************************************
{
fprintf(x_file, "Flags : 0x%.08X ", m_SectionHeader[v].dwFlags);
if(m_SectionHeader[v].dwFlags.bWritable)
fprintf(x_file, "(Writable) ");
if(m_SectionHeader[v].dwFlags.bPreload)
fprintf(x_file, "(Preload) ");
if(m_SectionHeader[v].dwFlags.bExecutable)
fprintf(x_file, "(Executable) ");
if(m_SectionHeader[v].dwFlags.bInsertedFile)
fprintf(x_file, "(Inserted File) ");
if(m_SectionHeader[v].dwFlags.bHeadPageRO)
fprintf(x_file, "(Head Page RO) ");
if(m_SectionHeader[v].dwFlags.bTailPageRO)
fprintf(x_file, "(Tail Page RO) ");
fprintf(x_file, "\n");
}
fprintf(x_file, "Virtual Address : 0x%.08X\n", m_SectionHeader[v].dwVirtualAddr);
fprintf(x_file, "Virtual Size : 0x%.08X\n", m_SectionHeader[v].dwVirtualSize);
fprintf(x_file, "Raw Address : 0x%.08X\n", m_SectionHeader[v].dwRawAddr);
fprintf(x_file, "Size of Raw : 0x%.08X\n", m_SectionHeader[v].dwSizeofRaw);
fprintf(x_file, "Section Name Address : 0x%.08X\n", m_SectionHeader[v].dwSectionNameAddr);
fprintf(x_file, "Section Reference Count : 0x%.08X\n", m_SectionHeader[v].dwSectionRefCount);
fprintf(x_file, "Head Shared Reference Count Addr : 0x%.08X\n", m_SectionHeader[v].dwHeadSharedRefCountAddr);
fprintf(x_file, "Tail Shared Reference Count Addr : 0x%.08X\n", m_SectionHeader[v].dwTailSharedRefCountAddr);
// ******************************************************************
// * print section digest
// ******************************************************************
{
fprintf(x_file, "Section Digest : ");
for(int s=0;s<20;s++)
fprintf(x_file, "%.02X", m_SectionHeader[v].bzSectionDigest[s]);
fprintf(x_file, "\n");
}
fprintf(x_file, "\n");
}
}
fprintf(x_file, "Dumping XBE Library Versions...\n");
fprintf(x_file, "\n");
// ******************************************************************
// * print library versions
// ******************************************************************
{
if(m_LibraryVersion == 0 || m_Header.dwLibraryVersions == 0)
{
fprintf(x_file, "(This XBE contains no Library Versions)\n");
fprintf(x_file, "\n");
}
else
{
for(uint32 v=0;v<m_Header.dwLibraryVersions;v++)
{
char tmp[9];
for(uint32 c=0;c<8;c++)
tmp[c] = m_LibraryVersion[v].szName[c];
tmp[8] = '\0';
fprintf(x_file, "Library Name : %s\n", tmp);
fprintf(x_file, "Version : %d.%d.%d\n", m_LibraryVersion[v].wMajorVersion, m_LibraryVersion[v].wMinorVersion, m_LibraryVersion[v].wBuildVersion);
// ******************************************************************
// * print flags
// ******************************************************************
{
fprintf(x_file, "Flags : ");
fprintf(x_file, "QFEVersion : 0x%.04X, ", m_LibraryVersion[v].dwFlags.QFEVersion);
if(m_LibraryVersion[v].dwFlags.bDebugBuild)
fprintf(x_file, "Debug, ");
else
fprintf(x_file, "Retail, ");
switch(m_LibraryVersion[v].dwFlags.Approved)
{
case 0:
fprintf(x_file, "Unapproved");
break;
case 1:
fprintf(x_file, "Possibly Approved");
break;
case 2:
fprintf(x_file, "Approved");
break;
}
fprintf(x_file, "\n");
}
fprintf(x_file, "\n");
}
}
}
fprintf(x_file, "Dumping XBE TLS...\n");
fprintf(x_file, "\n");
// ******************************************************************
// * print thread local storage
// ******************************************************************
if(m_TLS != 0)
{
fprintf(x_file, "Data Start Address : 0x%.08X\n", m_TLS->dwDataStartAddr);
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");
}
}
// ******************************************************************
// * ImportLogoBitmap
// ******************************************************************
void Xbe::ImportLogoBitmap(const uint08 x_Gray[100*17])
{
char *LogoBuffer = new char[4*1024];
uint32 LogoSize = 0;
// ******************************************************************
// * encode logo bitmap
// ******************************************************************
{
for(uint32 v=1;v<100*17;LogoSize++)
{
char color = x_Gray[v] >> 4;
uint32 len = 1;
while(++v<100*17-1 && len < 1024 && color == x_Gray[v] >> 4)
len++;
LogoRLE *cur = (LogoRLE *)&LogoBuffer[LogoSize];
if(len <= 7)
{
cur->m_Eight.bType1 = 1;
cur->m_Eight.Len = len;
cur->m_Eight.Data = color;
}
else
{
cur->m_Sixteen.bType1 = 0;
cur->m_Sixteen.bType2 = 1;
cur->m_Sixteen.Len = len;
cur->m_Sixteen.Data = color;
LogoSize++;
}
}
}
// ******************************************************************
// * check if there is room to save this, it not then throw an error
// ******************************************************************
{
uint08 *RLE = GetLogoBitmap(LogoSize);
if(RLE == 0)
{
if(GetError() == 0)
SetError("Logo bitmap could not be imported (not enough space in file?)", false);
return;
}
memcpy(RLE, LogoBuffer, LogoSize);
}
return;
}
// ******************************************************************
// * ExportLogoBitmap
// ******************************************************************
// *
// * This algorithm was originally discovered by superfro. I couldnt
// * figure out what the hell the encoding format was before he gave
// * me the information:
// *
// * basically what is going on here is a single pass through the
// * bitmap data, with 2 possible encodings per rle chunk. data is
// * stored as 4 bit grayscale, so the logical approach is to expand
// * this to 8 bit using a simple 4 bit left shift (*16). However, it
// * has been suggested to me by superfro that you might calculate a
// * slightly darker image by multiplying by 15 and adding .5. It's
// * a toss up, but i've choosen a simple bit shift left.
// *
// ******************************************************************
void Xbe::ExportLogoBitmap(uint08 x_Gray[100*17])
{
memset(x_Gray, 0, 100*17);
uint32 dwLength = m_Header.dwSizeofLogoBitmap;
uint08 *RLE = GetAddr(m_Header.dwLogoBitmapAddr);
if(RLE == 0 || GetError())
return;
uint32 o = 0;
for(uint32 v=0;v<dwLength;v++)
{
uint32 len = 0, data = 0;
LogoRLE *cur = (LogoRLE *)&RLE[v];
if(cur->m_Eight.bType1)
{
len = cur->m_Eight.Len;
data = cur->m_Eight.Data;
}
else
{
if(cur->m_Sixteen.bType2)
{
len = cur->m_Sixteen.Len;
data = cur->m_Sixteen.Data;
v += 1;
}
}
for(uint32 j=0;j<len;j++)
{
o++;
if(o < 100*17)
x_Gray[o] = (char)(data << 4); // could use (int)(data * 15.0 + .5);
}
}
}
// ******************************************************************
// * GetAddr
// ******************************************************************
uint08 *Xbe::GetAddr(uint32 x_dwVirtualAddress)
{
uint32 dwOffs = x_dwVirtualAddress - m_Header.dwBaseAddr;
// ******************************************************************
// * offset in image header
// ******************************************************************
if(dwOffs < sizeof(m_Header))
return &((uint08*)&m_Header)[dwOffs];
// ******************************************************************
// * offset in image header extra bytes
// ******************************************************************
if(dwOffs < m_Header.dwSizeofHeaders)
return (uint08*)&m_HeaderEx[dwOffs - sizeof(m_Header)];
// ******************************************************************
// * offset in some random section
// ******************************************************************
{
for(uint32 v=0;v<m_Header.dwSections;v++)
{
uint32 VirtAddr = m_SectionHeader[v].dwVirtualAddr;
uint32 VirtSize = m_SectionHeader[v].dwVirtualSize;
if( (x_dwVirtualAddress >= VirtAddr) && (x_dwVirtualAddress < (VirtAddr + VirtSize)) )
return &m_bzSection[v][x_dwVirtualAddress - VirtAddr];
}
}
return 0;
}
// ******************************************************************
// * GetLogoBitmap
// ******************************************************************
uint08 *Xbe::GetLogoBitmap(uint32 x_dwSize)
{
uint32 dwOffs = m_Header.dwLogoBitmapAddr - m_Header.dwBaseAddr;
uint32 dwLength = m_Header.dwSizeofLogoBitmap;
if(dwOffs == 0 || dwLength == 0)
return 0;
// ******************************************************************
// * if this bitmap will fit inside the already existing one, we
// * don't need to resize anything in the xbe, just return a pointer
// ******************************************************************
if(dwLength >= x_dwSize)
{
// ******************************************************************
// * update size of headers, if necessary
// ******************************************************************
if(dwOffs < m_Header.dwSizeofHeaders)
{
m_Header.dwSizeofHeaders -= dwLength;
m_Header.dwSizeofHeaders += x_dwSize;
m_Header.dwSizeofLogoBitmap = x_dwSize;
return GetAddr(m_Header.dwLogoBitmapAddr);
}
}
return 0;
}