-
Notifications
You must be signed in to change notification settings - Fork 93
Added various features #655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 5 commits
bd30f4b
2f0deb5
c0a40d6
b62a0ae
fc892e7
25c32e4
e13a346
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| #include "Exe.h" | ||
| #include "Xbe.h" | ||
|
|
||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| // program entry point | ||
|
|
@@ -19,18 +20,34 @@ int main(int argc, char *argv[]) | |
| char szXbeFilename[OPTION_LEN + 1] = { 0 }; | ||
| char szDumpFilename[OPTION_LEN + 1] = { 0 }; | ||
| char szXbeTitle[OPTION_LEN + 1] = "Untitled"; | ||
| char szXbeTitleID[OPTION_LEN + 1] = ""; | ||
| char szXbeRegions[OPTION_LEN + 1] = ""; | ||
| char szXbeVersion[OPTION_LEN + 1] = ""; | ||
| char szMode[OPTION_LEN + 1] = "retail"; | ||
| char szLogo[OPTION_LEN + 1] = ""; | ||
| char szDebugPath[OPTION_LEN + 1] = ""; | ||
|
|
||
| bool bRetail; | ||
| uint32 dwTitleId = 0xFFFF0002; | ||
| uint32 dwRegions; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs to get initialized or lines 121+ will read undefined values.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does in line 141 under the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a different control flow path, I'm talking about 121+
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok I see |
||
| uint32 dwVersion; | ||
|
|
||
| const char *program = argv[0]; | ||
| const char *program_desc = "CXBE EXE to XBE (win32 to Xbox) Relinker (Version: " VERSION ")"; | ||
| Option options[] = { | ||
| { szExeFilename, NULL, "exefile" }, { szXbeFilename, "OUT", "filename" }, | ||
| { szDumpFilename, "DUMPINFO", "filename" }, { szXbeTitle, "TITLE", "title" }, | ||
| { szMode, "MODE", "{debug|retail}" }, { szLogo, "LOGO", "filename" }, | ||
| { szDebugPath, "DEBUGPATH", "path" }, { NULL } | ||
| { szExeFilename, NULL, "exefile" }, | ||
| { szXbeFilename, "OUT", "filename" }, | ||
| { szDumpFilename, "DUMPINFO", "filename" }, | ||
| { szXbeTitle, "TITLE", "title" }, | ||
| { szXbeTitleID, "TITLEID", "{%c%c-%u|%x}" }, | ||
| { szXbeRegions, "REGION", | ||
| "{-|[n][j][w][m]}\n" | ||
| " -=none, n=North America, j=Japan, w=world, m=manufacturing" }, | ||
| { szXbeVersion, "VERSION", "version" }, | ||
| { szMode, "MODE", "{debug|retail}" }, | ||
| { szLogo, "LOGO", "filename" }, | ||
| { szDebugPath, "DEBUGPATH", "path" }, | ||
| { NULL } | ||
| }; | ||
|
|
||
| if(ParseOptions(argv, argc, options, szErrorMessage)) | ||
|
|
@@ -54,6 +71,91 @@ int main(int argc, char *argv[]) | |
| szXbeTitle[40] = '\0'; | ||
| } | ||
|
|
||
| // interpret title id | ||
| if(szXbeTitleID[0]) | ||
| { | ||
| bool hex = true; | ||
| for(int i = 0; szXbeTitleID[i]; ++i) | ||
| { | ||
| if(szXbeTitleID[i] == '-') | ||
| { | ||
| hex = false; | ||
| break; | ||
| } | ||
| } | ||
| if(hex) | ||
| { | ||
| sscanf(szXbeTitleID, "%x", &dwTitleId); | ||
| } | ||
| else | ||
| { | ||
| char titlechar[2]; | ||
| unsigned titleno; | ||
|
Comment on lines
+93
to
+94
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a not explicitly unsigned char can lead to incorrect results when shifting, better use the types defined in
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will adding |
||
| if (sscanf(szXbeTitleID, "%c%c-%u", &titlechar[0], &titlechar[1], &titleno) != 3) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line doesn't follow clang-format rules.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll see about doing a rebase and running clang-format on all the commits |
||
| { | ||
| strncpy(szErrorMessage, "invalid TITLEID", ERROR_LEN); | ||
| goto cleanup; | ||
| } | ||
| if(titleno > 0xFFFF) | ||
| { | ||
| printf("WARNING: Title ID number too high (max is 65535)\n"); | ||
| titleno = 0xFFFF; | ||
| } | ||
| dwTitleId = (titlechar[0] << 24) | (titlechar[1] << 16) | titleno; | ||
| } | ||
| } | ||
|
|
||
| // interpret region flags | ||
| if(szXbeRegions[0]) | ||
| { | ||
| char c; | ||
| for(int i = 0; (c = szXbeRegions[i]); ++i) | ||
| { | ||
| switch(c) | ||
| { | ||
| case '-':; | ||
| dwRegions = 0; | ||
| goto breakfor; | ||
| case 'a':; | ||
| dwRegions = XBEIMAGE_GAME_REGION_NA | XBEIMAGE_GAME_REGION_JAPAN | | ||
| XBEIMAGE_GAME_REGION_RESTOFWORLD | | ||
| XBEIMAGE_GAME_REGION_MANUFACTURING; | ||
| goto breakfor; | ||
| case 'n':; | ||
| dwRegions |= XBEIMAGE_GAME_REGION_NA; | ||
| break; | ||
| case 'j':; | ||
| dwRegions |= XBEIMAGE_GAME_REGION_JAPAN; | ||
| break; | ||
| case 'w':; | ||
| dwRegions |= XBEIMAGE_GAME_REGION_RESTOFWORLD; | ||
| break; | ||
| case 'm':; | ||
| dwRegions |= XBEIMAGE_GAME_REGION_MANUFACTURING; | ||
| break; | ||
| default:; | ||
| printf("WARNING: Invalid region char: %c\n", c); | ||
| break; | ||
| } | ||
| } | ||
| breakfor:; | ||
| } | ||
| else | ||
| { | ||
| dwRegions = XBEIMAGE_GAME_REGION_NA | XBEIMAGE_GAME_REGION_JAPAN | | ||
| XBEIMAGE_GAME_REGION_RESTOFWORLD | XBEIMAGE_GAME_REGION_MANUFACTURING; | ||
| } | ||
|
|
||
| // interpret version | ||
| if(szXbeVersion[0]) | ||
| { | ||
| dwVersion = strtoul(szXbeVersion, NULL, 0); | ||
| } | ||
| else | ||
| { | ||
| dwVersion = 0; | ||
| } | ||
|
|
||
| // verify we received the required parameters | ||
| if(szExeFilename[0] == '\0') | ||
| { | ||
|
|
@@ -90,7 +192,8 @@ int main(int argc, char *argv[]) | |
| LogoPtr = &logo; | ||
| } | ||
|
|
||
| Xbe *XbeFile = new Xbe(ExeFile, szXbeTitle, bRetail, LogoPtr, szDebugPath); | ||
| Xbe *XbeFile = | ||
| new Xbe(ExeFile, szXbeTitle, dwTitleId, dwRegions, dwVersion, bRetail, LogoPtr, szDebugPath); | ||
|
|
||
| if(XbeFile->GetError() != 0) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,8 +32,8 @@ static size_t BasenameOffset(const std::string &path) | |
| } | ||
|
|
||
| // construct via Exe file object | ||
| Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vector<uint08> *logo, | ||
| const char *x_szDebugPath) | ||
| Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, uint32 x_dwTitleID, uint32 x_dwRegions, | ||
| uint32 x_dwVersion, bool x_bRetail, const std::vector<uint08> *logo, const char *x_szDebugPath) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not follow clang-format rules. |
||
| { | ||
| ConstructorInit(); | ||
|
|
||
|
|
@@ -125,8 +125,16 @@ Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vec | |
| { | ||
| uint32 s = 0; | ||
|
|
||
| while(s < 8 && x_Exe->m_SectionHeader[v].m_name[s] != '\0') | ||
| s++; | ||
| if(x_Exe->m_SectionHeader_longname[v].m_longname) | ||
| { | ||
| while(s < 255 && x_Exe->m_SectionHeader_longname[v].m_longname[s] != '\0') | ||
| s++; | ||
| } | ||
| else | ||
| { | ||
| while(s < 8 && x_Exe->m_SectionHeader[v].m_name[s] != '\0') | ||
| s++; | ||
| } | ||
|
|
||
| mrc += s + 1; | ||
| } | ||
|
|
@@ -271,8 +279,7 @@ Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vec | |
|
|
||
| m_Certificate.dwTimeDate = CurrentTime; | ||
|
|
||
| // TODO: generate in the form CX-9999 | ||
| m_Certificate.dwTitleId = 0xFFFF0002; | ||
| m_Certificate.dwTitleId = x_dwTitleID; | ||
|
|
||
| // title name | ||
| memset(m_Certificate.wszTitleName, 0, sizeof(m_Certificate.wszTitleName)); | ||
|
|
@@ -297,19 +304,15 @@ Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vec | |
| XBEIMAGE_MEDIA_TYPE_MEDIA_BOARD | XBEIMAGE_MEDIA_TYPE_NONSECURE_HARD_DISK | | ||
| XBEIMAGE_MEDIA_TYPE_NONSECURE_MODE; | ||
|
|
||
| // TODO: allow configuration | ||
| m_Certificate.dwGameRegion = XBEIMAGE_GAME_REGION_MANUFACTURING | | ||
| XBEIMAGE_GAME_REGION_NA | XBEIMAGE_GAME_REGION_JAPAN | | ||
| XBEIMAGE_GAME_REGION_RESTOFWORLD; | ||
| m_Certificate.dwGameRegion = x_dwRegions; | ||
|
Comment on lines
-300
to
+308
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change probably belongs to a different commit and breaks building this one.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably |
||
|
|
||
| // TODO: allow configuration | ||
| m_Certificate.dwGameRatings = 0xFFFFFFFF; | ||
|
|
||
| // always disk 0, AFAIK | ||
| m_Certificate.dwDiskNumber = 0; | ||
|
|
||
| // TODO: allow configuration | ||
| m_Certificate.dwVersion = 0; | ||
| m_Certificate.dwVersion = x_dwVersion; | ||
|
|
||
| // generate blank LAN, signature, and alternate signature keys | ||
| { | ||
|
|
@@ -345,7 +348,7 @@ Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vec | |
|
|
||
| // write section headers / section names | ||
| { | ||
| m_szSectionName = new char[m_Header.dwSections][9]; | ||
| m_szSectionName = new char[m_Header.dwSections][256]; | ||
|
|
||
| m_SectionHeader = new SectionHeader[m_Header.dwSections]; | ||
|
|
||
|
|
@@ -373,14 +376,27 @@ Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vec | |
|
|
||
| memset(&m_SectionHeader[v].dwFlags, 0, sizeof(m_SectionHeader->dwFlags)); | ||
|
|
||
| if(characteristics & IMAGE_SCN_MEM_WRITE) | ||
| m_SectionHeader[v].dwFlags.bWritable = true; | ||
| // check for $$XTIMAGE or $$XSIMAGE and set the correct flags | ||
| if(x_Exe->m_SectionHeader_longname[v].m_longname && | ||
| (!strcmp(x_Exe->m_SectionHeader_longname[v].m_longname, "$$XTIMAGE") || | ||
| !strcmp(x_Exe->m_SectionHeader_longname[v].m_longname, "$$XSIMAGE"))) | ||
|
Comment on lines
+382
to
+383
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not a fan of this hack. I'd rather like to see proper file insertion support in cxbe and something like
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is currently no code to do section insertion as far as i'm aware, and that could probably be removed later once there is code made to add sections.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There isn't, as I said I'd rather see it implemented than a name-based hack on top of violating the PE spec. nxdk does not require the usage of these sections nor does it implement the APIs relying on them yet, so we might as well take the time to do things properly.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have the time to write something like that and I need the feature now. Loading the image sections takes up ram to do nothing. This code can be removed later when the better code is added.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not really interested in nxdk acquiring even more technical debt. We haven't even gotten rid of the one inherited from OpenXDK yet. |
||
| { | ||
| m_SectionHeader[v].dwFlags.bInsertedFile = true; | ||
| m_SectionHeader[v].dwFlags.bHeadPageRO = true; | ||
| m_SectionHeader[v].dwFlags.bTailPageRO = true; | ||
|
Comment on lines
+385
to
+387
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How were these flag settings determined? They don't match Halo 2.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used an XBE header dumper on a few XBEs. I think it was Doom 3 and a Quake homebrew XBE I had laying around |
||
| } | ||
| else | ||
| { | ||
| 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; | ||
|
|
||
| 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].dwFlags.bPreload = true; | ||
| m_SectionHeader[v].dwVirtualAddr = | ||
| x_Exe->m_SectionHeader[v].m_virtual_addr + m_Header.dwPeBaseAddr; | ||
|
|
||
|
|
@@ -431,10 +447,21 @@ Xbe::Xbe(class Exe *x_Exe, const char *x_szTitle, bool x_bRetail, const std::vec | |
| memset(secn, 0, 8); | ||
|
|
||
| m_SectionHeader[v].dwSectionNameAddr = hwc_secn; | ||
| while(s < 8 && x_Exe->m_SectionHeader[v].m_name[s] != '\0') | ||
| if(x_Exe->m_SectionHeader_longname[v].m_longname) | ||
| { | ||
| m_szSectionName[v][s] = secn[s] = x_Exe->m_SectionHeader[v].m_name[s]; | ||
| s++; | ||
| while(s < 255 && x_Exe->m_SectionHeader_longname[v].m_longname[s] != '\0') | ||
| { | ||
| m_szSectionName[v][s] = secn[s] = x_Exe->m_SectionHeader_longname[v].m_longname[s]; | ||
| s++; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| 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'; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How was this commit tested?
In all my testing, I could not get lld-link to produce a section that exceeds 8 characters, even with trickery. This matches Microsoft's documentation, which says that executable images do not use a string table and do not support section names longer than 8 characters.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used objcopy to rename a section I made in some inline asm
XTIMAGE->$$XTIMAGEThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to say I'm not a fan, I'd rather stay a mile away from intentionally breaking the PE spec (or giving the impression that we support doing so).
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing with
/is documented in the spec on microsoft's page. While it says that long section names are not supported with executables, objcopy can still produce executables with long section names and they load and run just fine.Oh also debug sections use long section names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is documented as not being valid for executable images. While it may be possible to hack around the linker for that, it is breaking the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I added this because I actually need this to have a title image.
It would incorrectly add debug sections and the image sections as something like
/43which ofc would not be picked up by the dashboard as an icon.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.