Improve PICT compatibility, add batch mode to gpr2gpa

This commit is contained in:
elasota
2020-05-17 17:54:58 -04:00
parent 35308e41f3
commit 153213e079
19 changed files with 870 additions and 158 deletions

View File

@@ -47,98 +47,196 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unpacktool", "unpacktool\un
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ReleasePackageInstaller", "ReleasePackageInstaller\ReleasePackageInstaller.wixproj", "{D26BD501-28A7-4849-8130-FB5EA0A2B82F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsUnicodeToolShim", "WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj", "{15009625-1120-405E-8BBA-69A16CD6713D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Debug|x64.ActiveCfg = Debug|x64
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Debug|x64.Build.0 = Debug|x64
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Debug|x86.ActiveCfg = Debug|Win32
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Debug|x86.Build.0 = Debug|Win32
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Release|x64.ActiveCfg = Release|x64
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Release|x64.Build.0 = Release|x64
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Release|x86.ActiveCfg = Release|Win32
{45B1B18C-C846-4044-9206-74F58DFC5E88}.Release|x86.Build.0 = Release|Win32
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Debug|x64.ActiveCfg = Debug|x64
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Debug|x64.Build.0 = Debug|x64
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Debug|x86.ActiveCfg = Debug|Win32
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Debug|x86.Build.0 = Debug|Win32
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Release|x64.ActiveCfg = Release|x64
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Release|x64.Build.0 = Release|x64
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Release|x86.ActiveCfg = Release|Win32
{6EC62B0F-9353-40A4-A510-3788F1368B33}.Release|x86.Build.0 = Release|Win32
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Debug|x64.ActiveCfg = Debug|x64
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Debug|x64.Build.0 = Debug|x64
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Debug|x86.ActiveCfg = Debug|Win32
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Debug|x86.Build.0 = Debug|Win32
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Release|x64.ActiveCfg = Release|x64
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Release|x64.Build.0 = Release|x64
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Release|x86.ActiveCfg = Release|Win32
{2FF15659-5C72-48B8-B55B-3C658E4125B5}.Release|x86.Build.0 = Release|Win32
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Debug|x64.ActiveCfg = Debug|x64
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Debug|x64.Build.0 = Debug|x64
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Debug|x86.ActiveCfg = Debug|Win32
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Debug|x86.Build.0 = Debug|Win32
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Release|x64.ActiveCfg = Release|x64
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Release|x64.Build.0 = Release|x64
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Release|x86.ActiveCfg = Release|Win32
{6233C3F2-5781-488E-B190-4FA8836F5A77}.Release|x86.Build.0 = Release|Win32
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Debug|x64.ActiveCfg = Debug|x64
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Debug|x64.Build.0 = Debug|x64
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Debug|x86.ActiveCfg = Debug|Win32
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Debug|x86.Build.0 = Debug|Win32
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x64.ActiveCfg = Release|x64
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x64.Build.0 = Release|x64
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x86.ActiveCfg = Release|Win32
{5FDE4822-C771-46A5-B6B2-FD12BACE86BF}.Release|x86.Build.0 = Release|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x64.ActiveCfg = Debug|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x64.Build.0 = Debug|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x86.ActiveCfg = Debug|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Debug|x86.Build.0 = Debug|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x64.ActiveCfg = Release|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x64.Build.0 = Release|x64
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x86.ActiveCfg = Release|Win32
{99549E56-2B3A-4B0C-9A1F-FBA6395BC96C}.Release|x86.Build.0 = Release|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x64.ActiveCfg = Debug|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x64.Build.0 = Debug|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x86.ActiveCfg = Debug|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Debug|x86.Build.0 = Debug|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x64.ActiveCfg = Release|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x64.Build.0 = Release|x64
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x86.ActiveCfg = Release|Win32
{E3BDC783-8646-433E-ADF0-8B6390D36669}.Release|x86.Build.0 = Release|Win32
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Debug|x64.ActiveCfg = Debug|x64
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Debug|x64.Build.0 = Debug|x64
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Debug|x86.ActiveCfg = Debug|Win32
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Debug|x86.Build.0 = Debug|Win32
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Release|x64.ActiveCfg = Release|x64
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Release|x64.Build.0 = Release|x64
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Release|x86.ActiveCfg = Release|Win32
{A8FCDC5E-729C-4A80-BF9F-B669C52B2AE3}.Release|x86.Build.0 = Release|Win32
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Debug|x64.ActiveCfg = Debug|x64
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Debug|x64.Build.0 = Debug|x64
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Debug|x86.ActiveCfg = Debug|Win32
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Debug|x86.Build.0 = Debug|Win32
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Release|x64.ActiveCfg = Release|x64
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Release|x64.Build.0 = Release|x64
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Release|x86.ActiveCfg = Release|Win32
{487216D8-16BA-4B4C-B5BF-43FEEDFEE03A}.Release|x86.Build.0 = Release|Win32
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Debug|x64.ActiveCfg = Debug|x64
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Debug|x64.Build.0 = Debug|x64
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Debug|x86.ActiveCfg = Debug|Win32
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Debug|x86.Build.0 = Debug|Win32
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x64.ActiveCfg = Release|x64
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x64.Build.0 = Release|x64
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x86.ActiveCfg = Release|Win32
{ED2F91E1-673A-4590-82B2-EB157927D3E3}.Release|x86.Build.0 = Release|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x64.ActiveCfg = Debug|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x64.Build.0 = Debug|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x86.ActiveCfg = Debug|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Debug|x86.Build.0 = Debug|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x64.ActiveCfg = Release|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x64.Build.0 = Release|x64
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x86.ActiveCfg = Release|Win32
{B852D549-4020-4477-8BFB-E199FF78B047}.Release|x86.Build.0 = Release|Win32
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Debug|x64.ActiveCfg = Debug|x64
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Debug|x64.Build.0 = Debug|x64
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Debug|x86.ActiveCfg = Debug|Win32
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Debug|x86.Build.0 = Debug|Win32
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Release|x64.ActiveCfg = Release|x64
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Release|x64.Build.0 = Release|x64
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Release|x86.ActiveCfg = Release|Win32
{FFC961AC-55B4-4A38-A83E-06AE98F59ACC}.Release|x86.Build.0 = Release|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x64.ActiveCfg = Debug|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x64.Build.0 = Debug|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x86.ActiveCfg = Debug|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x86.Build.0 = Debug|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x64.ActiveCfg = Release|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x64.Build.0 = Release|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x86.ActiveCfg = Release|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x86.Build.0 = Release|Win32
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Debug|x64.ActiveCfg = Debug|x64
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Debug|x64.Build.0 = Debug|x64
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Debug|x86.ActiveCfg = Debug|Win32
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Debug|x86.Build.0 = Debug|Win32
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Release|x64.ActiveCfg = Release|x64
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Release|x64.Build.0 = Release|x64
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Release|x86.ActiveCfg = Release|Win32
{0E383EF0-CEF7-4733-87C6-5AC9844AA1EF}.Release|x86.Build.0 = Release|Win32
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Debug|x64.ActiveCfg = Debug|x64
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Debug|x64.Build.0 = Debug|x64
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Debug|x86.ActiveCfg = Debug|Win32
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Debug|x86.Build.0 = Debug|Win32
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Release|x64.ActiveCfg = Release|x64
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Release|x64.Build.0 = Release|x64
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Release|x86.ActiveCfg = Release|Win32
{07351A8E-1F79-42C9-BBAB-31F071EAA99E}.Release|x86.Build.0 = Release|Win32
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Debug|x64.ActiveCfg = Debug|x64
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Debug|x64.Build.0 = Debug|x64
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Debug|x86.ActiveCfg = Debug|Win32
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Debug|x86.Build.0 = Debug|Win32
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Release|x64.ActiveCfg = Release|x64
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Release|x64.Build.0 = Release|x64
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Release|x86.ActiveCfg = Release|Win32
{27B7CA46-ED23-45C2-BF5F-0C126D81AEBF}.Release|x86.Build.0 = Release|Win32
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Debug|x64.ActiveCfg = Debug|x64
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Debug|x64.Build.0 = Debug|x64
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Debug|x86.ActiveCfg = Debug|Win32
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Debug|x86.Build.0 = Debug|Win32
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Release|x64.ActiveCfg = Release|x64
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Release|x64.Build.0 = Release|x64
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Release|x86.ActiveCfg = Release|Win32
{6AE5C85E-6631-4A12-97A0-A05F812FE9CA}.Release|x86.Build.0 = Release|Win32
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Debug|x64.ActiveCfg = Debug|x64
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Debug|x64.Build.0 = Debug|x64
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Debug|x86.ActiveCfg = Debug|Win32
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Debug|x86.Build.0 = Debug|Win32
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Release|x64.ActiveCfg = Release|x64
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Release|x64.Build.0 = Release|x64
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Release|x86.ActiveCfg = Release|Win32
{D7BFE702-0667-4155-9B0B-2A54DF9AE60B}.Release|x86.Build.0 = Release|Win32
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Debug|x64.ActiveCfg = Debug|x64
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Debug|x64.Build.0 = Debug|x64
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Debug|x86.ActiveCfg = Debug|Win32
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Debug|x86.Build.0 = Debug|Win32
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Release|x64.ActiveCfg = Release|x64
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Release|x64.Build.0 = Release|x64
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Release|x86.ActiveCfg = Release|Win32
{9023DF2F-A33D-485A-B13D-0973348B2F9B}.Release|x86.Build.0 = Release|Win32
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Debug|x64.ActiveCfg = Debug|x64
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Debug|x64.Build.0 = Debug|x64
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Debug|x86.ActiveCfg = Debug|Win32
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Debug|x86.Build.0 = Debug|Win32
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Release|x64.ActiveCfg = Release|x64
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Release|x64.Build.0 = Release|x64
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Release|x86.ActiveCfg = Release|Win32
{89F8D13E-F216-4B67-8DE9-7F842D349E94}.Release|x86.Build.0 = Release|Win32
{A778D062-DE76-49F6-8D05-EB26852DD605}.Debug|x64.ActiveCfg = Debug|x64
{A778D062-DE76-49F6-8D05-EB26852DD605}.Debug|x64.Build.0 = Debug|x64
{A778D062-DE76-49F6-8D05-EB26852DD605}.Debug|x86.ActiveCfg = Debug|Win32
{A778D062-DE76-49F6-8D05-EB26852DD605}.Debug|x86.Build.0 = Debug|Win32
{A778D062-DE76-49F6-8D05-EB26852DD605}.Release|x64.ActiveCfg = Release|x64
{A778D062-DE76-49F6-8D05-EB26852DD605}.Release|x64.Build.0 = Release|x64
{A778D062-DE76-49F6-8D05-EB26852DD605}.Release|x86.ActiveCfg = Release|Win32
{A778D062-DE76-49F6-8D05-EB26852DD605}.Release|x86.Build.0 = Release|Win32
{D26BD501-28A7-4849-8130-FB5EA0A2B82F}.Debug|x64.ActiveCfg = Debug|x64
{D26BD501-28A7-4849-8130-FB5EA0A2B82F}.Debug|x86.ActiveCfg = Debug|x64
{D26BD501-28A7-4849-8130-FB5EA0A2B82F}.Release|x64.ActiveCfg = Release|x64
{D26BD501-28A7-4849-8130-FB5EA0A2B82F}.Release|x86.ActiveCfg = Release|x64
{15009625-1120-405E-8BBA-69A16CD6713D}.Debug|x64.ActiveCfg = Debug|x64
{15009625-1120-405E-8BBA-69A16CD6713D}.Debug|x64.Build.0 = Debug|x64
{15009625-1120-405E-8BBA-69A16CD6713D}.Debug|x86.ActiveCfg = Debug|Win32
{15009625-1120-405E-8BBA-69A16CD6713D}.Debug|x86.Build.0 = Debug|Win32
{15009625-1120-405E-8BBA-69A16CD6713D}.Release|x64.ActiveCfg = Release|x64
{15009625-1120-405E-8BBA-69A16CD6713D}.Release|x64.Build.0 = Release|x64
{15009625-1120-405E-8BBA-69A16CD6713D}.Release|x86.ActiveCfg = Release|Win32
{15009625-1120-405E-8BBA-69A16CD6713D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,27 @@
Many Glider PRO houses, including the bundled ones, contain images in QuickDraw
PICT format in the game resource data.
Additionally, some PICT features are impossible to support because they
require copyrighted pattern sets and fonts that are bundled with the
operating system.
My goal is to support as many community houses as possible, but there is a
point where supporting the format is more work than just manually converting
the resources on a Macintosh machine or emulator.
All of the remaining known unsupported features necessary to decode the
remaining cases are only used by one house that I'm aware of each.
Known error codes:
Code 5 subcode 25: Strange image channel layout
Code 8 subcode 145: Unsupported BitsRgn opcode.
Code 8 subcode 40960: Undocumented opcode, possibly a format parsing error.
Code 8 subcode 34: Unsupported ShortLine opcode. (PICT contains vector graphics.)
Code 8 subcode 35: Unsupported ShortLineFrom opcode. (PICT contains vector graphics.)
Code 8 subcode 49: Unsupported PaintRect opcode. (PICT contains vector graphics.)
Code 8 subcode 51: Unsupported PaintOval opcode. (PICT contains vector graphics.)
Code 8 subcode 129: paintRgn opcode. (PICT contains vector graphics.)
Code 8 subcode 33280: Unsupported CompressedQuickTime opcode. (PICT contains a QuickTime frame.)
Code 8 subcode 33281: Unsupported UncompressedQuickTime opcode. (PICT contains a QuickTime frame.)

View File

@@ -55,4 +55,30 @@ Some old QuickTime movies contain movie tracking information in the movie
resource fork, in which case you need to merge them into the data for modern
utilities to read them. You can use the "flattenmov" tool to do this: Pass
it the data (.gpd) and resource (.gpr) data files for a movie, and it will
merge them into a single .mov file.
merge them into a single .mov file.
BATCH CONVERSION
------------------------------------------------------------------------------
To batch-convert house resource files, use gpr2gpa with a path that ends
with an asterisk (*) and omit the output filename.
SECURITY CONSIDERATIONS
------------------------------------------------------------------------------
Glider PRO didn't really do any validation of houses. Currently, Aerofoil
doesn't do any additional validation either, and it's possible that invalid
house data may lead to crashes or even remote code execution.
I will be doing a hardening pass on the loader for the 1.1 release. Until
then, please only load houses from trusted sources.
Also, Glider PRO houses were able to take advantage of a resource overlaying
feature of the Macintosh operating system, where a resource being present in
the house file with the same ID as an application resource would cause the
resource to override the application resource.
Aerofoil's resource loader is much more restrictive: Currently, only
backgrounds, audio triggers, and icons may load from the house data. This
restriction will be loosened in the 1.1 release to allow resources to be
overrided if I can confirm that it's safe to override them.

View File

@@ -1017,6 +1017,11 @@ public:
m_outputIndexStart = firstRow * m_width + firstCol;
}
bool EmitQTContent(IOStream *stream, uint32_t dataSize, bool isCompressed) override
{
return false;
}
void BlitScanlineAndAdvance(const void *data) override
{

View File

@@ -87,6 +87,15 @@ Rect BERect::ToRect() const
return rect;
}
Point BEPoint::ToPoint() const
{
Point point;
point.h = this->h;
point.v = this->v;
return point;
}
void HideCursor()
{
PortabilityLayer::HostDisplayDriver::GetInstance()->SetStandardCursor(EGpStandardCursors::kHidden);

View File

@@ -12,6 +12,28 @@
#include <vector>
#include <assert.h>
struct QDPictDecodeState
{
PortabilityLayer::RGBAColor m_foreColor;
PortabilityLayer::RGBAColor m_backColor;
Point m_penPos;
Point m_penSize;
Point m_origin;
uint16_t m_penMode;
uint8_t m_penPattern[8];
QDPictDecodeState()
{
m_foreColor = PortabilityLayer::RGBAColor::Create(0, 0, 0, 255);
m_backColor = PortabilityLayer::RGBAColor::Create(255, 255, 255, 255);
m_penPos = Point::Create(0, 0);
m_origin = Point::Create(0, 0);
m_penSize = Point::Create(1, 1);
for (int i = 0; i < 8; i++)
m_penPattern[i] = 0xff;
m_penMode = 0;
}
};
namespace PortabilityLayer
{
@@ -23,9 +45,13 @@ namespace PortabilityLayer
bool QDPictDecoder::DecodePict(IOStream *stream, QDPictEmitContext *emitContext)
{
QDPictHeader header;
QDPictDecodeState decodeState;
if (!header.Load(stream))
{
emitContext->ReportError(QDPictEmitContext::kMissingHeader, 0);
return false;
}
emitContext->SpecifyFrame(header.GetFrame());
@@ -64,7 +90,10 @@ namespace PortabilityLayer
break;
case QDOpcodes::kClipRegion:
if (stream->Read(scratchBytes, 10) != 10 || scratchBytes[0] != 0 || scratchBytes[1] != 10)
return false; // Unknown format region
{
emitContext->ReportError(QDPictEmitContext::kUnsupportedClipRegionFormat, 0);
return false;
}
GP_STATIC_ASSERT(sizeof(scratchBERect) == 8);
@@ -72,17 +101,26 @@ namespace PortabilityLayer
scratchRect = scratchBERect.ToRect();
if (!scratchRect.IsValid())
{
emitContext->ReportError(QDPictEmitContext::kInvalidRegionRect, 0);
return false;
}
break;
case QDOpcodes::kShortComment:
if (!stream->SeekCurrent(2))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
break;
case QDOpcodes::kLongComment:
{
if (stream->Read(scratchBytes, 4) != 4)
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
const uint16_t commentKind = (scratchBytes[0] << 8) | scratchBytes[1];
const uint16_t commentSize = (scratchBytes[2] << 8) | scratchBytes[3];
@@ -92,41 +130,156 @@ namespace PortabilityLayer
}
break;
case QDOpcodes::kBitsRect:
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), false, false, false, activeFrame, emitContext);
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), false, false, false, activeFrame, decodeState.m_origin, emitContext);
if (rasterOpErrorCode)
{
emitContext->ReportError(QDPictEmitContext::kRasterOpFailure, rasterOpErrorCode);
return false;
}
break;
case QDOpcodes::kPackBitsRect:
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, false, false, activeFrame, emitContext);
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, false, false, activeFrame, decodeState.m_origin, emitContext);
if (rasterOpErrorCode)
{
emitContext->ReportError(QDPictEmitContext::kRasterOpFailure, rasterOpErrorCode);
return false;
}
break;
case QDOpcodes::kPackBitsRgn:
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, true, false, activeFrame, emitContext);
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, true, false, activeFrame, decodeState.m_origin, emitContext);
if (rasterOpErrorCode)
{
emitContext->ReportError(QDPictEmitContext::kRasterOpFailure, rasterOpErrorCode);
return false;
}
break;
case QDOpcodes::kDirectBitsRect:
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, false, true, activeFrame, emitContext);
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, false, true, activeFrame, decodeState.m_origin, emitContext);
if (rasterOpErrorCode)
{
emitContext->ReportError(QDPictEmitContext::kRasterOpFailure, rasterOpErrorCode);
return false;
}
break;
case QDOpcodes::kDirectBitsRgn:
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, true, true, activeFrame, emitContext);
rasterOpErrorCode = ProcessRasterOp(stream, header.GetVersion(), true, true, true, activeFrame, decodeState.m_origin, emitContext);
if (rasterOpErrorCode)
{
emitContext->ReportError(QDPictEmitContext::kRasterOpFailure, rasterOpErrorCode);
return false;
}
break;
case QDOpcodes::kDefaultHilite:
break;
case QDOpcodes::kOpColor:
if (!stream->SeekCurrent(6))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
break;
case QDOpcodes::kEndOfPicture:
finished = true;
break;
case QDOpcodes::kPenSize:
{
BEPoint point;
if (!stream->Read(&point, 4))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
decodeState.m_penSize = point.ToPoint();
}
break;
case QDOpcodes::kPenPattern:
{
if (!stream->Read(decodeState.m_penPattern, 8))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
}
break;
case QDOpcodes::kPenMode:
{
BEUInt16_t penMode;
if (!stream->Read(&penMode, 2))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
decodeState.m_penMode = penMode;
}
break;
case QDOpcodes::kOrigin:
{
// NOTE: This is intentionally not the same order as Point
BEInt16_t dxdy[2];
if (!stream->Read(&dxdy, 4))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
decodeState.m_origin.h += dxdy[0];
decodeState.m_origin.v += dxdy[1];
}
break;
case QDOpcodes::kOpColor: // ??? Not sure what the difference between these two is
case QDOpcodes::kRGBForeColor:
{
uint8_t rgbBytes[6];
if (!stream->Read(rgbBytes, 6))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
decodeState.m_foreColor = RGBAColor::Create(rgbBytes[0], rgbBytes[2], rgbBytes[4], 255);
}
break;
case QDOpcodes::kRGBBackColor:
{
uint8_t rgbBytes[6];
if (!stream->Read(rgbBytes, 6))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
decodeState.m_backColor = RGBAColor::Create(rgbBytes[0], rgbBytes[2], rgbBytes[4], 255);
}
break;
case QDOpcodes::kCompressedQT:
case QDOpcodes::kUncompressedQT:
{
BEUInt32_t dataSize;
if (!stream->Read(&dataSize, 4))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
if (!emitContext->EmitQTContent(stream, dataSize, opcode == QDOpcodes::kCompressedQT))
{
emitContext->ReportError(QDPictEmitContext::kMalformedArguments, opcode);
return false;
}
}
break;
default:
// Unknown opcode
emitContext->ReportError(QDPictEmitContext::kUnsupportedOpcode, opcode);
return false;
}
@@ -135,7 +288,7 @@ namespace PortabilityLayer
}
}
int QDPictDecoder::ProcessRasterOp(IOStream *stream, int pictVersion, bool isPackedFlag, bool hasRegion, bool isDirect, const Rect &constraintRect, QDPictEmitContext *context)
int QDPictDecoder::ProcessRasterOp(IOStream *stream, int pictVersion, bool isPackedFlag, bool hasRegion, bool isDirect, const Rect &constraintRect, const Point &origin, QDPictEmitContext *context)
{
uint16_t rowSizeBytes = 0;
@@ -415,6 +568,12 @@ namespace PortabilityLayer
if (srcRect.bottom - srcRect.top != destRect.bottom - destRect.top)
return 39;
// Offset by origin
destRect.left -= origin.h;
destRect.right -= origin.v;
destRect.top -= origin.v;
destRect.bottom -= origin.v;
const Rect pixMapBounds = pixMapBE.m_bounds.ToRect();
if (!pixMapBounds.IsValid())
return 40;
@@ -574,6 +733,13 @@ namespace PortabilityLayer
}
else if (packType == 1)
{
if (!isLineValid)
{
if (!stream->SeekCurrent(rowSizeBytes))
return 59;
continue;
}
if (stream->Read(decompressedScanlineBuffer, rowSizeBytes) != rowSizeBytes)
return 51;

View File

@@ -2,7 +2,8 @@
#include <stdint.h>
struct Rect;
struct Rect;
struct Point;
namespace PortabilityLayer
{
@@ -17,7 +18,7 @@ namespace PortabilityLayer
bool DecodePict(IOStream *stream, QDPictEmitContext *emitContext);
private:
int ProcessRasterOp(IOStream *stream, int pictVersion, bool isPackedFlag, bool hasRegion, bool isDirect, const Rect &drawArea, QDPictEmitContext *context);
int ProcessRasterOp(IOStream *stream, int pictVersion, bool isPackedFlag, bool hasRegion, bool isDirect, const Rect &drawArea, const Point &origin, QDPictEmitContext *context);
static bool UnpackBits8(uint8_t *dest, size_t destSize, const uint8_t *src, size_t srcSize);
static bool UnpackBits16(uint8_t *dest, size_t destSize, const uint8_t *src, size_t srcSize);

View File

@@ -7,7 +7,8 @@ struct Rect;
namespace PortabilityLayer
{
struct RGBAColor;
struct QDPictEmitScanlineParameters;
struct QDPictEmitScanlineParameters;
class IOStream;
enum QDPictBlitSourceType
{
@@ -25,11 +26,27 @@ namespace PortabilityLayer
class QDPictEmitContext
{
public:
public:
enum ErrorCode
{
kMissingHeader,
kInvalidRegionRect,
kMalformedArguments,
kUnusedError1,
kUnusedError2,
kRasterOpFailure,
kUnsupportedClipRegionFormat,
kMalformedOpcode,
kUnsupportedOpcode,
};
virtual bool SpecifyFrame(const Rect &rect) = 0;
virtual Rect ConstrainRegion(const Rect &rect) const = 0;
virtual void Start(QDPictBlitSourceType sourceType, const QDPictEmitScanlineParameters &params) = 0;
virtual void BlitScanlineAndAdvance(const void *) = 0;
virtual bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) = 0;
virtual bool EmitQTContent(IOStream *stream, uint32_t dataSize, bool isCompressed) = 0;
virtual bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) = 0;
virtual void ReportError(int errorType, int errorSubtype) { }
};
}
}

