diff --git a/Source/Delphi/src/Headers/XbeHeaders.pas b/Source/Delphi/src/Headers/XbeHeaders.pas index da75582b..24d99a2c 100644 --- a/Source/Delphi/src/Headers/XbeHeaders.pas +++ b/Source/Delphi/src/Headers/XbeHeaders.pas @@ -52,6 +52,9 @@ interface dwXAPILibraryVersionAddr: DWord; // 0x016C - xapi library version address dwLogoBitmapAddr: DWord; // 0x0170 - logo bitmap address dwSizeofLogoBitmap: DWord; // 0x0174 - logo bitmap size + dwExtraLibraryVersionsAddr: DWord; // 0x0178 + dwExtraLibraryVersions: DWord; // 0x017C + dwUnknown: DWord; // 0x0180 end; XBEIMAGE_HEADER = _XBEIMAGE_HEADER; PXBEIMAGE_HEADER = ^XBEIMAGE_HEADER; @@ -75,6 +78,8 @@ interface bzLanKey: XBOX_KEY_DATA; // 0x00B0 - lan key bzSignatureKey: XBOX_KEY_DATA; // 0x00C0 - signature key bzTitleAlternateSignatureKey: array [0..XBEIMAGE_ALTERNATE_TITLE_ID_COUNT-1] of XBOX_KEY_DATA; // 0x00D0 - alternate signature keys + dwOriginalSizeOfCertificate: DWord; + dwOnlineServiceName: DWord; end; XBE_CERTIFICATE = _XBE_CERTIFICATE; PXBE_CERTIFICATE = ^XBE_CERTIFICATE; @@ -133,7 +138,7 @@ interface wMajorVersion: Word; // major version wMinorVersion: Word; // minor version wBuildVersion: Word; // build version - dwFlags: array [0..1] of Byte; + wFlags: Word; { struct Flags { uint16 QFEVersion : 13; // QFE Version diff --git a/Source/Delphi/src/Tools/XBEExplorer/uXBEExplorerMain.pas b/Source/Delphi/src/Tools/XBEExplorer/uXBEExplorerMain.pas index 0b7b77e0..3497c253 100644 --- a/Source/Delphi/src/Tools/XBEExplorer/uXBEExplorerMain.pas +++ b/Source/Delphi/src/Tools/XBEExplorer/uXBEExplorerMain.pas @@ -629,7 +629,7 @@ procedure TFormXBEExplorer.actSaveAsExecute(Sender: TObject); procedure TFormXBEExplorer.About1Click(Sender: TObject); begin TaskMessageDlg('About ' + Application.Title, - Application.Title + ' version ' + _XBE_EXPLORER_VERSION + ' '#$A9' 2011-2017, PatrickvL. Released under GPL3.'#13#13 + + Application.Title + ' version ' + _XBE_EXPLORER_VERSION + ' '#$A9' 2011-2018, PatrickvL. Released under GPL3.'#13#13 + Application.Title + ' is part of Dxbx - the Delphi Xbox1 emulator.'#13#13 + 'Website : http://github.com/PatrickvL/Dxbx', mtInformation, [mbOK], 0); @@ -715,14 +715,15 @@ procedure TFormXBEExplorer.LibVersionClick(Sender: TObject); Grid := TStringGrid(Sender); i := Grid.Row - Grid.FixedRows; - i := (i * SizeOf(TXbeLibraryVersion)) + MyXBE.m_Header.dwLibraryVersionsAddr - MyXBE.m_Header.dwBaseAddr; + i := (i * SizeOf(TXbeLibraryVersion)) + DWord(Grid.Tag) - MyXBE.m_Header.dwBaseAddr; - Grid.Cells[1, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).szName)); - Grid.Cells[2, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wMajorVersion)); - Grid.Cells[3, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wMinorVersion)); - Grid.Cells[4, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wBuildVersion)); - Grid.Cells[5, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).dwFlags)); -end; + Grid.Cells[1, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).szName)); + Grid.Cells[2, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wMajorVersion)); + Grid.Cells[3, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wMinorVersion)); + Grid.Cells[4, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wBuildVersion)); + Grid.Cells[5, 2] := DWord2Str(i + FIELD_OFFSET(PXbeLibraryVersion(nil).wFlags)); + Grid.Cells[6, 2] := ''; +end; // LibVersionClick function SortByColumn(Item1, Item2: TListItem; Data: Integer): Integer; stdcall; begin @@ -817,8 +818,6 @@ procedure TFormXBEExplorer.UpdateSymbolListView; end; end; -// LibVersionClick - procedure TFormXBEExplorer.HandleGridDrawCell(Sender: TObject; aCol, aRow: Integer; Rect: TRect; State: TGridDrawState); var @@ -830,6 +829,12 @@ procedure TFormXBEExplorer.HandleGridDrawCell(Sender: TObject; aCol, aRow: Integ and (aCol = TStringGrid(Sender).ColCount - 1) and (TStringGrid(Sender).Cells[aCol, 0] = 'Meaning') then begin + // RowSelect-ed text is always drawn left-aligned; + // Since this cannot seem to be altered, avoid drawing twice : + if goRowSelect in TStringGrid(Sender).Options then + if gdSelected in State then + Exit; + // Redraw cell, but right-aligned : TStringGrid(Sender).Canvas.FillRect(Rect); Str := TStringGrid(Sender).Cells[aCol, aRow]; @@ -1069,6 +1074,8 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; begin Result := TMemo.Create(Self); Result.SetTextBuf(PChar(string(aIni))); + Result.ScrollBars := ssBoth; + Result.Font.Name := 'Consolas'; end; function _Initialize_KernelThunkTable( @@ -1084,7 +1091,7 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; Result := NewGrid(1, ['Entry', 'Thunk', 'Symbol name']); // TODO : Add symbol type (func/variable), column sorting ability NrEntries := 0; - KernelThunkTable := PDWORD(IntPtr(aSectionData) + aKernelThunkOffset); + KernelThunkTable := PDWORD(UIntPtr(aSectionData) + aKernelThunkOffset); while KernelThunkTable[NrEntries] <> 0 do begin KernelThunkNumber := KernelThunkTable[NrEntries] and $7FFFFFFF; @@ -1153,6 +1160,14 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; GridAddRow(Result, ['dwXAPILibraryVersionAddr', 'Dword', _offset(PXbeHeader(nil).dwXAPILibraryVersionAddr), DWord2Str(Hdr.dwXAPILibraryVersionAddr)]); GridAddRow(Result, ['dwLogoBitmapAddr', 'Dword', _offset(PXbeHeader(nil).dwLogoBitmapAddr), DWord2Str(Hdr.dwLogoBitmapAddr)]); GridAddRow(Result, ['dwSizeofLogoBitmap', 'Dword', _offset(PXbeHeader(nil).dwSizeofLogoBitmap), DWord2Str(Hdr.dwSizeofLogoBitmap), BytesToString(Hdr.dwSizeofLogoBitmap)]); + if Hdr.dwSizeofImageHeader > FIELD_OFFSET(PXbeHeader(nil).dwExtraLibraryVersionsAddr) then + GridAddRow(Result, ['dwExtraLibraryVersionsAddr', 'Dword', _offset(PXbeHeader(nil).dwExtraLibraryVersionsAddr), DWord2Str(Hdr.dwExtraLibraryVersionsAddr)]); + + if Hdr.dwSizeofImageHeader > FIELD_OFFSET(PXbeHeader(nil).dwExtraLibraryVersions) then + GridAddRow(Result, ['dwExtraLibraryVersions', 'Dword', _offset(PXbeHeader(nil).dwExtraLibraryVersions), DWord2Str(Hdr.dwExtraLibraryVersions)]); + + if Hdr.dwSizeofImageHeader > FIELD_OFFSET(PXbeHeader(nil).dwUnknown) then + GridAddRow(Result, ['dwUnknown', 'Dword', _offset(PXbeHeader(nil).dwUnknown), DWord2Str(Hdr.dwUnknown)]); _AddRange(0, SizeOf(TXbeHeader), 'XBE Header'); _AddRange(Hdr.dwCertificateAddr - Hdr.dwBaseAddr, SizeOf(TXbeCertificate), 'Certificate'); @@ -1188,6 +1203,12 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; GridAddRow(Result, ['bzSignatureKey', 'Byte[16]', _offset(PXbeCertificate(nil).bzSignatureKey, o), PByteToHexString(@Cert.bzSignatureKey[0], 16)]); for i := Low(Cert.bzTitleAlternateSignatureKey) to High(Cert.bzTitleAlternateSignatureKey) do GridAddRow(Result, ['bzTitleAlternateSignatureKey[' + IntToStr(i) + ']', 'Byte[16]', _offset(PXbeCertificate(nil).bzTitleAlternateSignatureKey[i], o), PByteToHexString(@Cert.bzTitleAlternateSignatureKey[i][0], 16)]); + + if Cert.dwSize > FIELD_OFFSET(PXbeCertificate(nil).dwOriginalSizeOfCertificate) then + GridAddRow(Result, ['dwOriginalSizeOfCertificate', 'Dword', _offset(PXbeCertificate(nil).dwOriginalSizeOfCertificate, o), DWord2Str(Cert.dwOriginalSizeOfCertificate), BytesToString(Cert.dwOriginalSizeOfCertificate)]); + + if Cert.dwSize > FIELD_OFFSET(PXbeCertificate(nil).dwOnlineServiceName) then + GridAddRow(Result, ['dwOnlineServiceName', 'Dword', _offset(PXbeCertificate(nil).dwOnlineServiceName, o), DWord2Str(Cert.dwOnlineServiceName), string(PCharToString(@Cert.dwOnlineServiceName, 4))]); end; // _Initialize_Certificate function _Initialize_SectionHeaders: TPanel; @@ -1197,6 +1218,8 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; ItemName: string; Splitter: TSplitter; SectionViewer: TSectionViewer; + SharedRefCountStart: DWord; + SharedRefCountEnd: DWord; begin if Length(MyXBE.m_SectionHeader) = 0 then begin @@ -1217,6 +1240,8 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; GridAddRow(SectionsGrid, [' ', 'Type:', 'Dword', 'Dword', 'Dword', 'Dword', 'Dword', 'Dword', 'Dword', 'Dword', 'Dword', 'Byte[20]']); GridAddRow(SectionsGrid, ['Section', 'Offset', '-Click row-']); // This is the offset-row + SharedRefCountStart := MaxInt; + SharedRefCountEnd := 0; o := MyXBE.m_Header.dwSectionHeadersAddr - MyXBE.m_Header.dwBaseAddr; for i := 0 to Length(MyXBE.m_SectionHeader) - 1 do begin @@ -1242,7 +1267,8 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; if Assigned(MyXBE.m_bzSection[i]) then begin // Add image tab when this section seems to contain a XPR resource : - if PXPR_IMAGE(MyXBE.m_bzSection[i]).hdr.Header.dwMagic = XPR_MAGIC_VALUE then + if (PXPR_IMAGE(MyXBE.m_bzSection[i]).hdr.Header.dwMagic = XPR0_MAGIC_VALUE) + or (PXPR_IMAGE(MyXBE.m_bzSection[i]).hdr.Header.dwMagic = XPR1_MAGIC_VALUE) then _CreateNode(NodeResources, 'Image ' + ItemName, _Initialize_XPRSection(PXPR_IMAGE(MyXBE.m_bzSection[i]))); @@ -1259,6 +1285,15 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; {aSectionData=}MyXBE.m_bzSection[i], {aSectionRawAddr=}Hdr.dwRawAddr, {aKernelThunkOffset=}KernelThunkAddress - Hdr.dwVirtualAddr)); + + // Determine start and end addresses of the shared refcount words : + if Hdr.dwHeadSharedRefCountAddr > 0 then + if SharedRefCountStart > Hdr.dwHeadSharedRefCountAddr then + SharedRefCountStart := Hdr.dwHeadSharedRefCountAddr; + + if Hdr.dwTailSharedRefCountAddr > 0 then + if SharedRefCountEnd < Hdr.dwTailSharedRefCountAddr then + SharedRefCountEnd := Hdr.dwTailSharedRefCountAddr; end; _AddRange(o, SizeOf(TXbeSectionHeader), 'SectionHeader ' + ItemName); @@ -1271,6 +1306,9 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; Inc(o, SizeOf(TXbeSectionHeader)); end; + if SharedRefCountStart < SharedRefCountEnd then + _AddRange(SharedRefCountStart - MyXBE.m_Header.dwBaseAddr, SharedRefCountEnd + SizeOf(Word) - SharedRefCountStart, 'SectionSharedRefCounts'); + // Resize SectionsGrid to fit into 40% of the height or less : ResizeGrid(SectionsGrid, 0.4); @@ -1283,24 +1321,46 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; SectionViewer.Parent := Result; SectionViewer.Align := alClient; - SectionsGrid.Tag := Integer(SectionViewer); + SectionsGrid.Tag := NativeInt(SectionViewer); SectionsGrid.OnClick := SectionClick; end; // _Initialize_SectionHeaders - function _Initialize_LibraryVersions: TStringGrid; + function LibraryVersionFlagsToString(const aFlags: Word): string; + var + QFEVersion: Word; + begin + QFEVersion := aFlags and ((1 shl 13) - 1); // wFlags shr 3; + + Result := 'QFEVersion:' + IntToStr(QFEVersion); + if (aFlags and XBE_LIBRARYVERSION_FLAG_DebugBuild) > 0 then + Result := Result + ' Debug, ' + else + Result := Result + ' Retail, '; + + if (aFlags and XBE_LIBRARYVERSION_FLAG_ApprovedYes) > 0 then + Result := Result + 'Approved' + else + if (aFlags and XBE_LIBRARYVERSION_FLAG_ApprovedPossibly) > 0 then + Result := Result + 'Possibly Approved' + else + Result := Result + 'Unapproved'; + end; + + function _Initialize_LibraryVersions(const aLibraryVersion: XBE_LIBRARYVERSIONs; const dwLibraryVersionsAddr: DWord): TStringGrid; var o: DWord; i: Integer; LibVer: PXbeLibraryVersion; ItemName: string; begin - if Length(MyXBE.m_LibraryVersion) = 0 then + if Length(aLibraryVersion) = 0 then begin Result := nil; Exit; end; - Result := NewGrid(1, ['Member:', 'szName', 'wMajorVersion', 'wMinorVersion', 'wBuildVersion', 'dwFlags']); + Result := NewGrid(1, ['Member:', 'szName', 'wMajorVersion', 'wMinorVersion', 'wBuildVersion', 'wFlags', 'Meaning']); + Result.Tag := NativeInt(dwLibraryVersionsAddr); Result.RowCount := 4; Result.Options := Result.Options + [goRowSelect]; Result.FixedRows := 3; @@ -1308,10 +1368,10 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; GridAddRow(Result, ['Type:', 'Char[8]', 'Word', 'Word', 'Word', 'Byte[2]']); GridAddRow(Result, ['Offset', '-Click row-']); // This is the offset-row - o := MyXBE.m_Header.dwLibraryVersionsAddr - MyXBE.m_Header.dwBaseAddr; - for i := 0 to Length(MyXBE.m_LibraryVersion) - 1 do + o := DWord(Result.Tag) - MyXBE.m_Header.dwBaseAddr; + for i := 0 to Length(aLibraryVersion) - 1 do begin - LibVer := @(MyXBE.m_LibraryVersion[i]); + LibVer := @(aLibraryVersion[i]); ItemName := string(PCharToString(PAnsiChar(@LibVer.szName[0]), 8)); GridAddRow(Result, [ DWord2Str(o), @@ -1319,7 +1379,8 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; DWord2Str(LibVer.wMajorVersion), DWord2Str(LibVer.wMinorVersion), IntToStr(LibVer.wBuildVersion), - PByteToHexString(@LibVer.dwFlags[0], 2) + PByteToHexString(@LibVer.wFlags, 2), + LibraryVersionFlagsToString(LibVer.wFlags) ]); _AddRange(o, SizeOf(TXbeLibraryVersion), 'LibraryVersion ' + ItemName); @@ -1439,7 +1500,8 @@ function TFormXBEExplorer.OpenFile(const aFilePath: string): Boolean; _CreateNode(NodeXBEHeader, 'Certificate', _Initialize_Certificate); _CreateNode(NodeXBEHeader, 'Section Headers', _Initialize_SectionHeaders); // Also adds various resource nodes - _CreateNode(NodeXBEHeader, 'Library Versions', _Initialize_LibraryVersions); + _CreateNode(NodeXBEHeader, 'Library Versions', _Initialize_LibraryVersions(MyXBE.m_LibraryVersion, MyXBE.m_Header.dwLibraryVersionsAddr)); + _CreateNode(NodeXBEHeader, 'Extra Library Versions', _Initialize_LibraryVersions(MyXBE.m_ExtraLibraryVersion, MyXBE.m_Header.dwExtraLibraryVersionsAddr)); _CreateNode(NodeXBEHeader, 'TLS', _Initialize_TLS); _CreateNode(Node0, 'Contents', _Initialize_HexViewer); diff --git a/Source/Delphi/src/uConsts.pas b/Source/Delphi/src/uConsts.pas index b0976e7b..25c8a35f 100644 --- a/Source/Delphi/src/uConsts.pas +++ b/Source/Delphi/src/uConsts.pas @@ -89,11 +89,11 @@ interface XBE_SECTIONHEADER_FLAG_HeadPageRO = $00000010; XBE_SECTIONHEADER_FLAG_TailPageRO = $00000020; - XBE_LIBRARYVERSION_FLAG_ApprovedNo = $00; - XBE_LIBRARYVERSION_FLAG_ApprovedPossibly = $20; - XBE_LIBRARYVERSION_FLAG_ApprovedYes = $40; - XBE_LIBRARYVERSION_FLAG_ApprovedMask = $60; - XBE_LIBRARYVERSION_FLAG_DebugBuild = $80; + XBE_LIBRARYVERSION_FLAG_ApprovedNo = $0000; + XBE_LIBRARYVERSION_FLAG_ApprovedPossibly = $2000; + XBE_LIBRARYVERSION_FLAG_ApprovedYes = $4000; + XBE_LIBRARYVERSION_FLAG_ApprovedMask = $6000; + XBE_LIBRARYVERSION_FLAG_DebugBuild = $8000; XBE_DebugUnicodeFileName_MAXLENGTH = 40; // ?? 256; diff --git a/Source/Delphi/src/uFileSystem.pas b/Source/Delphi/src/uFileSystem.pas index ac19e454..b52e1dc6 100644 --- a/Source/Delphi/src/uFileSystem.pas +++ b/Source/Delphi/src/uFileSystem.pas @@ -294,7 +294,7 @@ function TMappedFolderFileSystem.Open(const aFilePath: string): TFileHandle; f: THandle; begin Result := nil; - f := THandle(FileOpen(MountPoint + '\' + aFilePath, fmOpenRead)); + f := THandle(FileOpen(MountPoint + '\' + aFilePath, fmOpenRead or fmShareDenyWrite)); if f = THandle(-1) then begin // Handle GetLastError diff --git a/Source/Delphi/src/uXbe.pas b/Source/Delphi/src/uXbe.pas index f4f63533..f7ddfd69 100644 --- a/Source/Delphi/src/uXbe.pas +++ b/Source/Delphi/src/uXbe.pas @@ -61,6 +61,8 @@ interface // setup... but even if this happens, we could still use the FileSystem abstraction // but bypass it for the special cases (which means we can only do this on MappedFolders) type + XBE_LIBRARYVERSIONs = array of XBE_LIBRARYVERSION; + TXbe = class(TObject) private MyFile: TMemoryStream; @@ -75,7 +77,8 @@ TXbe = class(TObject) m_Header: XBEIMAGE_HEADER; m_HeaderEx: array of Byte; m_KernelLibraryVersion: XBE_LIBRARYVERSION; - m_LibraryVersion: array of XBE_LIBRARYVERSION; + m_LibraryVersion: XBE_LIBRARYVERSIONs; + m_ExtraLibraryVersion: XBE_LIBRARYVERSIONs; m_SectionHeader: array of XBE_SECTIONHEADER; m_szSectionName: array of array of AnsiChar; // TODO -oDXBX: Use XBE_SECTIONNAME_MAXLENGTH m_TLS: PXBE_TLS; @@ -372,6 +375,7 @@ procedure TXbe.ConstructorInit; SetLength(m_SectionHeader, 0); SetLength(m_szSectionName, 0); SetLength(m_LibraryVersion, 0); + SetLength(m_ExtraLibraryVersion, 0); FreeMem({var}m_TLS); SetLength(m_bzSection, 0); end; // TXbe.ConstructorInit @@ -535,26 +539,48 @@ constructor TXbe.Create(const aFileName: string); WriteLog(DxbxFormat('DXBX: Reading Library Version 0x%.4x... OK', [lIndex])); end; // for LIndex + end; - // read xbe kernel library version - WriteLog('DXBX: Reading Kernel Library Version...'); - if m_Header.dwKernelLibraryVersionAddr = 0 then - MessageDlg('Could not locate kernel library version', mtError, [mbOk], 0); - + // read xbe kernel library version + WriteLog('DXBX: Reading Kernel Library Version...'); + if m_Header.dwKernelLibraryVersionAddr = 0 then + MessageDlg('Could not locate kernel library version', mtError, [mbOk], 0) + else + begin i := m_Header.dwKernelLibraryVersionAddr - m_Header.dwBaseAddr; CopyMemory({Dest=}@m_KernelLibraryVersion, {Source=}@(RawData[i]), SizeOf(XBE_LIBRARYVERSION)); WriteLog(DxbxFormat('DXBX: Kernel Library Version = %d... OK', [m_KernelLibraryVersion.wBuildVersion])); + end; - // read xbe xapi library version - WriteLog('DXBX: Reading Xapi Library Version...'); - if m_Header.dwXAPILibraryVersionAddr = 0 then - MessageDlg('Could not locate Xapi Library Version', mtError, [mbOk], 0); - + // read xbe xapi library version + WriteLog('DXBX: Reading Xapi Library Version...'); + if m_Header.dwXAPILibraryVersionAddr = 0 then + MessageDlg('Could not locate Xapi Library Version', mtError, [mbOk], 0) + else + begin i := m_Header.dwXAPILibraryVersionAddr - m_Header.dwBaseAddr; CopyMemory({Dest=}@m_XAPILibraryVersion, {Source=}@(RawData[i]), SizeOf(XBE_LIBRARYVERSION)); WriteLog(DxbxFormat('DXBX: XAPI Library Version = %d... OK', [m_XAPILibraryVersion.wBuildVersion])); end; + // Does the header contain extra library versions? + if m_Header.dwSizeofImageHeader > FIELD_OFFSET(PXbeHeader(nil).dwExtraLibraryVersions) then + // Read xbe extra library versions + if m_Header.dwExtraLibraryVersionsAddr <> 0 then + begin + WriteLog('DXBX: Reading Extra Library Versions...'); + + i := m_Header.dwExtraLibraryVersionsAddr - m_Header.dwBaseAddr; + SetLength(m_ExtraLibraryVersion, m_Header.dwExtraLibraryVersions); + for lIndex := 0 to m_Header.dwExtraLibraryVersions - 1 do + begin + CopyMemory(@(m_ExtraLibraryVersion[lIndex]), @(RawData[i]), SizeOf(m_ExtraLibraryVersion[lIndex])); + Inc(i, SizeOf(m_ExtraLibraryVersion[lIndex])); + + WriteLog(DxbxFormat('DXBX: Reading Extra Library Version 0x%.4x... OK', [lIndex])); + end; // for LIndex + end; + // read Xbe sections begin WriteLog('DXBX: Reading Sections...'); @@ -687,7 +713,7 @@ function TXbe.DumpInformation(FileName: string): Boolean; lIndex, lIndex2: Integer; TmpStr: string; StrAsciiFileName: string; - Flag: Byte; + Flag: Word; // BIndex: Byte; QVersion: Word; @@ -919,10 +945,9 @@ function TXbe.DumpInformation(FileName: string): Boolean; //Some bit maths the QVersion Flag is only 13 bits long so i convert the 13 bits to a number - QVersion := m_LibraryVersion[lIndex].dwFlags[0] - + ((m_LibraryVersion[lIndex].dwFlags[1] and 31) shl 8); + QVersion := m_LibraryVersion[lIndex].wFlags and ((1 shl 13) - 1); - Flag := m_LibraryVersion[lIndex].dwFlags[1] and (not 31); + Flag := m_LibraryVersion[lIndex].wFlags; TmpStr := DxbxFormat('Flags : QFEVersion : 0x%.4x, ', [QVersion]); @@ -1209,7 +1234,8 @@ function TXbe.ExportXPRToBitmap(XprImage: PXPR_IMAGE; aBitmap: TBitmap): Boolean Result := False; // Check if it's an XPR (Xbox Packed Resources) : - if XprImage.hdr.Header.dwMagic = XPR_MAGIC_VALUE then + if (XprImage.hdr.Header.dwMagic = XPR0_MAGIC_VALUE) + or (XprImage.hdr.Header.dwMagic = XPR1_MAGIC_VALUE) then begin // Determine image dimensions : Width := 1 shl ((XprImage.hdr.Texture.Format and X_D3DFORMAT_USIZE_MASK) shr X_D3DFORMAT_USIZE_SHIFT); @@ -1218,32 +1244,34 @@ function TXbe.ExportXPRToBitmap(XprImage: PXPR_IMAGE; aBitmap: TBitmap): Boolean // Prepare easy access to the bitmap data : aBitmap.SetSize(Width, Height); if (XprImage.hdr.Header.dwTotalSize - XprImage.hdr.Header.dwHeaderSize)/Width/Height = 2 then - begin // 16 bit per pixel textures - aBitmap.PixelFormat := pf16bit; - Scanlines16.Initialize(aBitmap); - - // Read the texture into the 16bit bitmap : - Result := ReadD3D16bitTextureFormatIntoBitmap( - {Format=}(XprImage.hdr.Texture.Format and X_D3DFORMAT_FORMAT_MASK) shr X_D3DFORMAT_FORMAT_SHIFT, - {Data=}PBytes(@(XprImage.pBits[0])), - {DataSize=}XprImage.hdr.Header.dwTotalSize - XprImage.hdr.Header.dwHeaderSize, - {Output=}@Scanlines16); - end else - begin // 32 bit per pixel textures - aBitmap.PixelFormat := pf32bit; - Scanlines32.Initialize(aBitmap); - - // Read the texture into the 32bit bitmap : - Result := ReadD3DTextureFormatIntoBitmap( - {Format=}(XprImage.hdr.Texture.Format and X_D3DFORMAT_FORMAT_MASK) shr X_D3DFORMAT_FORMAT_SHIFT, - {Data=}PBytes(@(XprImage.pBits[0])), - {DataSize=}XprImage.hdr.Header.dwTotalSize - XprImage.hdr.Header.dwHeaderSize, - {Output=}@Scanlines32); - end; + begin // 16 bit per pixel textures + aBitmap.PixelFormat := pf16bit; + Scanlines16.Initialize(aBitmap); + + // Read the texture into the 16bit bitmap : + Result := ReadD3D16bitTextureFormatIntoBitmap( + {Format=}(XprImage.hdr.Texture.Format and X_D3DFORMAT_FORMAT_MASK) shr X_D3DFORMAT_FORMAT_SHIFT, + {Data=}PBytes(@(XprImage.pBits[0])), + {DataSize=}XprImage.hdr.Header.dwTotalSize - XprImage.hdr.Header.dwHeaderSize, + {Output=}@Scanlines16); + end + else + begin // 32 bit per pixel textures + aBitmap.PixelFormat := pf32bit; + Scanlines32.Initialize(aBitmap); + + // Read the texture into the 32bit bitmap : + Result := ReadD3DTextureFormatIntoBitmap( + {Format=}(XprImage.hdr.Texture.Format and X_D3DFORMAT_FORMAT_MASK) shr X_D3DFORMAT_FORMAT_SHIFT, + {Data=}PBytes(@(XprImage.pBits[0])), + {DataSize=}XprImage.hdr.Header.dwTotalSize - XprImage.hdr.Header.dwHeaderSize, + {Output=}@Scanlines32); + end; + Exit; end; -// TODO -oDXBX: Check for 'DDS' format, and read that too, perhaps using these resources : +// TODO -oDXBX: Check for 'DDS ' format, and read that too, perhaps using these resources : // http://www.imageconverterplus.com/help-center/about-icp/supported-formats/dds/ // http://archive.netbsd.se/view_attachment.php?id=2463254.32112 // if StrLPas(PAnsiChar(@XprImage.hdr.Header.dwMagic), 3) = 'DDS' then