View File

@@ -3,7 +3,13 @@ PL_PICTOP(0x0001, kClipRegion, Rule_SizeTagged16)
PL_PICTOP(0x0002, kBackPattern, 8)
PL_PICTOP(0x0003, kTextFont, 2)
PL_PICTOP(0x0004, kTextFontStyle, 1)
PL_PICTOP(0x0005, kTextSourceMode, 2)
PL_PICTOP(0x0005, kTextSourceMode, 2)
PL_PICTOP(0x0007, kPenSize, 4)
PL_PICTOP(0x0008, kPenMode, 2)
PL_PICTOP(0x0009, kPenPattern, 8)
PL_PICTOP(0x000c, kOrigin, 4) // Relative
PL_PICTOP(0x001a, kRGBForeColor, 6)
PL_PICTOP(0x001b, kRGBBackColor, 6)
PL_PICTOP(0x001e, kDefaultHilite, 0)
PL_PICTOP(0x001f, kOpColor, 6)
PL_PICTOP(0x0030, kFrameRect, 8)
@@ -15,4 +21,6 @@ PL_PICTOP(0x0098, kPackBitsRect, Rule_PackBitsRect)
PL_PICTOP(0x0099, kPackBitsRgn, Rule_PackBitsRgn)
PL_PICTOP(0x009a, kDirectBitsRect, Rule_DirectBitsRect)
PL_PICTOP(0x009b, kDirectBitsRgn, Rule_DirectBitsRgn)
PL_PICTOP(0x8200, kCompressedQT, Rule_SizeTagged32)
PL_PICTOP(0x8201, kUncompressedQT, Rule_SizeTagged32)
PL_PICTOP(0x00ff, kEndOfPicture, 0)

View File

@@ -66,6 +66,14 @@ struct BERect
Rect ToRect() const;
};
struct BEPoint
{
BEInt16_t v;
BEInt16_t h;
Point ToPoint() const;
};
struct BERegion
{
BEUInt16_t recordSize;

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>$(SolutionDir)WindowsUnicodeToolShim;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup />
<ItemGroup />
</Project>

View File

@@ -0,0 +1,154 @@
#include <string>
#include "UTF8.h"
#include "UTF16.h"
#include <Windows.h>
#include <vector>
// This library provides front-ends and shims to make tools a bit more portable by handling all path strings as UTF-8,
// and providing a "main" entry point that is also UTF-8.
static std::string ConvertWStringToUTF8(const wchar_t *str)
{
size_t strLength = wcslen(str);
std::string result;
for (size_t i = 0; i < strLength; )
{
size_t charsDigested = 0;
uint32_t codePoint = 0;
uint8_t asUTF8[4];
if (!PortabilityLayer::UTF16Processor::DecodeCodePoint(reinterpret_cast<const uint16_t*>(str) + i, strLength - i, charsDigested, codePoint))
return "";
i += charsDigested;
size_t bytesEmitted = 0;
PortabilityLayer::UTF8Processor::EncodeCodePoint(asUTF8, bytesEmitted, codePoint);
result.append(reinterpret_cast<const char*>(asUTF8), bytesEmitted);
}
return result;
}
static std::wstring ConvertUTF8ToWString(const char *str)
{
size_t strLength = strlen(str);
std::wstring result;
for (size_t i = 0; i < strLength; )
{
size_t charsDigested = 0;
uint32_t codePoint = 0;
uint16_t asUTF16[4];
if (!PortabilityLayer::UTF8Processor::DecodeCodePoint(reinterpret_cast<const uint8_t*>(str) + i, strLength - i, charsDigested, codePoint))
return L"";
i += charsDigested;
size_t codePointsEmitted = 0;
PortabilityLayer::UTF16Processor::EncodeCodePoint(asUTF16, codePointsEmitted, codePoint);
result.append(reinterpret_cast<const wchar_t*>(asUTF16), codePointsEmitted);
}
return result;
}
FILE *fopen_utf8(const char *path, const char *options)
{
std::wstring pathUTF16 = ConvertUTF8ToWString(path);
std::wstring optionsUTF16 = ConvertUTF8ToWString(options);
return _wfopen(pathUTF16.c_str(), optionsUTF16.c_str());
}
int fputs_utf8(const char *str, FILE *f)
{
return fputs(str, f);
}
int mkdir_utf8(const char *path)
{
std::wstring pathUTF16 = ConvertUTF8ToWString(path);
return _wmkdir(pathUTF16.c_str());
}
void TerminateDirectoryPath(std::string &path)
{
const size_t length = path.length();
if (length == 0)
path.append("\\");
else
{
const char lastChar = path[path.length() - 1];
if (lastChar != '\\' && lastChar != '/')
path.append("\\");
}
}
void ScanDirectoryForExtension(std::vector<std::string> &outPaths, const char *path, const char *ending, bool recursive)
{
std::wstring dirFilter = std::wstring(L"\\\\?\\") + ConvertUTF8ToWString(path) + L"\\*";
size_t endingLen = strlen(ending);
WIN32_FIND_DATAW findDataW;
HANDLE h = FindFirstFileW(dirFilter.c_str(), &findDataW);
if (h == INVALID_HANDLE_VALUE)
return;
while (true)
{
std::string utf8Name = ConvertWStringToUTF8(findDataW.cFileName);
if (utf8Name != "." && utf8Name != "..")
{
if (recursive && findDataW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
ScanDirectoryForExtension(outPaths, (std::string(path) + "\\" + utf8Name).c_str(), ending, true);
else if (utf8Name.length() >= endingLen && utf8Name.substr(utf8Name.length() - endingLen) == ending)
outPaths.push_back(std::string(path) + "\\" + utf8Name);
}
if (!FindNextFileW(h, &findDataW))
break;
}
FindClose(h);
}
int toolMain(int argc, const char **argv);
int main(int argc, const char **argv)
{
SetConsoleOutputCP(CP_UTF8);
LPWSTR *szArglist;
int nArgs;
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
std::vector<std::string> utf8ArgStrings;
std::vector<const char *> utf8Args;
utf8ArgStrings.resize(nArgs);
utf8Args.resize(nArgs);
for (int i = 0; i < nArgs; i++)
{
utf8ArgStrings[i] = ConvertWStringToUTF8(szArglist[i]);
utf8Args[i] = utf8ArgStrings[i].c_str();
}
const char **args = nullptr;
if (nArgs)
args = &utf8Args[0];
return toolMain(nArgs, args);
}

View File

@@ -0,0 +1,9 @@
#include <string>
#include <vector>
#include <stdio.h>
FILE *fopen_utf8(const char *path, const char *options);
int fputs_utf8(const char *str, FILE *f);
int mkdir_utf8(const char *path);
void TerminateDirectoryPath(std::string &path);
void ScanDirectoryForExtension(std::vector<std::string>& outPaths, const char *path, const char *ending, bool recursive);

View File

@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{15009625-1120-405E-8BBA-69A16CD6713D}</ProjectGuid>
<RootNamespace>WindowsUnicodeToolShim</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\WindowsUnicodeToolShim.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\WindowsUnicodeToolShim.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\WindowsUnicodeToolShim.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\WindowsUnicodeToolShim.props" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="WindowsUnicodeToolShim.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WindowsUnicodeToolShim.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -20,6 +20,8 @@
#include "rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "WindowsUnicodeToolShim.h"
#include <stdio.h>
#include <vector>
#include <algorithm>
@@ -205,8 +207,8 @@ void ConvertToMSDOSTimestamp(const PortabilityLayer::CombinedTimestamp &ts, uint
void ExportZipFile(const char *path, const std::vector<PlannedEntry> &entries, const PortabilityLayer::CombinedTimestamp &ts)
{
FILE *outF = nullptr;
if (fopen_s(&outF, path, "wb"))
FILE *outF = fopen_utf8(path, "wb");
if (!outF)
{
fprintf(stderr, "Error opening output path");
return;
@@ -322,8 +324,14 @@ public:
Rect ConstrainRegion(const Rect &rect) const override;
void Start(PortabilityLayer::QDPictBlitSourceType sourceType, const PortabilityLayer::QDPictEmitScanlineParameters &params) override;
void BlitScanlineAndAdvance(const void *) override;
bool EmitQTContent(PortabilityLayer::IOStream *stream, uint32_t dataSize, bool isCompressed) override;
bool AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size) override;
void ReportError(int errorCode, int subCode) override
{
fprintf(stderr, "PICT import failed, error code %i, subcode %i\n", errorCode, subCode);
}
bool Export(std::vector<uint8_t> &outData) const;
private:
@@ -462,6 +470,17 @@ void BMPDumperContext::BlitScanlineAndAdvance(const void *scanlineData)
}
}
bool BMPDumperContext::EmitQTContent(PortabilityLayer::IOStream *stream, uint32_t dataSize, bool isCompressed)
{
// Only one known house ("Magic" seems to use uncompressed, which is partly documented here:
// https://github.com/gco/xee/blob/master/XeePhotoshopPICTLoader.m
// Known compressed cases and codecs:
// "Egypt" res 10011: JPEG
// "The Meadows" res 3000: Apple Video (a.k.a. Apple RPZA)
return false;
}
bool BMPDumperContext::AllocTempBuffers(uint8_t *&buffer1, size_t buffer1Size, uint8_t *&buffer2, size_t buffer2Size)
{
m_tempBuffers.resize(buffer1Size + buffer2Size);
@@ -1078,7 +1097,7 @@ bool ApplyPatch(const std::vector<uint8_t> &patchFileContents, std::vector<Plann
entry = &archive.back();
}
FILE *f = fopen(itemValue.GetString(), "rb");
FILE *f = fopen_utf8(itemValue.GetString(), "rb");
if (!f)
{
fprintf(stderr, "Could not find source file %s for patch", static_cast<const char*>(itemValue.GetString()));
@@ -1125,47 +1144,19 @@ bool ApplyPatch(const std::vector<uint8_t> &patchFileContents, std::vector<Plann
return true;
}
int main(int argc, const char **argv)
int ConvertSingleFile(const char *resPath, const PortabilityLayer::CombinedTimestamp &ts, FILE *patchF, const char *outPath)
{
if (argc != 4 && argc != 5)
{
fprintf(stderr, "Usage: gpr2gpa <input.gpr> <input.ts> <output.gpa> [patch.json]");
return -1;
}
std::string base = argv[1];
FILE *inF = nullptr;
if (fopen_s(&inF, argv[1], "rb"))
FILE *inF = fopen_utf8(resPath, "rb");
if (!inF)
{
fprintf(stderr, "Error opening input file");
return -1;
}
FILE *timestampF = nullptr;
if (fopen_s(&timestampF, argv[2], "rb"))
{
fprintf(stderr, "Error opening metadata file");
return -1;
}
PortabilityLayer::CombinedTimestamp ts;
if (fread(&ts, 1, sizeof(ts), timestampF) != sizeof(ts))
{
fprintf(stderr, "Error reading timestamp");
return -1;
}
bool havePatchFile = false;
std::vector<uint8_t> patchFileContents;
FILE *patchF = nullptr;
if (argc == 5 && fopen_s(&patchF, argv[4], "rb"))
{
fprintf(stderr, "Error reading patch file");
return -1;
}
if (patchF)
{
havePatchFile = true;
@@ -1226,6 +1217,8 @@ int main(int argc, const char **argv)
if (ImportPICT(entry.m_contents, resData, resSize))
contents.push_back(entry);
else
fprintf(stderr, "Failed to import PICT res %i\n", static_cast<int>(res.m_resID));
}
else if (typeList.m_resType == sndTypeID)
{
@@ -1285,9 +1278,123 @@ int main(int argc, const char **argv)
std::sort(contents.begin(), contents.end(), EntryAlphaSortPredicate);
ExportZipFile(argv[3], contents, ts);
ExportZipFile(outPath, contents, ts);
resFile->Destroy();
return 0;
}
int ConvertDirectory(const std::string &basePath, const PortabilityLayer::CombinedTimestamp &ts)
{
std::vector<std::string> paths;
ScanDirectoryForExtension(paths, basePath.c_str(), ".gpr", true);
for (std::vector<std::string>::const_iterator it = paths.begin(), itEnd = paths.end(); it != itEnd; ++it)
{
const std::string &resPath = *it;
std::string housePathBase = resPath.substr(0, resPath.length() - 4);
std::string metaPath = housePathBase + ".gpf";
FILE *metaF = fopen_utf8(metaPath.c_str(), "rb");
if (!metaF)
{
fprintf(stderr, "Failed to open metadata file ");
fputs_utf8(metaPath.c_str(), stderr);
fprintf(stderr, "\n");
}
PortabilityLayer::MacFilePropertiesSerialized mfps;
if (fread(mfps.m_data, 1, PortabilityLayer::MacFilePropertiesSerialized::kSize, metaF) != PortabilityLayer::MacFilePropertiesSerialized::kSize)
{
fclose(metaF);
fprintf(stderr, "Failed to load metadata file ");
fputs_utf8(metaPath.c_str(), stderr);
fprintf(stderr, "\n");
return -1;
}
fclose(metaF);
PortabilityLayer::MacFileProperties mfp;
mfps.Deserialize(mfp);
if (mfp.m_fileType[0] == 'g' && mfp.m_fileType[1] == 'l' && mfp.m_fileType[2] == 'i' && mfp.m_fileType[3] == 'H')
{
std::string houseArchivePath = (housePathBase + ".gpa");
fprintf(stdout, "Importing ");
fputs_utf8(houseArchivePath.c_str(), stdout);
fprintf(stdout, "\n");
int returnCode = ConvertSingleFile(resPath.c_str(), ts, nullptr, houseArchivePath.c_str());
if (returnCode)
{
fprintf(stderr, "An error occurred while converting\n");
fputs_utf8(resPath.c_str(), stderr);
fprintf(stderr, "\n");
return returnCode;
}
}
}
return 0;
}
int PrintUsage()
{
fprintf(stderr, "Usage: gpr2gpa <input.gpr> <input.ts> <output.gpa> [patch.json]");
fprintf(stderr, " gpr2gpa <input dir>\* <input.ts>");
fprintf(stderr, " gpr2gpa <input dir>/* <input.ts>");
fprintf(stderr, " gpr2gpa * <input.ts>");
return -1;
}
int toolMain(int argc, const char **argv)
{
if (argc < 3)
return PrintUsage();
FILE *timestampF = fopen_utf8(argv[2], "rb");
if (!timestampF)
{
fprintf(stderr, "Error opening timestamp file");
return -1;
}
PortabilityLayer::CombinedTimestamp ts;
if (fread(&ts, 1, sizeof(ts), timestampF) != sizeof(ts))
{
fprintf(stderr, "Error reading timestamp");
return -1;
}
fclose(timestampF);
std::string base = argv[1];
if (base == "*")
return ConvertDirectory(".", ts);
if (base.length() >= 2)
{
std::string baseEnding = base.substr(base.length() - 2, 2);
if (baseEnding == "\\*" || baseEnding == "/*")
return ConvertDirectory(base.substr(0, base.length() - 2), ts);
}
if (argc != 4 && argc != 5)
return PrintUsage();
FILE *patchF = nullptr;
if (argc == 5)
{
patchF = fopen_utf8(argv[4], "rb");
if (!patchF)
{
fprintf(stderr, "Error reading patch file");
return -1;
}
}
return ConvertSingleFile(argv[1], ts, patchF, argv[3]);
}

View File

@@ -64,6 +64,7 @@
<Import Project="..\GpCommon.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\RapidJSON.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -73,6 +74,7 @@
<Import Project="..\GpCommon.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\RapidJSON.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -82,6 +84,7 @@
<Import Project="..\GpCommon.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\RapidJSON.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
@@ -91,6 +94,7 @@
<Import Project="..\GpCommon.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\RapidJSON.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
@@ -142,6 +146,9 @@
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
<ProjectReference Include="..\WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj">
<Project>{15009625-1120-405e-8bba-69a16cd6713d}</Project>
</ProjectReference>
<ProjectReference Include="..\zlib\zlib.vcxproj">
<Project>{6ae5c85e-6631-4a12-97a0-a05f812fe9ca}</Project>
</ProjectReference>

View File

@@ -22,6 +22,7 @@
#include "CompactProLZHRLEDecompressor.h"
#include "CSInputBuffer.h"
#include "WindowsUnicodeToolShim.h"
#include <string.h>
@@ -92,84 +93,6 @@ StuffItParser g_stuffItParser;
StuffIt5Parser g_stuffIt5Parser;
CompactProParser g_compactProParser;
std::string ConvertWStringToUTF8(const wchar_t *str)
{
size_t strLength = wcslen(str);
std::string result;
for (size_t i = 0; i < strLength; )
{
size_t charsDigested = 0;
uint32_t codePoint = 0;
uint8_t asUTF8[4];
if (!PortabilityLayer::UTF16Processor::DecodeCodePoint(reinterpret_cast<const uint16_t*>(str) + i, strLength - i, charsDigested, codePoint))
return "";
i += charsDigested;
size_t bytesEmitted = 0;
PortabilityLayer::UTF8Processor::EncodeCodePoint(asUTF8, bytesEmitted, codePoint);
result.append(reinterpret_cast<const char*>(asUTF8), bytesEmitted);
}
return result;
}
std::wstring ConvertUTF8ToWString(const char *str)
{
size_t strLength = strlen(str);
std::wstring result;
for (size_t i = 0; i < strLength; )
{
size_t charsDigested = 0;
uint32_t codePoint = 0;
uint16_t asUTF16[4];
if (!PortabilityLayer::UTF8Processor::DecodeCodePoint(reinterpret_cast<const uint8_t*>(str) + i, strLength - i, charsDigested, codePoint))
return L"";
i += charsDigested;
size_t codePointsEmitted = 0;
PortabilityLayer::UTF16Processor::EncodeCodePoint(asUTF16, codePointsEmitted, codePoint);
result.append(reinterpret_cast<const wchar_t*>(asUTF16), codePointsEmitted);
}
return result;
}
FILE *fopen_utf8(const char *path, const char *options)
{
std::wstring pathUTF16 = ConvertUTF8ToWString(path);
std::wstring optionsUTF16 = ConvertUTF8ToWString(options);
return _wfopen(pathUTF16.c_str(), optionsUTF16.c_str());
}
int mkdir_utf8(const char *path)
{
std::wstring pathUTF16 = ConvertUTF8ToWString(path);
return _wmkdir(pathUTF16.c_str());
}
void TerminateDirectoryPath(std::string &path)
{
const size_t length = path.length();
if (length == 0)
path.append("\\");
else
{
const char lastChar = path[path.length() - 1];
if (lastChar != '\\' && lastChar != '/')
path.append("\\");
}
}
std::string LegalizeWindowsFileName(const std::string &path)
{
const size_t length = path.length();
@@ -441,7 +364,7 @@ int ExtractItem(int depth, const ArchiveItem &item, const std::string &dirPath,
for (int i = 0; i < depth; i++)
printf(" ");
fputws(ConvertUTF8ToWString(path.data()).c_str(), stdout);
fputs_utf8(path.c_str(), stdout);
printf("\n");
path = LegalizeWindowsFileName(path);
@@ -479,7 +402,7 @@ int RecursiveExtractFiles(int depth, ArchiveItemList *itemList, const std::strin
return 0;
}
int unpackMain(int argc, const char **argv)
int toolMain(int argc, const char **argv)
{
if (argc != 3)
{
@@ -537,30 +460,3 @@ int unpackMain(int argc, const char **argv)
return returnCode;
}
int main(int argc, const char **argv)
{
LPWSTR *szArglist;
int nArgs;
int i;
szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
std::vector<std::string> utf8ArgStrings;
std::vector<const char *> utf8Args;
utf8ArgStrings.resize(nArgs);
utf8Args.resize(nArgs);
for (int i = 0; i < nArgs; i++)
{
utf8ArgStrings[i] = ConvertWStringToUTF8(szArglist[i]);
utf8Args[i] = utf8ArgStrings[i].c_str();
}
const char **args = nullptr;
if (nArgs)
args = &utf8Args[0];
return unpackMain(nArgs, args);
}

View File

@@ -61,24 +61,28 @@
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\PortabilityLayer.props" />
<Import Project="..\Common.props" />
<Import Project="..\MacRomanConversion.props" />
<Import Project="..\WindowsUnicodeToolShim.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
@@ -186,6 +190,9 @@
<ProjectReference Include="..\PortabilityLayer\PortabilityLayer.vcxproj">
<Project>{6ec62b0f-9353-40a4-a510-3788f1368b33}</Project>
</ProjectReference>
<ProjectReference Include="..\WindowsUnicodeToolShim\WindowsUnicodeToolShim.vcxproj">
<Project>{15009625-1120-405e-8bba-69a16cd6713d}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">