├── .gitmodules ├── HD_GUI ├── GameGear.h ├── targetver.h ├── Common.h ├── TitleScreen.h ├── Scaling.h ├── HD_GUI.vcxproj.filters ├── Tutorials.h ├── HD_GUI.vcxproj ├── GameGear.cpp ├── TitleScreen.cpp ├── Mission.cpp ├── Tutorials.cpp ├── mod.cpp ├── Subtitles.h └── Subtitles.cpp ├── README.md ├── sadx-hd-gui.sln ├── .gitattributes └── .gitignore /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "sadx-mod-loader"] 2 | path = sadx-mod-loader 3 | url = https://github.com/sonicretro/sadx-mod-loader 4 | -------------------------------------------------------------------------------- /HD_GUI/GameGear.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct AdvertiseBaseParam 4 | { 5 | NJS_TEXLIST* TexList; 6 | int TexNumber; 7 | NJS_POINT2 Top; 8 | NJS_POINT2 Size; 9 | float Priority; 10 | unsigned int Color; 11 | NJS_POINT2 UvTop; 12 | NJS_POINT2 UvDown; 13 | }; -------------------------------------------------------------------------------- /HD_GUI/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /HD_GUI/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define TARGET_DYNAMIC(name) ((decltype(name##_r)*)name##_t->Target()) 4 | #define TARGET_STATIC(name) ((decltype(name##_r)*)name##_t.Target()) 5 | 6 | #define ReplacePVMX(a) helperFunctions.ReplaceFile("system\\" a ".PVM", "system\\" a "_HD.PVM") 7 | 8 | void LoadSubtitleFont(); 9 | 10 | extern const HelperFunctions* helperFunctionsGlobal; -------------------------------------------------------------------------------- /HD_GUI/TitleScreen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(push) 4 | #pragma warning(disable: 4838) 5 | 6 | DataPointer(char, IsTitleScreenReplaced, 0x510350); 7 | 8 | struct TitleScreenData 9 | { 10 | int f0; 11 | void* field_4; 12 | void* field_8; 13 | float field_C; 14 | char gap_10[4]; 15 | int field_14; 16 | int field_18; 17 | char gap_1c[8]; 18 | _DWORD dword24; 19 | _DWORD dword28; 20 | char f2C[4]; 21 | _DWORD dword30; 22 | float float34; 23 | char byte38; 24 | char _padding[3]; 25 | char field_3C[36]; 26 | }; 27 | 28 | #pragma warning(pop) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HD GUI 2 mod by PkR, Dark Sonic, Sonikko & SPEEPSHighway 2 | 3 | HD GUI 2 is a mod for Sonic Adventure DX PC that adds high-resolution textures for almost all menus and GUI items in the game. 4 | 5 | To install HD GUI 2 you can use SADX Mod Installer that sets up SADX Mod Loader and downloads the latest versions of mods automatically. The installer can also convert the Steam version of SADX to the 2004 version, which supports the Mod Loader. 6 | 7 | **SADX Mod Installer:** https://sadxmodinstaller.unreliable.network 8 | 9 | Alternatively you could install HD GUI 2 manually by downloading the latest build [here](https://dcmods.unreliable.network/owncloud/data/PiKeyAr/files/Setup/data/HD_DCStyle.7z). 10 | 11 | **Related mods:** 12 | 13 | Dreamcast Conversion: https://gitlab.com/PiKeyAr/sadx_dreamcast 14 | 15 | Dreamcast DLC: https://gitlab.com/PiKeyAr/sadx-dreamcast-dlc 16 | 17 | Sound Overhaul: https://gitlab.com/PiKeyAr/sadx-sound-overhaul 18 | 19 | Time of Day: https://gitlab.com/PiKeyAr/sadx-timeofday-mod 20 | -------------------------------------------------------------------------------- /HD_GUI/Scaling.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct AdvertiseBaseParam 4 | { 5 | NJS_TEXLIST* TexList; 6 | int TexNumber; 7 | NJS_POINT2 Top; 8 | NJS_POINT2 Size; 9 | float Priority; 10 | unsigned int Color; 11 | NJS_POINT2 UvTop; 12 | NJS_POINT2 UvDown; 13 | }; 14 | 15 | struct GameGearTextureArray 16 | { 17 | int address; 18 | int count; 19 | }; 20 | 21 | struct GameGearTextureData 22 | { 23 | char array; 24 | char index; 25 | float top_x; 26 | float top_y; 27 | float size_x; 28 | float size_y; 29 | }; 30 | 31 | GameGearTextureArray GameGearTextures[] = { 32 | { 0x87C348, 3 }, 33 | { 0x87ECD0, 31 }, 34 | { 0x87E0C8, 24 }, 35 | //{ 0x87CAA8, 2 }, //Emulator (scaled separately) 36 | //{ 0x87CB08, 2 }, //2P mode (scaled separately) 37 | { 0x87CB68, 1 }, //GG_BG 38 | { 0x87CB98, 1 }, //GG_TENKAN 39 | { 0x87F358, 17 }, 40 | { 0x87F9A0, 7 }, 41 | { 0x87C490, 15 }, 42 | { 0x87E6C8, 9 }, 43 | { 0x87F2E8, 1 }, 44 | { 0x87F700, 2 }, 45 | { 0x87F790, 2 }, 46 | }; 47 | 48 | DataPointer(uint8_t, TextureFilterSettingForPoint_1, 0x0078B7C4); 49 | DataPointer(uint8_t, TextureFilterSettingForPoint_2, 0x0078B7D8); 50 | DataPointer(uint8_t, TextureFilterSettingForPoint_3, 0x0078B7EC); -------------------------------------------------------------------------------- /HD_GUI/HD_GUI.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | -------------------------------------------------------------------------------- /sadx-hd-gui.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29201.188 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HD_GUI", "HD_GUI\HD_GUI.vcxproj", "{166D0676-BFF0-4F96-99A6-192FFC5F38CF}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {90CF4AD9-6603-458F-8E3F-E99C0818E43D} = {90CF4AD9-6603-458F-8E3F-E99C0818E43D} 9 | {EC0293F5-4BCF-46B2-8133-18CAEA141C5B} = {EC0293F5-4BCF-46B2-8133-18CAEA141C5B} 10 | EndProjectSection 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModLoaderCommon", "sadx-mod-loader\mod-loader-common\ModLoaderCommon\ModLoaderCommon.vcxproj", "{EC0293F5-4BCF-46B2-8133-18CAEA141C5B}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmodutils", "sadx-mod-loader\libmodutils\libmodutils.vcxproj", "{90CF4AD9-6603-458F-8E3F-E99C0818E43D}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|x86 = Debug|x86 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {166D0676-BFF0-4F96-99A6-192FFC5F38CF}.Debug|x86.ActiveCfg = Debug|Win32 23 | {166D0676-BFF0-4F96-99A6-192FFC5F38CF}.Debug|x86.Build.0 = Debug|Win32 24 | {166D0676-BFF0-4F96-99A6-192FFC5F38CF}.Release|x86.ActiveCfg = Release|Win32 25 | {166D0676-BFF0-4F96-99A6-192FFC5F38CF}.Release|x86.Build.0 = Release|Win32 26 | {EC0293F5-4BCF-46B2-8133-18CAEA141C5B}.Debug|x86.ActiveCfg = Debug|Win32 27 | {EC0293F5-4BCF-46B2-8133-18CAEA141C5B}.Debug|x86.Build.0 = Debug|Win32 28 | {EC0293F5-4BCF-46B2-8133-18CAEA141C5B}.Release|x86.ActiveCfg = Release|Win32 29 | {EC0293F5-4BCF-46B2-8133-18CAEA141C5B}.Release|x86.Build.0 = Release|Win32 30 | {90CF4AD9-6603-458F-8E3F-E99C0818E43D}.Debug|x86.ActiveCfg = Debug|Win32 31 | {90CF4AD9-6603-458F-8E3F-E99C0818E43D}.Debug|x86.Build.0 = Debug|Win32 32 | {90CF4AD9-6603-458F-8E3F-E99C0818E43D}.Release|x86.ActiveCfg = Release|Win32 33 | {90CF4AD9-6603-458F-8E3F-E99C0818E43D}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {10B8EBB0-EC20-43C9-8230-24E0D47ACBA2} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /HD_GUI/Tutorials.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TutorialScreenDataX 4 | { 5 | __int16 BoxX; 6 | __int16 BoxY; 7 | __int16 anonymous_2; 8 | __int16 BoxScaleX; 9 | __int16 BoxScaleY; 10 | __int16 anonymous_3; 11 | void *Pointer1; 12 | void *Pointer2; 13 | }; 14 | 15 | struct TutorialScreenItemX 16 | { 17 | char TexID; 18 | char unknown; 19 | __int16 XOffset; 20 | __int16 YOffset; 21 | }; 22 | 23 | // Tutorial screens 24 | DataArray(TutorialScreenDataX, TutoScreenXSonic_E, 0x2BC3C30, 7); 25 | DataArray(TutorialScreenDataX, TutoScreenXSonic_J, 0x2BC3BA0, 7); 26 | DataArray(TutorialScreenDataX, TutoScreenXSonic_F, 0x2BC3CC0, 7); 27 | DataArray(TutorialScreenDataX, TutoScreenXSonic_G, 0x2BC3DE0, 7); 28 | DataArray(TutorialScreenDataX, TutoScreenXSonic_S, 0x2BC3D50, 7); 29 | DataArray(TutorialScreenDataX, TutoScreenXTails_E, 0x2BC4018, 7); 30 | DataArray(TutorialScreenDataX, TutoScreenXTails_J, 0x2BC3F78, 7); 31 | DataArray(TutorialScreenDataX, TutoScreenXTails_F, 0x2BC40A8, 7); 32 | DataArray(TutorialScreenDataX, TutoScreenXTails_S, 0x2BC4138, 7); 33 | DataArray(TutorialScreenDataX, TutoScreenXTails_G, 0x2BC41C8, 7); 34 | DataArray(TutorialScreenDataX, TutoScreenXKnuckles_E, 0x2BC4450, 7); 35 | DataArray(TutorialScreenDataX, TutoScreenXKnuckles_J, 0x2BC4398, 7); 36 | DataArray(TutorialScreenDataX, TutoScreenXKnuckles_F, 0x2BC44F0, 7); 37 | DataArray(TutorialScreenDataX, TutoScreenXKnuckles_G, 0x2BC4630, 7); 38 | DataArray(TutorialScreenDataX, TutoScreenXKnuckles_S, 0x2BC4590, 7); 39 | DataArray(TutorialScreenDataX, TutoScreenXAmy_E, 0x2BC4830, 7); 40 | DataArray(TutorialScreenDataX, TutoScreenXAmy_J, 0x2BC47A0, 7); 41 | DataArray(TutorialScreenDataX, TutoScreenXAmy_F, 0x2BC48C0, 7); 42 | DataArray(TutorialScreenDataX, TutoScreenXAmy_G, 0x2BC49E0, 7); 43 | DataArray(TutorialScreenDataX, TutoScreenXAmy_S, 0x2BC4950, 7); 44 | DataArray(TutorialScreenDataX, TutoScreenXBig_E, 0x2BC5158, 9); 45 | DataArray(TutorialScreenDataX, TutoScreenXBig_J, 0x2BC5090, 10); 46 | DataArray(TutorialScreenDataX, TutoScreenXBig_F, 0x2BC5210, 9); 47 | DataArray(TutorialScreenDataX, TutoScreenXBig_G, 0x2BC5380, 9); 48 | DataArray(TutorialScreenDataX, TutoScreenXBig_S, 0x2BC52C8, 9); 49 | DataArray(TutorialScreenDataX, TutoScreenXGamma_E, 0x2BC4C08, 8); 50 | DataArray(TutorialScreenDataX, TutoScreenXGamma_J, 0x2BC4B68, 8); 51 | DataArray(TutorialScreenDataX, TutoScreenXGamma_F, 0x2BC4CA8, 8); 52 | DataArray(TutorialScreenDataX, TutoScreenXGamma_G, 0x2BC4DE8, 8); 53 | DataArray(TutorialScreenDataX, TutoScreenXGamma_S, 0x2BC4D48, 8); 54 | 55 | // Tutorial screen items 56 | DataArray(TutorialScreenItemX, TutorialLayoutX_Sonic_Page1_E, 0x02BC3ACE, 6); 57 | DataArray(TutorialScreenItemX, TutorialLayoutX_Sonic_Page1_J, 0x02BC3A8E, 5); 58 | DataArray(TutorialScreenItemX, TutorialLayoutX_SharedTailsKnucklesPage1_E, 0x2BC3E90, 4); 59 | DataArray(TutorialScreenItemX, TutorialLayoutX_SharedTailsKnucklesPage1_J, 0x2BC3E74, 3); 60 | DataPointer(TutorialScreenItemX, TutorialLayoutX_Tails_Page1_E, 0x2BC3EB2); 61 | DataPointer(TutorialScreenItemX, TutorialLayoutX_Tails_Page1_J, 0x2BC3EAA); 62 | DataPointer(TutorialScreenItemX, TutorialLayoutX_Knuckles_Page1_E, 0x2BC425E); 63 | DataPointer(TutorialScreenItemX, TutorialLayoutX_Knuckles_Page1_J, 0x2BC4256); 64 | DataArray(TutorialScreenItemX, TutorialLayoutX_AmyGamma_Page1_E, 0x2BC46E6, 4); 65 | DataArray(TutorialScreenItemX, TutorialLayoutX_AmyGamma_Page1_J, 0x2BC46D2, 3); 66 | DataArray(TutorialScreenItemX, TutorialLayoutX_Amy_Page1_E, 0x2BC4712, 2); 67 | DataArray(TutorialScreenItemX, TutorialLayoutX_Amy_Page1_J, 0x2BC4702, 2); 68 | DataArray(TutorialScreenItemX, TutorialLayoutX_BigPage1_E, 0x2BC4E8A, 4); 69 | DataArray(TutorialScreenItemX, TutorialLayoutX_BigPage1Part2_E, 0x2BC4EB6, 2); 70 | DataArray(TutorialScreenItemX, TutorialLayoutX_BigPage1Part2_J, 0x2BC4EA6, 2); 71 | DataArray(TutorialScreenItemX, TutorialLayoutX_BigPage5_E, 0x2BC4F46, 6); 72 | DataArray(TutorialScreenItemX, TutorialLayoutX_Gamma_Page1_E, 0x2BC4A7E, 2); 73 | DataArray(TutorialScreenItemX, TutorialLayoutX_Gamma_Page1_J, 0x2BC4A6E, 2); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | *.VC.VC.opendb 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 | # checkin your Azure Web App publish settings, but sensitive information contained 150 | # in these scripts will be unencrypted 151 | PublishScripts/ 152 | 153 | # NuGet Packages 154 | *.nupkg 155 | # The packages folder can be ignored because of Package Restore 156 | **/packages/* 157 | # except build/, which is used as an MSBuild target. 158 | !**/packages/build/ 159 | # Uncomment if necessary however generally it will be regenerated when needed 160 | #!**/packages/repositories.config 161 | # NuGet v3's project.json files produces more ignoreable files 162 | *.nuget.props 163 | *.nuget.targets 164 | 165 | # Microsoft Azure Build Output 166 | csx/ 167 | *.build.csdef 168 | 169 | # Microsoft Azure Emulator 170 | ecf/ 171 | rcf/ 172 | 173 | # Windows Store app package directories and files 174 | AppPackages/ 175 | BundleArtifacts/ 176 | Package.StoreAssociation.xml 177 | _pkginfo.txt 178 | 179 | # Visual Studio cache files 180 | # files ending in .cache can be ignored 181 | *.[Cc]ache 182 | # but keep track of directories ending in .cache 183 | !*.[Cc]ache/ 184 | 185 | # Others 186 | ClientBin/ 187 | ~$* 188 | *~ 189 | *.dbmdl 190 | *.dbproj.schemaview 191 | *.pfx 192 | *.publishsettings 193 | node_modules/ 194 | orleans.codegen.cs 195 | 196 | # Since there are multiple workflows, uncomment next line to ignore bower_components 197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 | #bower_components/ 199 | 200 | # RIA/Silverlight projects 201 | Generated_Code/ 202 | 203 | # Backup & report files from converting an old project file 204 | # to a newer Visual Studio version. Backup files are not needed, 205 | # because we have git ;-) 206 | _UpgradeReport_Files/ 207 | Backup*/ 208 | UpgradeLog*.XML 209 | UpgradeLog*.htm 210 | 211 | # SQL Server files 212 | *.mdf 213 | *.ldf 214 | 215 | # Business Intelligence projects 216 | *.rdl.data 217 | *.bim.layout 218 | *.bim_*.settings 219 | 220 | # Microsoft Fakes 221 | FakesAssemblies/ 222 | 223 | # GhostDoc plugin setting file 224 | *.GhostDoc.xml 225 | 226 | # Node.js Tools for Visual Studio 227 | .ntvs_analysis.dat 228 | 229 | # Visual Studio 6 build log 230 | *.plg 231 | 232 | # Visual Studio 6 workspace options file 233 | *.opt 234 | 235 | # Visual Studio LightSwitch build output 236 | **/*.HTMLClient/GeneratedArtifacts 237 | **/*.DesktopClient/GeneratedArtifacts 238 | **/*.DesktopClient/ModelManifest.xml 239 | **/*.Server/GeneratedArtifacts 240 | **/*.Server/ModelManifest.xml 241 | _Pvt_Extensions 242 | 243 | # Paket dependency manager 244 | .paket/paket.exe 245 | paket-files/ 246 | 247 | # FAKE - F# Make 248 | .fake/ 249 | 250 | # JetBrains Rider 251 | .idea/ 252 | *.sln.iml 253 | -------------------------------------------------------------------------------- /HD_GUI/HD_GUI.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15.0 15 | {166D0676-BFF0-4F96-99A6-192FFC5F38CF} 16 | Win32Proj 17 | HD_GUI 18 | 7.0 19 | 20 | 21 | 22 | DynamicLibrary 23 | true 24 | v141_xp 25 | Unicode 26 | 27 | 28 | DynamicLibrary 29 | false 30 | v141_xp 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | $(SolutionDir)bin\ 48 | $(Configuration)\ 49 | 50 | 51 | $(SolutionDir)bin\ 52 | 53 | 54 | 55 | Level3 56 | NotUsing 57 | WIN32;NDEBUG;%(PreprocessorDefinitions) 58 | $(ProjectDir)..\sadx-mod-loader\libmodutils;$(ProjectDir)..\sadx-mod-loader\mod-loader-common\ModLoaderCommon;$(ProjectDir)..\sadx-mod-loader\SADXModLoader\include;%(AdditionalIncludeDirectories) 59 | true 60 | true 61 | true 62 | 63 | 64 | Windows 65 | true 66 | true 67 | 68 | 69 | $(SolutionDir)bin\ModLoaderCommon.lib;$(SolutionDir)bin\libmodutils.lib;%(AdditionalDependencies) 70 | 71 | 72 | 73 | 74 | Level3 75 | WIN32;_DEBUG;HD_GUI_EXPORTS;%(PreprocessorDefinitions) 76 | $(ProjectDir)..\sadx-mod-loader\libmodutils;$(ProjectDir)..\sadx-mod-loader\SADXModLoader\include;$(ProjectDir)..\sadx-mod-loader\mod-loader-common\ModLoaderCommon;%(AdditionalIncludeDirectories) 77 | true 78 | true 79 | 80 | 81 | Windows 82 | $(ProjectDir)..\bin\ModLoaderCommon.lib;$(ProjectDir)..\bin\libmodutils.lib;%(AdditionalDependencies) 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /HD_GUI/GameGear.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "GameGear.h" 3 | 4 | AdvertiseBaseParam GameGearBackgroundParams[64]; 5 | 6 | DataPointer(NJS_TEXLIST, GG_TEXLIST_TEXLIST, 0x339CC44); 7 | 8 | static float HorizontalResolution_Float = 640.0f; 9 | 10 | // Recreates background textures for the Mini Game Collection in widescreen. 11 | void GenerateGameGearBackground() 12 | { 13 | HorizontalResolution_Float = (float)HorizontalResolution; 14 | float startpoint = HorizontalResolution_Float; 15 | int index = 0; 16 | for (int b = 0; b < 8; b++) 17 | { 18 | // Top/bottom 19 | for (int i = 0; i < 2; i++) 20 | { 21 | // Top 22 | GameGearBackgroundParams[index].Color = 0xFFFFFFFF; 23 | GameGearBackgroundParams[index].Priority = 0.3f; 24 | GameGearBackgroundParams[index].Size.x = 256.0f; 25 | GameGearBackgroundParams[index].Size.y = 256.0f; 26 | GameGearBackgroundParams[index].TexList = &GG_TEXLIST_TEXLIST; 27 | GameGearBackgroundParams[index].TexNumber = (b % 2 != 0) ? (9 - i * 2) : (7 + i * 2); 28 | GameGearBackgroundParams[index].UvTop.x = (b % 2 != 0) ? 1 : 0; 29 | GameGearBackgroundParams[index].UvTop.y = 0; 30 | GameGearBackgroundParams[index].UvDown.x = (b % 2 != 0) ? 0 : 1; 31 | GameGearBackgroundParams[index].UvDown.y = 1.0f; 32 | GameGearBackgroundParams[index].Top.x = 0 - startpoint + 256.0f * i + 640.0f * b + ((b % 2 != 0) ? 128.0f : 0.0f); 33 | GameGearBackgroundParams[index].Top.y = 0; 34 | index++; 35 | // Bottom 36 | GameGearBackgroundParams[index].Color = 0xFFFFFFFF; 37 | GameGearBackgroundParams[index].Priority = 0.3f; 38 | GameGearBackgroundParams[index].Size.x = 256.0f; 39 | GameGearBackgroundParams[index].Size.y = 256.0f; 40 | GameGearBackgroundParams[index].TexList = &GG_TEXLIST_TEXLIST; 41 | GameGearBackgroundParams[index].TexNumber = (b % 2 != 0) ? (10 - i * 2) : (8 + i * 2); 42 | GameGearBackgroundParams[index].UvTop.x = (b % 2 != 0) ? 1 : 0;; 43 | GameGearBackgroundParams[index].UvTop.y = 0; 44 | GameGearBackgroundParams[index].UvDown.x = (b % 2 != 0) ? 0 : 1; 45 | GameGearBackgroundParams[index].UvDown.y = 1.0f; 46 | GameGearBackgroundParams[index].Top.x = 0 - startpoint + 256.0f * i + 640.0f * b + ((b % 2 != 0) ? 128.0f : 0.0f); 47 | GameGearBackgroundParams[index].Top.y = 256.0f; 48 | index++; 49 | 50 | } 51 | // Right 52 | for (int d = 0; d < 2; d++) 53 | { 54 | // Top right 55 | GameGearBackgroundParams[index].Color = 0xFFFFFFFF; 56 | GameGearBackgroundParams[index].Priority = 0.3f; 57 | GameGearBackgroundParams[index].Size.x = 128.0f; 58 | GameGearBackgroundParams[index].Size.y = 128.0f; 59 | GameGearBackgroundParams[index].TexList = &GG_TEXLIST_TEXLIST; 60 | GameGearBackgroundParams[index].TexNumber = 1 + d; 61 | GameGearBackgroundParams[index].UvTop.x = (b % 2 != 0) ? 1 : 0; 62 | GameGearBackgroundParams[index].UvTop.y = 0; 63 | GameGearBackgroundParams[index].UvDown.x = (b % 2 != 0) ? 0 : 1; 64 | GameGearBackgroundParams[index].UvDown.y = 1.0f; 65 | GameGearBackgroundParams[index].Top.x = 0 - startpoint + 640.0f * b + ((b % 2 != 0) ? 0.0f : 512.0f); 66 | GameGearBackgroundParams[index].Top.y = 128.0f * d; 67 | index++; 68 | // Bottom right 69 | GameGearBackgroundParams[index].Color = 0xFFFFFFFF; 70 | GameGearBackgroundParams[index].Priority = 0.3f; 71 | GameGearBackgroundParams[index].Size.x = 128.0f; 72 | GameGearBackgroundParams[index].Size.y = 128.0f; 73 | GameGearBackgroundParams[index].TexList = &GG_TEXLIST_TEXLIST; 74 | GameGearBackgroundParams[index].TexNumber = 3 + d; 75 | GameGearBackgroundParams[index].UvTop.x = (b % 2 != 0) ? 1 : 0; 76 | GameGearBackgroundParams[index].UvTop.y = 0; 77 | GameGearBackgroundParams[index].UvDown.x = (b % 2 != 0) ? 0 : 1; 78 | GameGearBackgroundParams[index].UvDown.y = 1.0f; 79 | GameGearBackgroundParams[index].Top.x = 0 - startpoint + 640.0f * b + ((b % 2 != 0) ? 0.0f : 512.0f); 80 | GameGearBackgroundParams[index].Top.y = 128.0f * d + 256.0f; 81 | index++; 82 | } 83 | } 84 | } 85 | 86 | void DrawHoneycomb(NJS_POINT2COL* pointcol, Int n, Float pri, Uint32 attr) 87 | { 88 | for (int i = 0; i < 6; i++) 89 | pointcol->p[i].x -= ((float)HorizontalResolution - 640) / 2; 90 | njDrawCircle2D(pointcol, n, pri, attr); 91 | } 92 | 93 | void GameGearTexmemlist_NoAlphaRejection(NJS_TEXTURE_VTX* a1, Int count, Uint32 gbix, Int flag) 94 | { 95 | if (gbix == 1310100 || gbix == 1311000) // Pause menu shadow, corners 96 | { 97 | njTextureShadingMode(1); 98 | //PrintDebug("%d\n", gbix); 99 | } 100 | else 101 | njTextureShadingMode(2); 102 | njDrawTextureMemList(a1, count, gbix, flag); 103 | } 104 | 105 | void GameGear_Init() 106 | { 107 | WriteCall((void*)0x701764, GameGearTexmemlist_NoAlphaRejection); 108 | HorizontalResolution_Float = (float)HorizontalResolution; 109 | GenerateGameGearBackground(); 110 | WriteData<1>((char*)0x007032C3, 0x40); // 64 textures for background (game select screen) 111 | WriteData((AdvertiseBaseParam**)0x007032BB, GameGearBackgroundParams); // Replace background array (game select screen) 112 | WriteData((AdvertiseBaseParam**)0x006FFFBB, GameGearBackgroundParams); // Replace background array (controls screen) 113 | WriteData<1>((char*)0x006FFFC3, 0x40); // 64 textures for background (controls screen) 114 | // Honeycomb transition 115 | WriteData((float**)0x006FF5C8, &VerticalStretch); 116 | WriteData((float**)0x006FF5D9, &VerticalStretch); 117 | WriteData((float**)0x006FF5EB, &VerticalStretch); 118 | WriteData((float**)0x006FF603, &VerticalStretch); 119 | WriteData((float**)0x006FF611, &VerticalStretch); 120 | WriteData((float**)0x006FF632, &VerticalStretch); 121 | WriteData((float**)0x006FF657, &VerticalStretch); 122 | WriteData((float**)0x006FF4B1, &HorizontalResolution_Float); 123 | WriteCall((void*)0x006FF662, DrawHoneycomb); 124 | } -------------------------------------------------------------------------------- /HD_GUI/TitleScreen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "TitleScreen.h" 3 | 4 | static float xoffset = 0; 5 | static float sonic_xoffset = 832; 6 | static float logo_xoffset = 800; 7 | static bool logoback = false; 8 | 9 | void DrawTitleScreenShit_cdecl(TitleScreenData* a1) 10 | { 11 | NJS_COLOR StartColor = { 0x00FFFFFF }; 12 | unsigned int v1; // ecx 13 | float xpos = 0; 14 | float ypos = 0; 15 | float vscale = 1.0f; 16 | float hzscale = 1.0f; 17 | float center_x = (float)HorizontalResolution / 2.0f; 18 | float center_y = (float)VerticalResolution / 2.0f; 19 | unsigned char PressStartTransparency; 20 | NJS_COLOR color1 = { 0xFF0000EE }; 21 | NJS_COLOR color2 = { 0xFF0000EE }; 22 | NJS_COLOR color3 = { 0xFF310072 }; 23 | NJS_COLOR color4 = { 0xFF310072 }; 24 | 25 | vscale = (float)VerticalResolution / 480.0f; 26 | hzscale = (float)HorizontalResolution / 640.0f; 27 | v1 = a1->dword30; 28 | if (v1 < 2) 29 | xoffset = 0; 30 | if (v1 >= 0x3C) 31 | { 32 | SetVtxColorA(0xFFFFFFFF); 33 | } 34 | else 35 | { 36 | SetVtxColorA(((char)(255 * v1 / 0x3C) << 24) + 0xFFFFFF); 37 | sonic_xoffset = ((float)HorizontalResolution / vscale) + 256.0f; 38 | logo_xoffset = ((float)HorizontalResolution / vscale) + 256.0f; 39 | logoback = false; 40 | } 41 | float sonic_and_logo_step = 128 * hzscale / vscale; 42 | SetVtxColorB(0xFFFFFFFF); 43 | njSetTexture(&ava_title_cmn_TEXLIST); 44 | njTextureShadingMode(1); // Disable alpha rejection 45 | if (!MissedFrames) 46 | { 47 | // The full scrolling clouds image is 2560 (1280 at 1x) pixels wide 48 | float scale = 1280 * vscale; 49 | int delta = HorizontalResolution - (int)scale; 50 | int times = 2 + ceil(delta / scale); 51 | //PrintDebug("Vscale: %f, Scale: %f\n", vscale, times); 52 | // Draw the scrolling clouds 53 | ypos = -10 * vscale; 54 | // Draw the four rows of clouds 55 | xpos = 0; 56 | for (int q = 0; q < times + 1; q++) 57 | { 58 | for (int i = 0; i < 10; i++) 59 | { 60 | xpos = 256.0f * vscale * 0.5f * (i + 10 * q) - xoffset; 61 | //if (xpos <= -2560.0f/vscale) xoffset = 0; 62 | //PrintDebug("xpos: %f\n", xpos); 63 | DrawBG(30 + i, xpos, ypos, 2.0f, vscale * 0.5f, vscale * 0.5f); 64 | DrawBG(40 + i, xpos, ypos + 256.0f * vscale * 0.5f, 2.0f, vscale * 0.5f, vscale * 0.5f); 65 | DrawBG(50 + i, xpos, ypos + 512.0f * vscale * 0.5f, 2.0f, vscale * 0.5f, vscale * 0.5f); 66 | DrawBG(60 + i, xpos, ypos + 768.0f * vscale * 0.5f, 2.0f, vscale * 0.5f, vscale * 0.5f); 67 | } 68 | } 69 | if (vscale >= 0.5f) 70 | xoffset += 2 * vscale; 71 | else 72 | xoffset = 0; 73 | //PrintDebug("v1: %f\n", xoffset*vscale* 0.5f); 74 | // Draw the circles around Sonic (front) 75 | xpos = center_x - 320.0f * vscale + 280 * vscale; 76 | ypos = center_y - 240.0f * vscale + 52 * vscale; 77 | DrawBG(2, xpos, ypos, 1.4f, vscale * 0.5f, vscale * 0.5f); 78 | DrawBG(3, xpos + 256.0f * vscale * 0.5f, ypos, 1.4f, vscale * 0.5f, vscale * 0.5f); 79 | DrawBG(4, xpos, ypos + 256.0f * vscale * 0.5f, 1.4f, vscale * 0.5f, vscale * 0.5f); 80 | DrawBG(5, xpos + 256.0f * vscale * 0.5f, ypos + 256.0f * vscale * 0.5f, 1.4f, vscale * 0.5f, vscale * 0.5f); 81 | DrawBG(6, xpos, ypos + 512.0f * vscale * 0.5f, 1.4f, vscale * 0.5f, vscale * 0.5f); 82 | DrawBG(7, xpos + 256.0f * vscale * 0.5f, ypos + 512.0f * vscale * 0.5f, 1.4f, vscale * 0.5f, vscale * 0.5f); 83 | // Draw the circles around Sonic (back) 84 | xpos = center_x - 320.0f * vscale - 90.0f * vscale; 85 | ypos = center_y - 240.0f * vscale + 52 * vscale; 86 | DrawBG(8, xpos, ypos, 1.3f, vscale * 0.5f, vscale * 0.5f); 87 | DrawBG(9, xpos, ypos + 256.0f * vscale * 0.5f, 1.4f, vscale * 0.5f, vscale * 0.5f); 88 | DrawBG(10, xpos, ypos + 512.0f * vscale * 0.5f, 1.4f, vscale * 0.5f, vscale * 0.5f); 89 | // Draw the gradient overlay/border thing 90 | // Left 91 | if (v1 <= 60) 92 | { 93 | color1.argb.a = int(((float)v1 / 60.0f) * 255); 94 | color2.argb.a = int(((float)v1 / 60.0f) * 255); 95 | color3.argb.a = int(((float)v1 / 60.0f) * 255); 96 | color4.argb.a = int(((float)v1 / 60.0f) * 255); 97 | } 98 | else 99 | { 100 | color1.argb.a = 255; 101 | color2.argb.a = 255; 102 | color3.argb.a = 255; 103 | color4.argb.a = 255; 104 | } 105 | ScreenTextureVertices[0].col = color1.color; 106 | ScreenTextureVertices[1].col = color2.color; 107 | // Right 108 | ScreenTextureVertices[2].col = color3.color; 109 | ScreenTextureVertices[3].col = color4.color; 110 | DrawBG(1, 0, 0, 1.3f, (float)HorizontalResolution / 256.0f, vscale * 0.5f); 111 | ypos = (float)VerticalResolution - 256.0f * vscale * 0.5f; 112 | DrawBG(0x40000001, 0, ypos, 1.3f, (float)HorizontalResolution / 256.0f, vscale * 0.5f); 113 | SetVtxColorB(0xFFFFFFFF); 114 | // Draw copyright text 115 | xpos = center_x; 116 | ypos = center_y + 140.0f * vscale; 117 | DrawBG(11, xpos, ypos, 1.3f, vscale * 0.4f, vscale * 0.4f); 118 | DrawBG(12, xpos + 256.0f * vscale * 0.4f, ypos, 1.3f, vscale * 0.4f, vscale * 0.4f); 119 | DrawBG(13, xpos + 512.0f * vscale * 0.4f, ypos, 1.3f, vscale * 0.4f, vscale * 0.4f); 120 | // Draw the lines above and below the gradients 121 | DrawBG(0, 0, 0, 1.3f, (float)HorizontalResolution / 256.0f, vscale * 0.5f); 122 | ypos = (float)VerticalResolution - 256.0f * vscale * 0.5f; 123 | DrawBG(0x40000000, 0, ypos, 1.3f, (float)HorizontalResolution / 256.0f, vscale * 0.5f); 124 | // Draw Sonic 125 | xpos = center_x - 320.0f * vscale - (128.0f - sonic_xoffset) * vscale; 126 | ypos = center_y - 260.0f * vscale; 127 | if (v1 >= 60) 128 | { 129 | if (sonic_xoffset > sonic_and_logo_step - 1) 130 | sonic_xoffset -= sonic_and_logo_step; 131 | else 132 | sonic_xoffset = 0; 133 | } 134 | int sonictex = 0; 135 | for (int v = 0; v < 4; v++) 136 | { 137 | for (int h = 0; h < 4; h++) 138 | { 139 | float finalx = xpos + 256.0f * h * vscale * 0.5f; 140 | float finaly = ypos + 256.0f * v * vscale * 0.5f; 141 | DrawBG(14 + sonictex, finalx, finaly, 1.2f, vscale * 0.5f, vscale * 0.5f); 142 | sonictex++; 143 | } 144 | } 145 | // Draw logo 146 | njSetTexture(TextLanguage ? &ava_gtitle0_e_TEXLIST : &TexList_Ava_Gtitle0); 147 | xpos = center_x - (171.0f + logo_xoffset) * vscale; 148 | ypos = center_y - 143.0f * vscale; 149 | DrawBG(0, xpos, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 150 | DrawBG(1, xpos + 256.0f * vscale * 0.5f, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 151 | DrawBG(2, xpos + 512.0f * vscale * 0.5f, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 152 | DrawBG(3, xpos + 768.0f * vscale * 0.5f, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 153 | DrawBG(4, xpos, ypos + 256.0f * vscale * 0.5f, 1.1f, vscale * 0.5f, vscale * 0.5f); 154 | DrawBG(5, xpos + 256.0f * vscale * 0.5f, ypos + 256.0f * vscale * 0.5f, 1.1f, vscale * 0.5f, vscale * 0.5f); 155 | DrawBG(6, xpos + 512.0f * vscale * 0.5f, ypos + 256.0f * vscale * 0.5f, 1.1f, vscale * 0.5f, vscale * 0.5f); 156 | DrawBG(7, xpos + 768.0f * vscale * 0.5f, ypos + 256.0f * vscale * 0.5f, 1.1f, vscale * 0.5f, vscale * 0.5f); 157 | //PrintDebug("logo: %f\n", logo_xoffset); 158 | //PrintDebug("Start: %d\n", a1->dword28); 159 | if (v1 >= 80) 160 | { 161 | if (!logoback) 162 | { 163 | if (logo_xoffset > -sonic_and_logo_step) logo_xoffset -= sonic_and_logo_step; 164 | else 165 | { 166 | logoback = true; 167 | } 168 | } 169 | else 170 | { 171 | if (logo_xoffset < -(sonic_and_logo_step - 1)) logo_xoffset += sonic_and_logo_step; else logo_xoffset = 0; 172 | } 173 | } 174 | // Increase timer 175 | a1->dword30 += MissedFrames_B; 176 | // Draw Press Start 177 | if (a1->dword24 >= 150) 178 | { 179 | PressStartTransparency = a1->dword28; 180 | if ((a1->dword28 & 0x1FFu) >= 0x100) 181 | { 182 | PressStartTransparency = -1 - a1->dword28; 183 | } 184 | StartColor.argb.a = PressStartTransparency; 185 | SetVtxColorB(StartColor.color); 186 | xpos = center_x + 32.0f * vscale; 187 | ypos = center_y + 84 * vscale; 188 | njTextureShadingMode(1); 189 | njSetTexture(TextLanguage ? &ava_gtitle0_e_TEXLIST : &TexList_Ava_Gtitle0); 190 | DrawBG(8, xpos, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 191 | DrawBG(9, xpos + 128.0f * vscale, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 192 | if (!TextLanguage) 193 | DrawBG(10, xpos + 256.0f * vscale, ypos, 1.1f, vscale * 0.5f, vscale * 0.5f); 194 | njTextureShadingMode(2); 195 | SetVtxColorB(0xFFFFFFFF); 196 | } 197 | } 198 | } 199 | 200 | static void __declspec(naked) DrawTitleScreenShit_asm() 201 | { 202 | __asm 203 | { 204 | push esi // a1 205 | 206 | // Call your __cdecl function here: 207 | call DrawTitleScreenShit_cdecl 208 | 209 | pop esi // a1 210 | retn 211 | } 212 | } 213 | 214 | void TitleScreen_Init() 215 | { 216 | WriteCall((void*)0x51037E, DrawTitleScreenShit_asm); 217 | } 218 | 219 | void TitleScreen_OnReset() 220 | { 221 | xoffset = 0; 222 | } -------------------------------------------------------------------------------- /HD_GUI/Mission.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Common.h" 3 | #include "FunctionHook.h" 4 | 5 | VoidFunc(DrawMiClearStatus, 0x590690); 6 | FunctionPointer(Sint32, ReleaseMiClearStatus, (), 0x00590660); 7 | 8 | #define ReplacePNG_MissionE(a) do { \ 9 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_mission_en\\index.txt", path); \ 10 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 11 | } while (0) 12 | 13 | #define ReplacePNG_MissionJ(a) do { \ 14 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_mission_jp\\index.txt", path); \ 15 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 16 | } while (0) 17 | 18 | #define ReplacePNG_MissionF(a) do { \ 19 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_mission_fr\\index.txt", path); \ 20 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 21 | } while (0) 22 | 23 | #define ReplacePNG_GoalRing(a) do { \ 24 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_mission_goalring\\index.txt", path); \ 25 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 26 | } while (0) 27 | 28 | 29 | FunctionHook DrawMiClearStatus_h(DrawMiClearStatus); 30 | FunctionHook ReleaseMiClearStatus_h(ReleaseMiClearStatus); 31 | 32 | static void __cdecl DrawMiClearStatus_r() 33 | { 34 | // Draw AVA_BACK background 35 | DrawSkyBg(1.1f); 36 | DrawMiClearStatus_h.Original(); 37 | } 38 | 39 | static Sint32 __cdecl ReleaseMiClearStatus_r() 40 | { 41 | late_ReleaseTexture(&ava_back_TEXLIST); 42 | return ReleaseMiClearStatus_h.Original(); 43 | } 44 | 45 | void LoadAvaBackForMission() 46 | { 47 | texLoadTexturePvmFile("AVA_BACK", &ava_back_TEXLIST); 48 | } 49 | 50 | void ReleaseAvaBackForMission() 51 | { 52 | late_ReleaseTexture(&MIS_C_TEXLIST); 53 | } 54 | 55 | void Mission_Init(const char* path, const HelperFunctions & helperFunctions) 56 | { 57 | DrawMiClearStatus_h.Hook(DrawMiClearStatus_r); 58 | WriteCall((void*)0x00590E87, LoadAvaBackForMission); 59 | WriteCall((void*)0x0040C99E, ReleaseAvaBackForMission); 60 | char pathbuf[MAX_PATH]; 61 | HMODULE GoalRing = GetModuleHandle(L"GoalRing"); 62 | // English mission PVRs 63 | ReplacePNG_MissionE("MISSION_A_BALRING_E"); 64 | ReplacePNG_MissionE("MISSION_A_BALZERO_E"); 65 | ReplacePNG_MissionE("MISSION_A_FIN_E"); 66 | ReplacePNG_MissionE("MISSION_A_HOT_E"); 67 | ReplacePNG_MissionE("MISSION_A_TWIN_E"); 68 | ReplacePNG_MissionE("MISSION_BIG_1K_E"); 69 | ReplacePNG_MissionE("MISSION_BIG_2K_E"); 70 | ReplacePNG_MissionE("MISSION_BIG_FROG_E"); 71 | ReplacePNG_MissionE("MISSION_G_103RING_E"); 72 | ReplacePNG_MissionE("MISSION_G_103_E"); 73 | ReplacePNG_MissionE("MISSION_G_104RING_E"); 74 | ReplacePNG_MissionE("MISSION_G_104_E"); 75 | ReplacePNG_MissionE("MISSION_G_105RING_E"); 76 | ReplacePNG_MissionE("MISSION_G_105_E"); 77 | ReplacePNG_MissionE("MISSION_G_EME_E"); 78 | ReplacePNG_MissionE("MISSION_G_FIN_E"); 79 | ReplacePNG_MissionE("MISSION_G_FROGRING_E"); 80 | ReplacePNG_MissionE("MISSION_G_FROG_E"); 81 | ReplacePNG_MissionE("MISSION_G_SONICDRING_E"); 82 | ReplacePNG_MissionE("MISSION_G_HOT_E"); 83 | ReplacePNG_MissionE("MISSION_G_RED_E"); 84 | ReplacePNG_MissionE("MISSION_G_SONICD_E"); 85 | ReplacePNG_MissionE("MISSION_G_WIN_E"); 86 | ReplacePNG_MissionE("MISSION_K_1MIN_E"); 87 | ReplacePNG_MissionE("MISSION_K_2MIN_E"); 88 | ReplacePNG_MissionE("MISSION_K_3EME_E"); 89 | ReplacePNG_MissionE("MISSION_K_NOHINT_E"); 90 | ReplacePNG_MissionE("MISSION_S_EGGC_E"); 91 | ReplacePNG_MissionE("MISSION_S_EMECASINO_E"); 92 | ReplacePNG_MissionE("MISSION_S_EMESNOW_E"); 93 | ReplacePNG_MissionE("MISSION_S_EMEWIND_E"); 94 | ReplacePNG_MissionE("MISSION_S_FEGG_E"); 95 | ReplacePNG_MissionE("MISSION_S_ISEKI_E"); 96 | ReplacePNG_MissionE("MISSION_S_TAILS_E"); 97 | ReplacePNG_MissionE("MISSION_T_EMECASINO_E"); 98 | ReplacePNG_MissionE("MISSION_T_EMESNOW_E"); 99 | ReplacePNG_MissionE("MISSION_T_EMEWIND_E"); 100 | ReplacePNG_MissionE("MISSION_T_FASTEGG_E"); 101 | ReplacePNG_MissionE("MISSION_T_FASTSONIC_E"); 102 | ReplacePNG_MissionE("MISSION_T_MISS_E"); 103 | ReplacePNG_MissionE("MISSION_T_RINGEGG_E"); 104 | ReplacePNG_MissionE("MISSION_T_RINGSONIC_E"); 105 | // Japanese mission PVRs 106 | ReplacePNG_MissionJ("MISSION_A_AFIN"); 107 | ReplacePNG_MissionJ("MISSION_A_AHOT"); 108 | ReplacePNG_MissionJ("MISSION_A_ATWI"); 109 | ReplacePNG_MissionJ("MISSION_A_BALMIN"); 110 | ReplacePNG_MissionJ("MISSION_A_BALRING"); 111 | ReplacePNG_MissionJ("MISSION_A_BALZERO"); 112 | ReplacePNG_MissionJ("MISSION_BIG_1K"); 113 | ReplacePNG_MissionJ("MISSION_BIG_2K"); 114 | ReplacePNG_MissionJ("MISSION_BIG_FROG"); 115 | ReplacePNG_MissionJ("MISSION_G_103"); 116 | ReplacePNG_MissionJ("MISSION_G_103RING"); 117 | ReplacePNG_MissionJ("MISSION_G_103SEC"); 118 | ReplacePNG_MissionJ("MISSION_G_104"); 119 | ReplacePNG_MissionJ("MISSION_G_104RING"); 120 | ReplacePNG_MissionJ("MISSION_G_105"); 121 | ReplacePNG_MissionJ("MISSION_G_105RING"); 122 | ReplacePNG_MissionJ("MISSION_G_105SEC"); 123 | ReplacePNG_MissionJ("MISSION_G_AEME"); 124 | ReplacePNG_MissionJ("MISSION_G_AFIN"); 125 | ReplacePNG_MissionJ("MISSION_G_AHOT"); 126 | ReplacePNG_MissionJ("MISSION_G_ARED"); 127 | ReplacePNG_MissionJ("MISSION_G_AWIN"); 128 | ReplacePNG_MissionJ("MISSION_G_BEME"); 129 | ReplacePNG_MissionJ("MISSION_G_BFIN"); 130 | ReplacePNG_MissionJ("MISSION_G_BHOT"); 131 | ReplacePNG_MissionJ("MISSION_G_BRED"); 132 | ReplacePNG_MissionJ("MISSION_G_BWIN"); 133 | ReplacePNG_MissionJ("MISSION_G_FROG"); 134 | ReplacePNG_MissionJ("MISSION_G_FROGRING"); 135 | ReplacePNG_MissionJ("MISSION_G_FROGSEC"); 136 | ReplacePNG_MissionJ("MISSION_G_SONICD"); 137 | ReplacePNG_MissionJ("MISSION_G_SONICDRING"); 138 | ReplacePNG_MissionJ("MISSION_G_SONICDSEC"); 139 | ReplacePNG_MissionJ("MISSION_K_1MIN"); 140 | ReplacePNG_MissionJ("MISSION_K_2MIN"); 141 | ReplacePNG_MissionJ("MISSION_K_3EME"); 142 | ReplacePNG_MissionJ("MISSION_K_NOHINT"); 143 | ReplacePNG_MissionJ("MISSION_S_BOXMIN"); 144 | ReplacePNG_MissionJ("MISSION_S_EGGC"); 145 | ReplacePNG_MissionJ("MISSION_S_EMECASINO"); 146 | ReplacePNG_MissionJ("MISSION_S_EMESNOW"); 147 | ReplacePNG_MissionJ("MISSION_S_EMEWIND"); 148 | ReplacePNG_MissionJ("MISSION_S_FEGG"); 149 | ReplacePNG_MissionJ("MISSION_S_ISEKI"); 150 | ReplacePNG_MissionJ("MISSION_S_TAILS"); 151 | ReplacePNG_MissionJ("MISSION_T_EMECASINO"); 152 | ReplacePNG_MissionJ("MISSION_T_EMESNOW"); 153 | ReplacePNG_MissionJ("MISSION_T_EMEWIND"); 154 | ReplacePNG_MissionJ("MISSION_T_FASTEGG"); 155 | ReplacePNG_MissionJ("MISSION_T_FASTSONIC"); 156 | ReplacePNG_MissionJ("MISSION_T_MISS"); 157 | ReplacePNG_MissionJ("MISSION_T_RINGEGG"); 158 | ReplacePNG_MissionJ("MISSION_T_RINGSONIC"); 159 | if (GoalRing == nullptr) 160 | { 161 | // Japanese 162 | ReplacePNG_MissionJ("MISSION_S_2MIN"); 163 | ReplacePNG_MissionJ("MISSION_S_2MINH"); 164 | ReplacePNG_MissionJ("MISSION_S_3MIN"); 165 | ReplacePNG_MissionJ("MISSION_S_4MIN"); 166 | ReplacePNG_MissionJ("MISSION_S_4MINH"); 167 | ReplacePNG_MissionJ("MISSION_S_5MIN"); 168 | ReplacePNG_MissionJ("MISSION_S_BOX"); 169 | ReplacePNG_MissionJ("MISSION_S_RINGBOX"); 170 | ReplacePNG_MissionJ("MISSION_T_BOX"); 171 | // English 172 | ReplacePNG_MissionE("MISSION_S_BOX_E"); 173 | ReplacePNG_MissionE("MISSION_S_BOX25MIN_E"); 174 | ReplacePNG_MissionE("MISSION_S_BOX2MIN_E"); 175 | ReplacePNG_MissionE("MISSION_S_BOX3MIN_E"); 176 | ReplacePNG_MissionE("MISSION_S_BOX45MIN_E"); 177 | ReplacePNG_MissionE("MISSION_S_BOX4MIN_E"); 178 | ReplacePNG_MissionE("MISSION_S_BOX5MIN_E"); 179 | ReplacePNG_MissionE("MISSION_S_RINGBOX_E"); 180 | ReplacePNG_MissionE("MISSION_T_BOX_E"); 181 | } 182 | else 183 | { 184 | // Japanese 185 | ReplacePNG_GoalRing("MISSION_S_2MIN"); 186 | ReplacePNG_GoalRing("MISSION_S_2MINH"); 187 | ReplacePNG_GoalRing("MISSION_S_3MIN"); 188 | ReplacePNG_GoalRing("MISSION_S_4MIN"); 189 | ReplacePNG_GoalRing("MISSION_S_4MINH"); 190 | ReplacePNG_GoalRing("MISSION_S_5MIN"); 191 | ReplacePNG_GoalRing("MISSION_S_BOX"); 192 | ReplacePNG_GoalRing("MISSION_S_RINGBOX"); 193 | ReplacePNG_GoalRing("MISSION_T_BOX"); 194 | // English 195 | ReplacePNG_GoalRing("MISSION_S_BOX_E"); 196 | ReplacePNG_GoalRing("MISSION_S_BOX25MIN_E"); 197 | ReplacePNG_GoalRing("MISSION_S_BOX2MIN_E"); 198 | ReplacePNG_GoalRing("MISSION_S_BOX3MIN_E"); 199 | ReplacePNG_GoalRing("MISSION_S_BOX45MIN_E"); 200 | ReplacePNG_GoalRing("MISSION_S_BOX4MIN_E"); 201 | ReplacePNG_GoalRing("MISSION_S_BOX5MIN_E"); 202 | ReplacePNG_GoalRing("MISSION_S_RINGBOX_E"); 203 | ReplacePNG_GoalRing("MISSION_T_BOX_E"); 204 | } 205 | // French mission PVRs 206 | ReplacePNG_MissionF("MISSION_A_BALRING_F"); 207 | ReplacePNG_MissionF("MISSION_A_BALZERO_F"); 208 | ReplacePNG_MissionF("MISSION_A_FIN_F"); 209 | ReplacePNG_MissionF("MISSION_A_HOT_F"); 210 | ReplacePNG_MissionF("MISSION_A_TWIN_F"); 211 | ReplacePNG_MissionF("MISSION_BIG_1K_F"); 212 | ReplacePNG_MissionF("MISSION_BIG_2K_F"); 213 | ReplacePNG_MissionF("MISSION_BIG_FROG_F"); 214 | ReplacePNG_MissionF("MISSION_G_103RING_F"); 215 | ReplacePNG_MissionF("MISSION_G_103_F"); 216 | ReplacePNG_MissionF("MISSION_G_104RING_F"); 217 | ReplacePNG_MissionF("MISSION_G_104_F"); 218 | ReplacePNG_MissionF("MISSION_G_105RING_F"); 219 | ReplacePNG_MissionF("MISSION_G_105_F"); 220 | ReplacePNG_MissionF("MISSION_G_EME_F"); 221 | ReplacePNG_MissionF("MISSION_G_FIN_F"); 222 | ReplacePNG_MissionF("MISSION_G_FROGRING_F"); 223 | ReplacePNG_MissionF("MISSION_G_FROG_F"); 224 | ReplacePNG_MissionF("MISSION_G_HOT_F"); 225 | ReplacePNG_MissionF("MISSION_G_RED_F"); 226 | ReplacePNG_MissionF("MISSION_G_SONICDRING_F"); 227 | ReplacePNG_MissionF("MISSION_G_SONICD_F"); 228 | ReplacePNG_MissionF("MISSION_G_WIN_F"); 229 | ReplacePNG_MissionF("MISSION_K_1MIN_F"); 230 | ReplacePNG_MissionF("MISSION_K_2MIN_F"); 231 | ReplacePNG_MissionF("MISSION_K_3EME_F"); 232 | ReplacePNG_MissionF("MISSION_K_NOHINT_F"); 233 | ReplacePNG_MissionF("MISSION_S_BOX25MIN_F"); 234 | ReplacePNG_MissionF("MISSION_S_BOX2MIN_F"); 235 | ReplacePNG_MissionF("MISSION_S_BOX3MIN_F"); 236 | ReplacePNG_MissionF("MISSION_S_BOX45MIN_F"); 237 | ReplacePNG_MissionF("MISSION_S_BOX4MIN_F"); 238 | ReplacePNG_MissionF("MISSION_S_BOX5MIN_F"); 239 | ReplacePNG_MissionF("MISSION_S_BOX_F"); 240 | ReplacePNG_MissionF("MISSION_S_EGGC_F"); 241 | ReplacePNG_MissionF("MISSION_S_EMECASINO_F"); 242 | ReplacePNG_MissionF("MISSION_S_EMESNOW_F"); 243 | ReplacePNG_MissionF("MISSION_S_EMEWIND_F"); 244 | ReplacePNG_MissionF("MISSION_S_FEGG_F"); 245 | ReplacePNG_MissionF("MISSION_S_ISEKI_F"); 246 | ReplacePNG_MissionF("MISSION_S_RINGBOX_F"); 247 | ReplacePNG_MissionF("MISSION_S_TAILS_F"); 248 | ReplacePNG_MissionF("MISSION_T_BOX_F"); 249 | ReplacePNG_MissionF("MISSION_T_EMECASINO_F"); 250 | ReplacePNG_MissionF("MISSION_T_EMESNOW_F"); 251 | ReplacePNG_MissionF("MISSION_T_EMEWIND_F"); 252 | ReplacePNG_MissionF("MISSION_T_FASTEGG_F"); 253 | ReplacePNG_MissionF("MISSION_T_FASTSONIC_F"); 254 | ReplacePNG_MissionF("MISSION_T_MISS_F"); 255 | ReplacePNG_MissionF("MISSION_T_RINGEGG_F"); 256 | ReplacePNG_MissionF("MISSION_T_RINGSONIC_F"); 257 | } -------------------------------------------------------------------------------- /HD_GUI/Tutorials.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Common.h" 3 | #include "Tutorials.h" 4 | 5 | float PadManuXOffset_F = 175.0f; 6 | float PadManuXOffset_General = 220.0f; 7 | float PadManuXOffset_J = 200.0f; 8 | float PadManuYOffset = 136.0f; 9 | float PadManuYOffset2 = 105.0f; 10 | float PadManuYMultiplier = 1.0f; 11 | 12 | void GreenRect_Wrapper(float x, float y, float z, float width, float height) 13 | { 14 | njTextureShadingMode(1); 15 | GreenMenuRect_Draw(x, y, z, width, height); 16 | njTextureShadingMode(2); 17 | } 18 | 19 | void Tutorials_Init(const char* path, const HelperFunctions& helperFunctions) 20 | { 21 | // Fix green rectangle in tutorials 22 | WriteCall((void*)0x0064393E, GreenRect_Wrapper); 23 | WriteData((float*)0x004333A0, -1.0f); // Screen fade for tutorials 24 | WriteData((float*)0x004333AE, -1.0f); // Screen fade for tutorials 25 | // PVMs 26 | ReplacePVMX("TUTO_CMN"); 27 | ReplacePVMX("TUTO_CMN_E"); 28 | ReplacePVMX("TUTOMSG_AMY_E"); 29 | ReplacePVMX("TUTOMSG_BIG_E"); 30 | ReplacePVMX("TUTOMSG_E102_E"); 31 | ReplacePVMX("TUTOMSG_KNUCKLES_E"); 32 | ReplacePVMX("TUTOMSG_SONIC_E"); 33 | ReplacePVMX("TUTOMSG_TAILS_E"); 34 | ReplacePVMX("TUTOMSG_AMY"); 35 | ReplacePVMX("TUTOMSG_AMY_F"); 36 | ReplacePVMX("TUTOMSG_AMY_G"); 37 | ReplacePVMX("TUTOMSG_AMY_S"); 38 | ReplacePVMX("TUTOMSG_BIG"); 39 | ReplacePVMX("TUTOMSG_BIG_F"); 40 | ReplacePVMX("TUTOMSG_BIG_G"); 41 | ReplacePVMX("TUTOMSG_BIG_S"); 42 | ReplacePVMX("TUTOMSG_E102"); 43 | ReplacePVMX("TUTOMSG_E102_F"); 44 | ReplacePVMX("TUTOMSG_E102_G"); 45 | ReplacePVMX("TUTOMSG_E102_S"); 46 | ReplacePVMX("TUTOMSG_KNUCKLES"); 47 | ReplacePVMX("TUTOMSG_KNUCKLES_F"); 48 | ReplacePVMX("TUTOMSG_KNUCKLES_G"); 49 | ReplacePVMX("TUTOMSG_KNUCKLES_S"); 50 | ReplacePVMX("TUTOMSG_SONIC"); 51 | ReplacePVMX("TUTOMSG_SONIC_F"); 52 | ReplacePVMX("TUTOMSG_SONIC_G"); 53 | ReplacePVMX("TUTOMSG_SONIC_S"); 54 | ReplacePVMX("TUTOMSG_TAILS"); 55 | ReplacePVMX("TUTOMSG_TAILS_F"); 56 | ReplacePVMX("TUTOMSG_TAILS_G"); 57 | ReplacePVMX("TUTOMSG_TAILS_S"); 58 | WriteData((float**)0x0064328D, &PadManuXOffset_F); 59 | WriteData((float**)0x00643295, &PadManuXOffset_General); 60 | WriteData((float**)0x00643280, &PadManuXOffset_J); 61 | WriteData((float**)0x006432C6, &PadManuYOffset); 62 | WriteData((float**)0x006432E4, &PadManuYOffset2); 63 | WriteData((float**)0x006432D4, &PadManuYMultiplier); 64 | // Sonic 65 | // English 66 | TutoScreenXSonic_E[0].BoxScaleX = 390; 67 | TutoScreenXSonic_E[0].BoxScaleY = 144; 68 | TutoScreenXSonic_E[0].BoxX = 210; 69 | TutoScreenXSonic_E[4].BoxScaleY = 160; 70 | TutorialLayoutX_Sonic_Page1_E[1].XOffset = 136; // Rotate camera 71 | TutorialLayoutX_Sonic_Page1_E[1].YOffset = 0; // Rotate camera 72 | TutorialLayoutX_Sonic_Page1_E[2].XOffset = 136; // Maneuver character 73 | TutorialLayoutX_Sonic_Page1_E[2].YOffset = 24; // Maneuver character 74 | TutorialLayoutX_Sonic_Page1_E[4].XOffset = 136; // A button 75 | TutorialLayoutX_Sonic_Page1_E[4].YOffset = 64; // A button 76 | TutorialLayoutX_Sonic_Page1_E[4].TexID = 3; 77 | TutorialLayoutX_Sonic_Page1_E[5].TexID = 4; 78 | TutorialLayoutX_Sonic_Page1_E[5].XOffset = 136; 79 | TutorialLayoutX_Sonic_Page1_E[5].YOffset = 96; 80 | WriteData((__int16*)0x02BC3AE2, (__int16)2000); // Hide an extra item in controls page (all langs) 81 | // Japanese 82 | TutoScreenXSonic_J[0].BoxScaleX = 400; 83 | TutoScreenXSonic_J[0].BoxScaleY = 144; 84 | TutoScreenXSonic_J[0].BoxX = 200; 85 | TutoScreenXSonic_J[4].BoxScaleY = 160; 86 | TutorialLayoutX_Sonic_Page1_J[1].XOffset = 136; // Rotate camera 87 | TutorialLayoutX_Sonic_Page1_J[1].YOffset = 0; // Rotate camera 88 | TutorialLayoutX_Sonic_Page1_J[2].XOffset = 136; // Maneuver character 89 | TutorialLayoutX_Sonic_Page1_J[2].YOffset = 24; // Maneuver character 90 | TutorialLayoutX_Sonic_Page1_J[3].XOffset = 136; // A button 91 | TutorialLayoutX_Sonic_Page1_J[3].YOffset = 64; // A button 92 | TutorialLayoutX_Sonic_Page1_J[3].TexID = 3; 93 | TutorialLayoutX_Sonic_Page1_J[4].TexID = 4; 94 | TutorialLayoutX_Sonic_Page1_J[4].XOffset = 136; 95 | TutorialLayoutX_Sonic_Page1_J[4].YOffset = 96; 96 | // German 97 | TutoScreenXSonic_G[0].BoxScaleX = 380; 98 | TutoScreenXSonic_G[0].BoxScaleY = 144; 99 | TutoScreenXSonic_G[0].BoxX = 220; 100 | TutoScreenXSonic_G[3].BoxScaleY = 160; 101 | TutoScreenXSonic_G[4].BoxScaleY = 160; 102 | // French 103 | TutoScreenXSonic_F[4].BoxScaleY = 192; 104 | TutoScreenXSonic_F[0].BoxScaleX = 425; 105 | TutoScreenXSonic_F[0].BoxScaleY = 144; 106 | TutoScreenXSonic_F[0].BoxX = 175; 107 | // Spanish 108 | TutoScreenXSonic_S[0].BoxScaleX = 370; 109 | TutoScreenXSonic_S[0].BoxScaleY = 144; 110 | TutoScreenXSonic_S[0].BoxX = 230; 111 | TutoScreenXSonic_S[4].BoxScaleY = 192; 112 | // Tails 113 | // English 114 | TutoScreenXTails_E[0].BoxScaleX = 390; 115 | TutoScreenXTails_E[0].BoxScaleY = 144; 116 | TutoScreenXTails_E[0].BoxX = 210; 117 | TutoScreenXTails_E[4].BoxScaleY = 160; 118 | TutorialLayoutX_SharedTailsKnucklesPage1_E[0].XOffset = 136; // Rotate camera 119 | TutorialLayoutX_SharedTailsKnucklesPage1_E[0].YOffset = 0; // Rotate camera 120 | TutorialLayoutX_SharedTailsKnucklesPage1_E[1].XOffset = 136; // Maneuver character 121 | TutorialLayoutX_SharedTailsKnucklesPage1_E[1].YOffset = 24; // Maneuver character 122 | TutorialLayoutX_SharedTailsKnucklesPage1_E[3].XOffset = 136; // A button 123 | TutorialLayoutX_SharedTailsKnucklesPage1_E[3].YOffset = 96; // A button 124 | TutorialLayoutX_Tails_Page1_E.XOffset = 136; // Tail attack 125 | TutorialLayoutX_Tails_Page1_E.YOffset = 64; // Tail attack 126 | // Japanese 127 | TutoScreenXTails_J[0].BoxScaleX = 400; 128 | TutoScreenXTails_J[0].BoxScaleY = 144; 129 | TutoScreenXTails_J[0].BoxX = 200; 130 | TutoScreenXTails_J[4].BoxScaleY = 160; 131 | TutorialLayoutX_SharedTailsKnucklesPage1_J[0].XOffset = 136; // Rotate camera 132 | TutorialLayoutX_SharedTailsKnucklesPage1_J[0].YOffset = 0; // Rotate camera 133 | TutorialLayoutX_SharedTailsKnucklesPage1_J[1].XOffset = 136; // Maneuver character 134 | TutorialLayoutX_SharedTailsKnucklesPage1_J[1].YOffset = 24; // Maneuver character 135 | TutorialLayoutX_SharedTailsKnucklesPage1_J[2].XOffset = 136; // A button 136 | TutorialLayoutX_SharedTailsKnucklesPage1_J[2].YOffset = 96; // A button 137 | TutorialLayoutX_Tails_Page1_J.XOffset = 136; // Tail attack 138 | TutorialLayoutX_Tails_Page1_J.YOffset = 64; // Tail attack 139 | // French 140 | TutoScreenXTails_F[4].BoxScaleY = 192; 141 | TutoScreenXTails_F[0].BoxScaleX = 425; 142 | TutoScreenXTails_F[0].BoxScaleY = 144; 143 | TutoScreenXTails_F[0].BoxX = 175; 144 | // German 145 | TutoScreenXTails_G[0].BoxScaleX = 390; 146 | TutoScreenXTails_G[0].BoxScaleY = 144; 147 | TutoScreenXTails_G[0].BoxX = 210; 148 | TutoScreenXTails_G[3].BoxScaleY = 128; 149 | TutoScreenXTails_G[4].BoxScaleY = 160; 150 | TutoScreenXTails_G[0].BoxScaleX = 380; 151 | TutoScreenXTails_G[0].BoxScaleY = 144; 152 | TutoScreenXTails_G[0].BoxX = 220; 153 | WriteData((__int16*)0x02BC3E9E, (__int16)2000); // Hide an extra item in controls page 154 | // Spanish 155 | TutoScreenXTails_S[0].BoxScaleX = 370; 156 | TutoScreenXTails_S[0].BoxScaleY = 144; 157 | TutoScreenXTails_S[0].BoxX = 230; 158 | TutoScreenXTails_S[4].BoxScaleY = 192; 159 | // Knuckles 160 | // English 161 | TutoScreenXKnuckles_E[0].BoxScaleX = 390; 162 | TutoScreenXKnuckles_E[0].BoxScaleY = 144; 163 | TutoScreenXKnuckles_E[0].BoxX = 210; 164 | TutoScreenXKnuckles_E[4].BoxX = 180; 165 | TutoScreenXKnuckles_E[4].BoxScaleY = 128; 166 | TutoScreenXKnuckles_E[4].BoxScaleX = 425; 167 | TutoScreenXKnuckles_E[5].BoxScaleY = 160; 168 | TutorialLayoutX_Knuckles_Page1_E.XOffset = 136; // Punch attack 169 | TutorialLayoutX_Knuckles_Page1_E.YOffset = 64; // Punch attack 170 | WriteData<1>((char*)0x02BC4308, 0x03); // Number of items in Maximum Heat screen, remove unnecessary line 171 | // Japanese 172 | TutoScreenXKnuckles_J[0].BoxScaleX = 400; 173 | TutoScreenXKnuckles_J[0].BoxScaleY = 144; 174 | TutoScreenXKnuckles_J[0].BoxX = 200; 175 | TutoScreenXKnuckles_J[4].BoxX = 180; 176 | TutoScreenXKnuckles_J[4].BoxScaleY = 128; 177 | TutoScreenXKnuckles_J[4].BoxScaleX = 425; 178 | TutoScreenXKnuckles_J[5].BoxScaleY = 160; 179 | TutorialLayoutX_Knuckles_Page1_J.XOffset = 136; // Punch attack 180 | TutorialLayoutX_Knuckles_Page1_J.YOffset = 64; // Punch attack 181 | // German 182 | TutoScreenXKnuckles_G[0].BoxScaleX = 380; 183 | TutoScreenXKnuckles_G[0].BoxScaleY = 144; 184 | TutoScreenXKnuckles_G[0].BoxX = 220; 185 | TutoScreenXKnuckles_G[2].BoxScaleY = 128; 186 | TutoScreenXKnuckles_G[4].BoxX = 180; 187 | TutoScreenXKnuckles_G[4].BoxScaleX = 420; 188 | TutoScreenXKnuckles_G[4].BoxScaleY = 128; 189 | TutoScreenXKnuckles_G[5].BoxScaleY = 160; 190 | WriteData((__int16*)0x02BC42E0, (__int16)2000); // Hide an extra item in Climbing page 191 | // French 192 | TutoScreenXKnuckles_F[0].BoxScaleX = 430; 193 | TutoScreenXKnuckles_F[0].BoxScaleY = 144; 194 | TutoScreenXKnuckles_F[0].BoxX = 170; 195 | TutoScreenXKnuckles_F[1].BoxScaleX = 455; 196 | TutoScreenXKnuckles_F[1].BoxX = 145; 197 | TutoScreenXKnuckles_F[4].BoxScaleX = 475; 198 | TutoScreenXKnuckles_F[4].BoxX = 125; 199 | TutoScreenXKnuckles_F[4].BoxScaleY = 128; 200 | TutoScreenXKnuckles_F[5].BoxScaleY = 192; 201 | WriteData((__int16*)0x02BC3E9E, (__int16)2000); // Hide an extra item in Controls page 202 | WriteData((__int16*)0x02BC433A, (__int16)2000); // Hide an extra item in Maximum Heat page 203 | WriteData((__int16*)0x02BC4340, (__int16)2000); // Hide an extra item in Maximum Heat page 204 | // Spanish 205 | TutoScreenXKnuckles_S[0].BoxScaleX = 370; 206 | TutoScreenXKnuckles_S[0].BoxScaleY = 144; 207 | TutoScreenXKnuckles_S[0].BoxX = 230; 208 | TutoScreenXKnuckles_S[4].BoxScaleX = 415; 209 | TutoScreenXKnuckles_S[4].BoxX = 190; 210 | TutoScreenXKnuckles_S[4].BoxScaleY = 128; 211 | TutoScreenXKnuckles_S[5].BoxScaleY = 192; 212 | // Amy 213 | // English 214 | TutoScreenXAmy_E[0].BoxScaleX = 390; 215 | TutoScreenXAmy_E[0].BoxScaleY = 144; 216 | TutoScreenXAmy_E[0].BoxX = 210; 217 | TutoScreenXAmy_E[4].BoxScaleY = 160; 218 | TutorialLayoutX_AmyGamma_Page1_E[1].XOffset = 136; // Rotate camera 219 | TutorialLayoutX_AmyGamma_Page1_E[1].YOffset = 0; // Rotate camera 220 | TutorialLayoutX_AmyGamma_Page1_E[2].XOffset = 136; // Maneuver character 221 | TutorialLayoutX_AmyGamma_Page1_E[2].YOffset = 24; // Maneuver character 222 | TutorialLayoutX_Amy_Page1_E[0].XOffset = 136; // A 223 | TutorialLayoutX_Amy_Page1_E[0].YOffset = 96; // A 224 | TutorialLayoutX_Amy_Page1_E[1].XOffset = 136; // B 225 | TutorialLayoutX_Amy_Page1_E[1].YOffset = 64; // B 226 | // Japanese 227 | TutoScreenXAmy_J[0].BoxScaleX = 400; 228 | TutoScreenXAmy_J[0].BoxScaleY = 144; 229 | TutoScreenXAmy_J[0].BoxX = 200; 230 | TutoScreenXAmy_J[4].BoxScaleY = 160; 231 | TutorialLayoutX_AmyGamma_Page1_J[1].XOffset = 136; // Rotate camera 232 | TutorialLayoutX_AmyGamma_Page1_J[1].YOffset = 0; // Rotate camera 233 | TutorialLayoutX_AmyGamma_Page1_J[2].XOffset = 136; // Maneuver character 234 | TutorialLayoutX_AmyGamma_Page1_J[2].YOffset = 24; // Maneuver character 235 | TutorialLayoutX_Amy_Page1_J[0].XOffset = 136; // A 236 | TutorialLayoutX_Amy_Page1_J[0].YOffset = 96; // A 237 | TutorialLayoutX_Amy_Page1_J[1].XOffset = 136; // B 238 | TutorialLayoutX_Amy_Page1_J[1].YOffset = 64; // B 239 | // German 240 | TutoScreenXAmy_G[0].BoxScaleX = 380; 241 | TutoScreenXAmy_G[0].BoxScaleY = 144; 242 | TutoScreenXAmy_G[0].BoxX = 220; 243 | TutoScreenXAmy_G[4].BoxScaleY = 160; 244 | WriteData((__int16*)0x02BC46FA, (__int16)2000); // Hide an extra item in controls page 245 | // French 246 | TutoScreenXAmy_F[0].BoxScaleX = 425; 247 | TutoScreenXAmy_F[0].BoxScaleY = 144; 248 | TutoScreenXAmy_F[0].BoxX = 175; 249 | TutoScreenXAmy_F[4].BoxScaleY = 192; 250 | // Spanish 251 | TutoScreenXAmy_S[0].BoxScaleX = 370; 252 | TutoScreenXAmy_S[0].BoxScaleY = 144; 253 | TutoScreenXAmy_S[0].BoxX = 230; 254 | TutoScreenXAmy_S[4].BoxScaleY = 192; 255 | // Big 256 | // English 257 | TutoScreenXBig_E[0].BoxScaleX = 390; 258 | TutoScreenXBig_E[0].BoxScaleY = 144; 259 | TutoScreenXBig_E[0].BoxX = 210; 260 | TutoScreenXBig_E[4].BoxScaleY = 128; 261 | TutoScreenXBig_E[7].BoxScaleX = 420; 262 | TutoScreenXBig_E[7].BoxX = 180; 263 | TutorialLayoutX_BigPage1_E[1].XOffset = 136; // Rotate camera 264 | TutorialLayoutX_BigPage1_E[1].YOffset = 0; // Rotate camera 265 | TutorialLayoutX_BigPage1_E[2].XOffset = 136; // Maneuver character 266 | TutorialLayoutX_BigPage1_E[2].YOffset = 24; // Maneuver character 267 | TutorialLayoutX_BigPage1Part2_E[0].XOffset = 136; // A 268 | TutorialLayoutX_BigPage1Part2_E[0].YOffset = 96; // A 269 | TutorialLayoutX_BigPage1Part2_E[1].XOffset = 136; // B 270 | TutorialLayoutX_BigPage1Part2_E[1].YOffset = 64; // B 271 | TutorialLayoutX_BigPage5_E[2].TexID = 32; // Hide "Tugging the rod" 272 | TutorialLayoutX_BigPage5_E[3].YOffset = 64; // Move A up 273 | TutorialLayoutX_BigPage5_E[4].YOffset = 96; // Move B up 274 | // Japanese 275 | TutoScreenXBig_J[0].BoxScaleX = 400; 276 | TutoScreenXBig_J[0].BoxScaleY = 144; 277 | TutoScreenXBig_J[0].BoxX = 200; 278 | TutoScreenXBig_J[4].BoxScaleY = 160; 279 | TutoScreenXBig_J[7].BoxScaleX = 400; 280 | TutoScreenXBig_J[7].BoxX = 200; 281 | TutorialLayoutX_BigPage1Part2_J[0].XOffset = 136; // A 282 | TutorialLayoutX_BigPage1Part2_J[0].YOffset = 96; // A 283 | TutorialLayoutX_BigPage1Part2_J[1].XOffset = 136; // B 284 | TutorialLayoutX_BigPage1Part2_J[1].YOffset = 64; // B 285 | // German 286 | TutoScreenXBig_G[0].BoxScaleX = 395; 287 | TutoScreenXBig_G[0].BoxScaleY = 144; 288 | TutoScreenXBig_G[0].BoxX = 205; 289 | TutoScreenXBig_G[4].BoxScaleY = 128; 290 | WriteData((__int16*)0x02BC4E9E, (__int16)2000); // Hide an extra item in controls page 291 | // French 292 | TutoScreenXBig_F[0].BoxScaleX = 425; 293 | TutoScreenXBig_F[0].BoxScaleY = 144; 294 | TutoScreenXBig_F[0].BoxX = 175; 295 | TutoScreenXBig_F[4].BoxScaleY = 128; 296 | TutoScreenXBig_F[7].BoxScaleX = 445; 297 | TutoScreenXBig_F[7].BoxX = 155; 298 | // Spanish 299 | TutoScreenXBig_S[0].BoxScaleX = 370; 300 | TutoScreenXBig_S[0].BoxScaleY = 144; 301 | TutoScreenXBig_S[0].BoxX = 230; 302 | TutoScreenXBig_S[4].BoxScaleX = 275; 303 | TutoScreenXBig_S[4].BoxX = 325; 304 | TutoScreenXBig_S[4].BoxScaleY = 128; 305 | TutoScreenXBig_S[7].BoxScaleX = 420; 306 | TutoScreenXBig_S[7].BoxX = 180; 307 | TutoScreenXBig_S[7].BoxScaleX = 475; 308 | TutoScreenXBig_S[7].BoxX = 125; 309 | // Gamma 310 | // English 311 | TutoScreenXGamma_E[0].BoxScaleX = 390; 312 | TutoScreenXGamma_E[0].BoxScaleY = 144; 313 | TutoScreenXGamma_E[0].BoxX = 210; 314 | TutoScreenXGamma_E[4].BoxScaleY = 160; 315 | TutorialLayoutX_Gamma_Page1_E[0].XOffset = 136; // A 316 | TutorialLayoutX_Gamma_Page1_E[0].YOffset = 96; // A 317 | TutorialLayoutX_Gamma_Page1_E[1].XOffset = 136; // B 318 | TutorialLayoutX_Gamma_Page1_E[1].YOffset = 64; // B 319 | // Japanese 320 | TutoScreenXGamma_J[0].BoxScaleX = 400; 321 | TutoScreenXGamma_J[0].BoxScaleY = 144; 322 | TutoScreenXGamma_J[0].BoxX = 200; 323 | TutoScreenXGamma_J[4].BoxScaleY = 160; 324 | TutorialLayoutX_Gamma_Page1_J[0].XOffset = 136; // A 325 | TutorialLayoutX_Gamma_Page1_J[0].YOffset = 96; // A 326 | TutorialLayoutX_Gamma_Page1_J[1].XOffset = 136; // B 327 | TutorialLayoutX_Gamma_Page1_J[1].YOffset = 64; // B 328 | // German 329 | TutoScreenXGamma_G[4].BoxScaleY = 160; 330 | TutoScreenXGamma_G[0].BoxScaleX = 380; 331 | TutoScreenXGamma_G[0].BoxScaleY = 144; 332 | TutoScreenXGamma_G[0].BoxX = 220; 333 | // French 334 | TutoScreenXGamma_F[0].BoxScaleX = 425; 335 | TutoScreenXGamma_F[0].BoxScaleY = 144; 336 | TutoScreenXGamma_F[0].BoxX = 175; 337 | TutoScreenXGamma_F[1].BoxScaleY = 192; 338 | TutoScreenXGamma_F[4].BoxScaleY = 192; 339 | WriteData((__int16*)0x02BC4AE4, (__int16)2000); // Hide an extra item in the second page 340 | // Spanish 341 | TutoScreenXGamma_S[0].BoxScaleX = 370; 342 | TutoScreenXGamma_S[0].BoxScaleY = 144; 343 | TutoScreenXGamma_S[0].BoxX = 230; 344 | TutoScreenXGamma_S[4].BoxScaleY = 192; 345 | } 346 | 347 | void Tutorials_OnFrame() 348 | { 349 | if (GetCharacterSelection() == 2) 350 | PadManuXOffset_F = 170; 351 | else 352 | PadManuXOffset_F = 175; 353 | switch (TextLanguage) 354 | { 355 | case 3: 356 | PadManuXOffset_General = 230; 357 | break; 358 | case 4: 359 | if (GetCharacterSelection() == 4) 360 | PadManuXOffset_General = 205; 361 | else 362 | PadManuXOffset_General = 220; 363 | break; 364 | default: 365 | PadManuXOffset_General = 205; 366 | break; 367 | } 368 | } -------------------------------------------------------------------------------- /HD_GUI/mod.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Common.h" 7 | 8 | bool SubtitlesHD = true; 9 | 10 | const HelperFunctions* helperFunctionsGlobal; 11 | 12 | NJS_TEXNAME textures_obj_regular[100]; 13 | NJS_TEXLIST texlist_obj_regular = { arrayptrandlength(textures_obj_regular) }; 14 | 15 | NJS_TEXNAME ava_title_e_hd_textures[11]; 16 | NJS_TEXLIST ava_title_e_hd_texlist = { arrayptrandlength(ava_title_e_hd_textures) }; 17 | 18 | NJS_TEXNAME ava_title_cmn_hd_textures[70]; 19 | NJS_TEXLIST ava_title_cmn_hd_texlist = { arrayptrandlength(ava_title_cmn_hd_textures) }; 20 | 21 | void Subtitles_OnFrame(); 22 | void Subtitles_Init(const char* path, const HelperFunctions& helperFunctions); 23 | 24 | void Mission_Init(const char* path, const HelperFunctions& helperFunctions); 25 | 26 | void Tutorials_Init(const char* path, const HelperFunctions& helperFunctions); 27 | void Tutorials_OnFrame(); 28 | 29 | void TitleScreen_Init(); 30 | void TitleScreen_OnReset(); 31 | 32 | void GameGear_Init(); 33 | void GenerateGameGearBackground(); 34 | 35 | #define ReplacePNG_Common(a) do { \ 36 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_common\\index.txt", path); \ 37 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 38 | } while (0) 39 | 40 | #define ReplacePNG_StageE(a) do { \ 41 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_stage_en\\index.txt", path); \ 42 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 43 | } while (0) 44 | 45 | #define ReplacePNG_StageJ(a) do { \ 46 | _snprintf_s(pathbuf, LengthOfArray(pathbuf), "%s\\textures\\pvr_stage_jp\\index.txt", path); \ 47 | helperFunctions.ReplaceFile("system\\" a ".PVR", pathbuf); \ 48 | } while (0) 49 | 50 | static float Options_ArrowScale = 0.0f; 51 | static Angle Options_ArrowAngle = 0; 52 | 53 | static int PSInt = 0; 54 | static int BSInt = 0; 55 | static float PSsX = 0; 56 | static float PSsY = 0; 57 | static float PSsZ = 0; 58 | static float BSsX = 0; 59 | static float BSsY = 0; 60 | static float BSsZ = 0; 61 | static float f480_Fixed = 0; 62 | static float f640_Fixed = 0; 63 | 64 | NJS_TEXANIM RandomRingIconPart_TEXANIM = { 32, 32, 16, 16, 0, 0, 255, 255, 95, 0x20 }; 65 | 66 | void FileIcon_Hook(int that_cant_be_right, float Texture_X, float Texture_Y, float Texture_Z) 67 | { 68 | float Arrow1_X; 69 | float Arrow1_Y; 70 | float Arrow2_X; 71 | float Arrow2_Y; 72 | float Arrow1Center_X = 251.0f; 73 | float Arrow1Center_Y = 268.0f; 74 | float Arrow2Center_X = 218.0f; 75 | float Arrow2Center_Y = 322.0f; 76 | float Arrow1Scale = 0.0f + Options_ArrowScale; 77 | float Arrow2Scale = 0.5f - Options_ArrowScale; 78 | Arrow1_X = (Arrow1Center_X - 64 * Arrow1Scale) - 320.0f + HorizontalStretch * 320.0f; 79 | Arrow1_Y = (Arrow1Center_Y - 64 * Arrow1Scale) - 240.0f + VerticalStretch * 240.0f; 80 | Arrow2_X = (Arrow2Center_X - 64 * Arrow2Scale) - 320.0f + HorizontalStretch * 320.0f; 81 | Arrow2_Y = (Arrow2Center_Y - 64 * Arrow2Scale) - 240.0f + VerticalStretch * 240.0f; 82 | njTextureShadingMode(1); 83 | DisplayScreenTexture(44, Texture_X, Texture_Y, Texture_Z); 84 | DrawBG(45, Arrow1_X, Arrow1_Y, Texture_Z, Arrow1Scale, Arrow1Scale); 85 | DrawBG(46, Arrow2_X, Arrow2_Y, Texture_Z, Arrow2Scale, Arrow2Scale); 86 | njTextureShadingMode(2); 87 | } 88 | 89 | void DrawShadow_Hook(int texnum, float x, float y, float z, float scaleX, float scaleY) 90 | { 91 | njTextureShadingMode(1); 92 | DrawBG(texnum, x, y, z, scaleX, scaleY); 93 | njTextureShadingMode(2); 94 | } 95 | 96 | void DrawTexture_Hook(int that_cant_be_right, float x, float y, float z) 97 | { 98 | njTextureShadingMode(1); 99 | DisplayScreenTexture(that_cant_be_right, x, y, z); 100 | njTextureShadingMode(2); 101 | } 102 | 103 | void DisplayScreenTexture_AlwaysTop(int that_cant_be_right, float x, float y, float z) 104 | { 105 | Direct3D_SetZFunc(7u); 106 | Direct3D_EnableZWrite(0); 107 | DisplayScreenTexture(that_cant_be_right, x, y, z); 108 | Direct3D_EnableZWrite(1); 109 | Direct3D_SetZFunc(3u); 110 | } 111 | 112 | void ScreenFadeFix(float left, float top, float right, float bottom, float depth, int color, QueuedModelFlagsB queueflags) 113 | { 114 | DrawRect_Queue(-50.0f, -50.0f, HorizontalResolution + 50.0f, VerticalResolution + 50.0f, 32048.0f, color, QueuedModelFlagsB_EnableZWrite); 115 | } 116 | 117 | void DrawShittyTextures(int texnum, float x, float y, float z, float scaleX, float scaleY) 118 | { 119 | DrawBG(texnum, x, y, z, scaleX, scaleY); 120 | DoColorGradientThingMaybe(0xFF0016FF, 0xFF002EFF, 0xFF0016FF, 0xFF002EFF); 121 | DisplayScreenTexture(BSInt, BSsX, BSsY, BSsZ); 122 | DoColorGradientThingMaybe(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); 123 | DisplayScreenTexture(PSInt, PSsX, PSsY, PSsZ); 124 | } 125 | 126 | void RetrieveBottomThingStuff(int texnum, float x, float y, float z) 127 | { 128 | BSInt = texnum; 129 | BSsX = x; 130 | BSsY = y; 131 | BSsZ = z; 132 | } 133 | 134 | void RetrievePlayerSelectStuff(int that_cant_be_right, float x, float y, float z) 135 | { 136 | PSInt = that_cant_be_right; 137 | PSsX = x; 138 | PSsY = y; 139 | PSsZ = z; 140 | } 141 | 142 | void ScaleCharselJapaneseText_LikeSeriouslyWTF(int that_cant_be_right, float x, float y, float z) 143 | { 144 | DrawBG(that_cant_be_right, x+5.0f, y, z, 0.77999997f, 0.77999997f); 145 | } 146 | 147 | void HelpAvaSquareThing(unsigned __int8 n, float x, float y, float z, float scaleX, float scaleY) 148 | { 149 | Direct3D_EnableZWrite(0); 150 | DrawBG_ava_square_a(n, x, y, z, scaleX, scaleY); 151 | Direct3D_EnableZWrite(1); 152 | } 153 | 154 | void DrawSprite_Hook(NJS_SPRITE *sp, Int n, Float pri, NJD_SPRITE attr, QueuedModelFlagsB queue_flags) 155 | { 156 | njTextureShadingMode(1); 157 | njDrawSprite2D_Queue(sp, n, pri, attr, queue_flags); 158 | njTextureShadingMode(2); 159 | } 160 | 161 | void DrawChnamBShit(Uint8 index) 162 | { 163 | Direct3D_SetZFunc(index); 164 | Direct3D_EnableZWrite(1); 165 | } 166 | 167 | extern "C" 168 | { 169 | __declspec(dllexport) ModInfo SADXModInfo = { ModLoaderVer }; 170 | 171 | __declspec(dllexport) void __cdecl Init(const char *path, const HelperFunctions &helperFunctions) 172 | { 173 | char pathbuf[MAX_PATH]; 174 | const std::string s_path(path); 175 | const std::string s_config_ini(s_path + "\\config.ini"); 176 | const IniFile* const config = new IniFile(s_config_ini); 177 | SubtitlesHD = config->getBool("General", "Subtitles", true); 178 | // Warnings 179 | if (helperFunctions.Version < 21) 180 | { 181 | MessageBox(WindowHandle, 182 | L"Please update the Mod Loader. HD GUI requires API version 21 or newer.", 183 | L"HD GUI error: Mod Loader out of date", MB_OK | MB_ICONERROR); 184 | return; 185 | } 186 | helperFunctionsGlobal = &helperFunctions; 187 | TitleScreen_Init(); 188 | GameGear_Init(); 189 | if (SubtitlesHD) 190 | Subtitles_Init(path, helperFunctions); 191 | Tutorials_Init(path, helperFunctions); 192 | Mission_Init(path, helperFunctions); 193 | // Temporary hack until the new update for DC Conversion is released 194 | if (GetModuleHandle(L"DCMods_Main") != nullptr) 195 | { 196 | helperFunctions.ReplaceFile("system\\OBJ_REGULAR.PVM", "system\\OBJ_REGULAR_DC.PVM"); 197 | OBJ_REGULAR_TEXLIST = texlist_obj_regular; 198 | } 199 | // Fix random ring icon 200 | WriteData((NJS_TEXANIM**)0x004C03FF, &RandomRingIconPart_TEXANIM); 201 | // Various fixes 202 | WriteData<1>((char*)0x913122, 0x48); // Offset sprite UV for the Adventure ring count to fix artifacts 203 | WriteData<1>((char*)0x91BB5A, 0x48); // Offset sprite UV for the Adventure ring count to fix artifacts (Big) 204 | WriteData((float*)0x0046FBF5, 52.0f); // Big Adv Field ring sprite position 205 | WriteCall((void*)0x00457F2F, DrawSprite_Hook); 206 | WriteCall((void*)0x00504DC4, HelpAvaSquareThing); 207 | WriteCall((void*)0x0050717E, ScaleCharselJapaneseText_LikeSeriouslyWTF); 208 | WriteCall((void*)0x005070E2, ScaleCharselJapaneseText_LikeSeriouslyWTF); 209 | WriteData<1>((char*)0x0091C00C, 0i8); // You win/lose text alignment 210 | WriteData<1>((char*)0x0091C00E, 0i8); // You win/lose text alignment 211 | WriteData<1>((char*)0x0091C020, 0i8); // You win/lose text alignment 212 | WriteData<1>((char*)0x0091C022, 0i8); // You win/lose text alignment 213 | WriteData<1>((char*)0x0091C034, 0i8); // You win/lose text alignment 214 | WriteData<1>((char*)0x0091C048, 0i8); // You win/lose text alignment 215 | WriteData((float*)0x006415DA, 1.5f); // EngBG X scale (DC images are smaller so they're scaled up a bit) 216 | WriteData((float*)0x006415DF, 1.5f); // EngBG Y scale 217 | // Texture replacements 218 | ReplacePVMX("ENDBG_AMY_0"); 219 | ReplacePVMX("ENDBG_AMY_1"); 220 | ReplacePVMX("ENDBG_AMY_2"); 221 | ReplacePVMX("ENDBG_BIG_0"); 222 | ReplacePVMX("ENDBG_BIG_1"); 223 | ReplacePVMX("ENDBG_BIG_2"); 224 | ReplacePVMX("ENDBG_E102_0"); 225 | ReplacePVMX("ENDBG_E102_1"); 226 | ReplacePVMX("ENDBG_E102_2"); 227 | ReplacePVMX("ENDBG_KNUCKLES_0"); 228 | ReplacePVMX("ENDBG_KNUCKLES_1"); 229 | ReplacePVMX("ENDBG_KNUCKLES_2"); 230 | ReplacePVMX("ENDBG_SONIC_0"); 231 | ReplacePVMX("ENDBG_SONIC_1"); 232 | ReplacePVMX("ENDBG_SONIC_2"); 233 | ReplacePVMX("ENDBG_SUPERSONIC_0"); 234 | ReplacePVMX("ENDBG_SUPERSONIC_1"); 235 | ReplacePVMX("ENDBG_SUPERSONIC_2"); 236 | ReplacePVMX("ENDBG_SUPERSONIC_3"); 237 | ReplacePVMX("ENDBG_TAILS_0"); 238 | ReplacePVMX("ENDBG_TAILS_1"); 239 | ReplacePVMX("ENDBG_TAILS_2"); 240 | ReplacePVMX("ADV_WINDOW"); 241 | ReplacePVMX("AVA_BACK"); 242 | ReplacePVMX("AVA_CHSEL"); 243 | ReplacePVMX("AVA_CHSEL_E"); 244 | ReplacePVMX("AVA_CSR"); 245 | ReplacePVMX("AVA_DLG"); 246 | ReplacePVMX("AVA_DLG_E"); 247 | ReplacePVMX("AVA_EMBLEMVIEW"); 248 | ReplacePVMX("AVA_EMBLEMVIEW_E"); 249 | ReplacePVMX("AVA_EMBLEM"); 250 | ReplacePVMX("AVA_FILESEL"); 251 | ReplacePVMX("AVA_FILESEL_E"); 252 | ReplacePVMX("AVA_FSDLG"); 253 | ReplacePVMX("AVA_FSDLG_E"); 254 | ReplacePVMX("AVA_METAL_SONIC"); 255 | ReplacePVMX("AVA_NEW16NO"); 256 | ReplacePVMX("AVA_OPTION"); 257 | ReplacePVMX("AVA_OPTION_E"); 258 | ReplacePVMX("AVA_SAN"); 259 | ReplacePVMX("AVA_SNDTEST"); 260 | ReplacePVMX("AVA_SNDTEST_E"); 261 | ReplacePVMX("AVA_SQUARE"); 262 | ReplacePVMX("AVA_STNAM"); 263 | ReplacePVMX("AVA_TITLE_CMN"); 264 | ReplacePVMX("AVA_STNAM_E"); 265 | ReplacePVMX("AVA_SUUJI"); 266 | if (ava_title_back_e_TEXLIST.nbTexture == 8) // Check if DC Conversion replaces TITLE_BACK and GTITLE0 267 | { 268 | //ReplacePVMX("AVA_TITLE_BACK"); - JP title screen, not used yet 269 | ReplacePVMX("AVA_TITLE_BACK_E"); 270 | ReplacePVMX("AVA_GTITLE0_E"); 271 | ReplacePVMX("AVA_GTITLE0"); 272 | } 273 | ReplacePVMX("AVA_TITLE"); 274 | ReplacePVMX("AVA_TITLE_E"); 275 | ReplacePVMX("AVA_TRIALACTSEL"); 276 | ReplacePVMX("AVA_TRIALACTSEL_E"); 277 | ReplacePVMX("BOARD_SCORE"); 278 | ReplacePVMX("B_CHNAM"); 279 | ReplacePVMX("B_CHNAM_E"); 280 | ReplacePVMX("CHAOS_LIFEGAUGE"); 281 | ReplacePVMX("CON_REGULAR"); 282 | ReplacePVMX("CON_REGULAR_E"); 283 | ReplacePVMX("E102TIME"); 284 | ReplacePVMX("EXTRA"); 285 | ReplacePVMX("ENDBG_LOGO"); 286 | ReplacePVMX("GAMEOVER"); 287 | ReplacePVMX("GAMEOVER_E"); 288 | ReplacePVMX("GG_TEXLIST_US"); 289 | ReplacePVMX("GGMENU_TEXLIST_US"); 290 | ReplacePVMX("AL_DX_TEX_XYBUTTON"); 291 | ReplacePVMX("AL_STG_KINDER_AD_TEX"); 292 | ReplacePVMX("AL_TEX_COMMON"); 293 | ReplacePVMX("AL_TEX_ODEKAKE_MENU_EN"); 294 | ReplacePVMX("MAP_EC_A"); 295 | ReplacePVMX("MAP_EC_B"); 296 | ReplacePVMX("MAP_EC_H"); 297 | ReplacePVMX("MAP_ICON"); 298 | ReplacePVMX("MAP_MR_A"); 299 | ReplacePVMX("MAP_MR_J"); 300 | ReplacePVMX("MAP_MR_S"); 301 | ReplacePVMX("MAP_PAST_E"); 302 | ReplacePVMX("MAP_PAST_S"); 303 | ReplacePVMX("MAP_SS"); 304 | ReplacePVMX("MILESRACE"); 305 | ReplacePVMX("MISSION_TUTO"); 306 | ReplacePVMX("MIS_C_EN"); 307 | ReplacePVMX("MIS_C_J"); 308 | ReplacePVMX("MIS_P"); 309 | ReplacePVMX("M_CHNAM"); 310 | ReplacePVMX("PRESSSTART"); 311 | ReplacePVMX("SCORE_ACT"); 312 | ReplacePVMX("SCORE_ACT_E"); 313 | ReplacePVMX("SCORE_BACK"); 314 | ReplacePVMX("SCORE_BOARD"); 315 | ReplacePVMX("SCORE_BOARD_E"); 316 | ReplacePVMX("SCORE_BOSS"); 317 | ReplacePVMX("SCORE_BOSS_E"); 318 | ReplacePVMX("SCORE_CART"); 319 | ReplacePVMX("SCORE_CART_E"); 320 | ReplacePVMX("SCORE_MOLE"); 321 | ReplacePVMX("SCORE_MOLE_E"); 322 | ReplacePVMX("SCORE_RESULT"); 323 | ReplacePVMX("SCORE_RESULT_E"); 324 | ReplacePVMX("SCORE_SHOOT"); 325 | ReplacePVMX("SCORE_SHOOT_E"); 326 | ReplacePVMX("SEGALOGO"); 327 | ReplacePVMX("SEGALOGO_E"); 328 | ReplacePVMX("SMRYBG_AMY"); 329 | ReplacePVMX("SMRYBG_BIG"); 330 | ReplacePVMX("SMRYBG_E102"); 331 | ReplacePVMX("SMRYBG_KNUCKLES"); 332 | ReplacePVMX("SMRYBG_SONIC"); 333 | ReplacePVMX("SMRYBG_SUPERSONIC"); 334 | ReplacePVMX("SMRYBG_TAILS"); 335 | ReplacePVMX("TX_CHNAM"); 336 | ReplacePVMX("TX_CHNAM_E"); 337 | // Common PVRs 338 | ReplacePNG_Common("ABC_TXT"); 339 | ReplacePNG_Common("HYOJI_BALLS_E"); 340 | ReplacePNG_Common("HYOJI_EMBLEM0"); 341 | ReplacePNG_Common("HYOJI_EMBLEM1"); 342 | ReplacePNG_Common("B32ASCII"); 343 | ReplacePNG_Common("B32ASCII_J"); 344 | ReplacePNG_Common("STAFFROLL_TXT"); 345 | ReplacePNG_Common("ST_064S_LOCKA"); 346 | ReplacePNG_Common("ST_064S_LOCKB"); 347 | ReplacePNG_Common("ST_064S_LOCKC"); 348 | ReplacePNG_Common("ST_064S_SCORE"); 349 | ReplacePNG_Common("ST_128S_HPGEJI"); 350 | // English stage PVRs 351 | ReplacePNG_StageE("A_STAGE01_E"); 352 | ReplacePNG_StageE("A_STAGE02_E"); 353 | ReplacePNG_StageE("A_STAGE03_E"); 354 | ReplacePNG_StageE("B_STAGE01_E"); 355 | ReplacePNG_StageE("B_STAGE02_E"); 356 | ReplacePNG_StageE("B_STAGE03_E"); 357 | ReplacePNG_StageE("B_STAGE04_E"); 358 | ReplacePNG_StageE("E_STAGE01_E"); 359 | ReplacePNG_StageE("E_STAGE02_E"); 360 | ReplacePNG_StageE("E_STAGE03_E"); 361 | ReplacePNG_StageE("E_STAGE04_E"); 362 | ReplacePNG_StageE("E_STAGE05_E"); 363 | ReplacePNG_StageE("K_STAGE01_E"); 364 | ReplacePNG_StageE("K_STAGE02_E"); 365 | ReplacePNG_StageE("K_STAGE03_E"); 366 | ReplacePNG_StageE("K_STAGE04_E"); 367 | ReplacePNG_StageE("K_STAGE05_E"); 368 | ReplacePNG_StageE("M_STAGE01_E"); 369 | ReplacePNG_StageE("M_STAGE02_E"); 370 | ReplacePNG_StageE("M_STAGE03_E"); 371 | ReplacePNG_StageE("M_STAGE04_E"); 372 | ReplacePNG_StageE("M_STAGE05_E"); 373 | ReplacePNG_StageE("ST_STAGE01_E"); 374 | ReplacePNG_StageE("ST_STAGE02_E"); 375 | ReplacePNG_StageE("ST_STAGE03_E"); 376 | ReplacePNG_StageE("ST_STAGE04_E"); 377 | ReplacePNG_StageE("ST_STAGE05_E"); 378 | ReplacePNG_StageE("S_STAGE01_E"); 379 | ReplacePNG_StageE("S_STAGE02_E"); 380 | ReplacePNG_StageE("S_STAGE03_E"); 381 | ReplacePNG_StageE("S_STAGE04_E"); 382 | ReplacePNG_StageE("S_STAGE05_E"); 383 | ReplacePNG_StageE("S_STAGE06_E"); 384 | ReplacePNG_StageE("S_STAGE07_E"); 385 | ReplacePNG_StageE("S_STAGE08_E"); 386 | ReplacePNG_StageE("S_STAGE09_E"); 387 | ReplacePNG_StageE("S_STAGE10_E"); 388 | ReplacePNG_StageE("T_EGGCARRIER_E"); 389 | ReplacePNG_StageE("T_MISTICRUIN_E"); 390 | ReplacePNG_StageE("T_STATIONSQUARE_E"); 391 | // Japanese stage PVRs 392 | ReplacePNG_StageJ("A_STAGE01"); 393 | ReplacePNG_StageJ("A_STAGE02"); 394 | ReplacePNG_StageJ("A_STAGE03"); 395 | ReplacePNG_StageJ("B_STAGE01"); 396 | ReplacePNG_StageJ("B_STAGE02"); 397 | ReplacePNG_StageJ("B_STAGE03"); 398 | ReplacePNG_StageJ("B_STAGE04"); 399 | ReplacePNG_StageJ("E_STAGE01"); 400 | ReplacePNG_StageJ("E_STAGE02"); 401 | ReplacePNG_StageJ("E_STAGE03"); 402 | ReplacePNG_StageJ("E_STAGE04"); 403 | ReplacePNG_StageJ("E_STAGE05"); 404 | ReplacePNG_StageJ("K_STAGE01"); 405 | ReplacePNG_StageJ("K_STAGE02"); 406 | ReplacePNG_StageJ("K_STAGE03"); 407 | ReplacePNG_StageJ("K_STAGE04"); 408 | ReplacePNG_StageJ("K_STAGE05"); 409 | ReplacePNG_StageJ("M_STAGE01"); 410 | ReplacePNG_StageJ("M_STAGE02"); 411 | ReplacePNG_StageJ("M_STAGE03"); 412 | ReplacePNG_StageJ("M_STAGE04"); 413 | ReplacePNG_StageJ("M_STAGE05"); 414 | ReplacePNG_StageJ("ST_STAGE01"); 415 | ReplacePNG_StageJ("ST_STAGE02"); 416 | ReplacePNG_StageJ("ST_STAGE03"); 417 | ReplacePNG_StageJ("ST_STAGE04"); 418 | ReplacePNG_StageJ("ST_STAGE05"); 419 | ReplacePNG_StageJ("S_STAGE01"); 420 | ReplacePNG_StageJ("S_STAGE02"); 421 | ReplacePNG_StageJ("S_STAGE03"); 422 | ReplacePNG_StageJ("S_STAGE04"); 423 | ReplacePNG_StageJ("S_STAGE05"); 424 | ReplacePNG_StageJ("S_STAGE06"); 425 | ReplacePNG_StageJ("S_STAGE07"); 426 | ReplacePNG_StageJ("S_STAGE08"); 427 | ReplacePNG_StageJ("S_STAGE09"); 428 | ReplacePNG_StageJ("S_STAGE10"); 429 | ReplacePNG_StageJ("T_EGGCARRIER"); 430 | ReplacePNG_StageJ("T_MISTICRUIN"); 431 | ReplacePNG_StageJ("T_STATIONSQUARE"); 432 | // Character select screen fixes 433 | WriteCall((void*)0x00511AD0, RetrievePlayerSelectStuff); // Player select text in character select screen 434 | WriteCall((void*)0x00511C76, RetrieveBottomThingStuff); // Bottom thing in character select screen 435 | WriteCall((void*)0x00511B3B, DrawShittyTextures); // Draw stuff that refuses to render properly otherwise 436 | WriteCall((void*)0x00511E47, DrawChnamBShit); // Fix disappearing character name after loading a different save 437 | WriteCall((void*)0x00511A8B, DisplayScreenTexture_AlwaysTop); // Move the "Select your character" text to top 438 | WriteData<5>((void*)0x00511C18, 0x90); // Disable ZFunc stuff to prevent character model overlap issues 439 | // Shadow blending fixes 440 | WriteCall((void*)0x0050B584, DrawShadow_Hook); 441 | WriteCall((void*)0x00431D37, DrawShadow_Hook); 442 | WriteCall((void*)0x00506EFF, DrawShadow_Hook); 443 | WriteCall((void*)0x0050D8B3, DrawShadow_Hook); 444 | WriteCall((void*)0x0050B61A, DrawShadow_Hook); // Main menu (trial) shadow 445 | WriteCall((void*)0x00508FFD, DrawTexture_Hook); // Sound test icon 446 | WriteCall((void*)0x00509130, DrawTexture_Hook); // Sonic icon background 447 | WriteCall((void*)0x00509191, DrawTexture_Hook); // Sonic icon 448 | WriteCall((void*)0x00509439, DrawTexture_Hook); // Languages icon 449 | WriteCall((void*)0x0050952F, DrawTexture_Hook); // Rumble icon 450 | WriteCall((void*)0x0050782A, DrawTexture_Hook); // AVA_SAN triangle shadow 451 | // Fixes for the question mark in the Character Select menu 452 | ((NJS_OBJECT*)0x010D7774)->basicdxmodel->mats[0].diffuse.color = 0xFFB2B2B2; 453 | ((NJS_OBJECT*)0x010D7774)->basicdxmodel->mats[0].attr_texId = 10; 454 | ava_title_e_TEXLIST = ava_title_e_hd_texlist; // Added Internet option 455 | ava_title_cmn_TEXLIST = ava_title_cmn_hd_texlist; 456 | WriteCall((void*)0x005092A1, FileIcon_Hook); // File icon 457 | } 458 | 459 | __declspec(dllexport) void __cdecl OnInitGameLoop() 460 | { 461 | if (SubtitlesHD) 462 | LoadSubtitleFont(); 463 | } 464 | 465 | __declspec(dllexport) void __cdecl OnFrame() 466 | { 467 | if (SubtitlesHD) 468 | Subtitles_OnFrame(); 469 | Tutorials_OnFrame(); 470 | 471 | if (GameMode == GameModes_Menu) 472 | { 473 | Options_ArrowScale += njSin(Options_ArrowAngle) / 54.2f; 474 | Options_ArrowAngle = (Options_ArrowAngle += 768) % 65535; 475 | } 476 | } 477 | 478 | __declspec(dllexport) void __cdecl OnRenderDeviceReset() 479 | { 480 | TitleScreen_OnReset(); 481 | GenerateGameGearBackground(); 482 | } 483 | } -------------------------------------------------------------------------------- /HD_GUI/Subtitles.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum class ListenToRecapMode 4 | { 5 | Idle = 0, 6 | Listen = 1, 7 | Done = 2 8 | }; 9 | 10 | // Structs 11 | 12 | struct SubtitleCodepage 13 | { 14 | int StartChar; 15 | int TexID; 16 | }; 17 | 18 | struct SubtitleThing 19 | { 20 | char kind; 21 | __int16 x; 22 | __int16 y; 23 | unsigned __int16 width; 24 | unsigned __int16 height; 25 | unsigned __int16 buf_width; 26 | unsigned __int16 buf_height; 27 | unsigned __int16 buf_width2; 28 | unsigned __int16 buf_height2; 29 | __int16 lx; 30 | __int16 ly; 31 | __int16 sx; 32 | __int16 sy; 33 | unsigned __int16 color; 34 | NJS_COLOR fc; 35 | NJS_COLOR bc; 36 | float scale; 37 | void* bitmap; 38 | unsigned int globalindex; 39 | NJS_TEXLIST texlist; 40 | NJS_TEXNAME texname; 41 | int msgc_flag; 42 | }; 43 | 44 | struct FontOffset 45 | { 46 | char width; // Character width 47 | char offset_x; // Horizontal offset 48 | char offset_y; // Vertical offset 49 | }; 50 | 51 | struct TextLine 52 | { 53 | int LineLength; 54 | //char LineString[256]; 55 | unsigned __int16 LineString_S[256]; 56 | }; 57 | 58 | // Pointers 59 | FunctionPointer(void, DoTextThing_Start, (SubtitleThing *a1), 0x40D850); 60 | FunctionPointer(void, DoTextThing_Stop, (SubtitleThing *a1), 0x40D2A0); 61 | DataPointer(int, RecapScreenMode, 0x3C8308C); 62 | 63 | // Arrays 64 | static NJS_TEXANIM SubtitleFont[] = { 65 | { 64, 64, 0, 0, 0, 0, 15, 15, 0, 0 }, 66 | { 64, 64, 0, 0, 15, 0, 31, 15, 0, 0 }, 67 | { 64, 64, 0, 0, 31, 0, 47, 15, 0, 0 }, 68 | { 64, 64, 0, 0, 47, 0, 63, 15, 0, 0 }, 69 | { 64, 64, 0, 0, 63, 0, 79, 15, 0, 0 }, 70 | { 64, 64, 0, 0, 79, 0, 95, 15, 0, 0 }, 71 | { 64, 64, 0, 0, 95, 0, 111, 15, 0, 0 }, 72 | { 64, 64, 0, 0, 111, 0, 127, 15, 0, 0 }, 73 | { 64, 64, 0, 0, 127, 0, 143, 15, 0, 0 }, 74 | { 64, 64, 0, 0, 143, 0, 159, 15, 0, 0 }, 75 | { 64, 64, 0, 0, 159, 0, 175, 15, 0, 0 }, 76 | { 64, 64, 0, 0, 175, 0, 191, 15, 0, 0 }, 77 | { 64, 64, 0, 0, 191, 0, 207, 15, 0, 0 }, 78 | { 64, 64, 0, 0, 207, 0, 223, 15, 0, 0 }, 79 | { 64, 64, 0, 0, 223, 0, 239, 15, 0, 0 }, 80 | { 64, 64, 0, 0, 239, 0, 255, 15, 0, 0 }, 81 | { 64, 64, 0, 0, 0, 15, 15, 31, 0, 0 }, 82 | { 64, 64, 0, 0, 15, 15, 31, 31, 0, 0 }, 83 | { 64, 64, 0, 0, 31, 15, 47, 31, 0, 0 }, 84 | { 64, 64, 0, 0, 47, 15, 63, 31, 0, 0 }, 85 | { 64, 64, 0, 0, 63, 15, 79, 31, 0, 0 }, 86 | { 64, 64, 0, 0, 79, 15, 95, 31, 0, 0 }, 87 | { 64, 64, 0, 0, 95, 15, 111, 31, 0, 0 }, 88 | { 64, 64, 0, 0, 111, 15, 127, 31, 0, 0 }, 89 | { 64, 64, 0, 0, 127, 15, 143, 31, 0, 0 }, 90 | { 64, 64, 0, 0, 143, 15, 159, 31, 0, 0 }, 91 | { 64, 64, 0, 0, 159, 15, 175, 31, 0, 0 }, 92 | { 64, 64, 0, 0, 175, 15, 191, 31, 0, 0 }, 93 | { 64, 64, 0, 0, 191, 15, 207, 31, 0, 0 }, 94 | { 64, 64, 0, 0, 207, 15, 223, 31, 0, 0 }, 95 | { 64, 64, 0, 0, 223, 15, 239, 31, 0, 0 }, 96 | { 64, 64, 0, 0, 239, 15, 255, 31, 0, 0 }, 97 | { 64, 64, 0, 0, 0, 31, 15, 47, 0, 0 }, 98 | { 64, 64, 0, 0, 15, 31, 31, 47, 0, 0 }, 99 | { 64, 64, 0, 0, 31, 31, 47, 47, 0, 0 }, 100 | { 64, 64, 0, 0, 47, 31, 63, 47, 0, 0 }, 101 | { 64, 64, 0, 0, 63, 31, 79, 47, 0, 0 }, 102 | { 64, 64, 0, 0, 79, 31, 95, 47, 0, 0 }, 103 | { 64, 64, 0, 0, 95, 31, 111, 47, 0, 0 }, 104 | { 64, 64, 0, 0, 111, 31, 127, 47, 0, 0 }, 105 | { 64, 64, 0, 0, 127, 31, 143, 47, 0, 0 }, 106 | { 64, 64, 0, 0, 143, 31, 159, 47, 0, 0 }, 107 | { 64, 64, 0, 0, 159, 31, 175, 47, 0, 0 }, 108 | { 64, 64, 0, 0, 175, 31, 191, 47, 0, 0 }, 109 | { 64, 64, 0, 0, 191, 31, 207, 47, 0, 0 }, 110 | { 64, 64, 0, 0, 207, 31, 223, 47, 0, 0 }, 111 | { 64, 64, 0, 0, 223, 31, 239, 47, 0, 0 }, 112 | { 64, 64, 0, 0, 239, 31, 255, 47, 0, 0 }, 113 | { 64, 64, 0, 0, 0, 47, 15, 63, 0, 0 }, 114 | { 64, 64, 0, 0, 15, 47, 31, 63, 0, 0 }, 115 | { 64, 64, 0, 0, 31, 47, 47, 63, 0, 0 }, 116 | { 64, 64, 0, 0, 47, 47, 63, 63, 0, 0 }, 117 | { 64, 64, 0, 0, 63, 47, 79, 63, 0, 0 }, 118 | { 64, 64, 0, 0, 79, 47, 95, 63, 0, 0 }, 119 | { 64, 64, 0, 0, 95, 47, 111, 63, 0, 0 }, 120 | { 64, 64, 0, 0, 111, 47, 127, 63, 0, 0 }, 121 | { 64, 64, 0, 0, 127, 47, 143, 63, 0, 0 }, 122 | { 64, 64, 0, 0, 143, 47, 159, 63, 0, 0 }, 123 | { 64, 64, 0, 0, 159, 47, 175, 63, 0, 0 }, 124 | { 64, 64, 0, 0, 175, 47, 191, 63, 0, 0 }, 125 | { 64, 64, 0, 0, 191, 47, 207, 63, 0, 0 }, 126 | { 64, 64, 0, 0, 207, 47, 223, 63, 0, 0 }, 127 | { 64, 64, 0, 0, 223, 47, 239, 63, 0, 0 }, 128 | { 64, 64, 0, 0, 239, 47, 255, 63, 0, 0 }, 129 | { 64, 64, 0, 0, 0, 63, 15, 79, 0, 0 }, 130 | { 64, 64, 0, 0, 15, 63, 31, 79, 0, 0 }, 131 | { 64, 64, 0, 0, 31, 63, 47, 79, 0, 0 }, 132 | { 64, 64, 0, 0, 47, 63, 63, 79, 0, 0 }, 133 | { 64, 64, 0, 0, 63, 63, 79, 79, 0, 0 }, 134 | { 64, 64, 0, 0, 79, 63, 95, 79, 0, 0 }, 135 | { 64, 64, 0, 0, 95, 63, 111, 79, 0, 0 }, 136 | { 64, 64, 0, 0, 111, 63, 127, 79, 0, 0 }, 137 | { 64, 64, 0, 0, 127, 63, 143, 79, 0, 0 }, 138 | { 64, 64, 0, 0, 143, 63, 159, 79, 0, 0 }, 139 | { 64, 64, 0, 0, 159, 63, 175, 79, 0, 0 }, 140 | { 64, 64, 0, 0, 175, 63, 191, 79, 0, 0 }, 141 | { 64, 64, 0, 0, 191, 63, 207, 79, 0, 0 }, 142 | { 64, 64, 0, 0, 207, 63, 223, 79, 0, 0 }, 143 | { 64, 64, 0, 0, 223, 63, 239, 79, 0, 0 }, 144 | { 64, 64, 0, 0, 239, 63, 255, 79, 0, 0 }, 145 | { 64, 64, 0, 0, 0, 79, 15, 95, 0, 0 }, 146 | { 64, 64, 0, 0, 15, 79, 31, 95, 0, 0 }, 147 | { 64, 64, 0, 0, 31, 79, 47, 95, 0, 0 }, 148 | { 64, 64, 0, 0, 47, 79, 63, 95, 0, 0 }, 149 | { 64, 64, 0, 0, 63, 79, 79, 95, 0, 0 }, 150 | { 64, 64, 0, 0, 79, 79, 95, 95, 0, 0 }, 151 | { 64, 64, 0, 0, 95, 79, 111, 95, 0, 0 }, 152 | { 64, 64, 0, 0, 111, 79, 127, 95, 0, 0 }, 153 | { 64, 64, 0, 0, 127, 79, 143, 95, 0, 0 }, 154 | { 64, 64, 0, 0, 143, 79, 159, 95, 0, 0 }, 155 | { 64, 64, 0, 0, 159, 79, 175, 95, 0, 0 }, 156 | { 64, 64, 0, 0, 175, 79, 191, 95, 0, 0 }, 157 | { 64, 64, 0, 0, 191, 79, 207, 95, 0, 0 }, 158 | { 64, 64, 0, 0, 207, 79, 223, 95, 0, 0 }, 159 | { 64, 64, 0, 0, 223, 79, 239, 95, 0, 0 }, 160 | { 64, 64, 0, 0, 239, 79, 255, 95, 0, 0 }, 161 | { 64, 64, 0, 0, 0, 95, 15, 111, 0, 0 }, 162 | { 64, 64, 0, 0, 15, 95, 31, 111, 0, 0 }, 163 | { 64, 64, 0, 0, 31, 95, 47, 111, 0, 0 }, 164 | { 64, 64, 0, 0, 47, 95, 63, 111, 0, 0 }, 165 | { 64, 64, 0, 0, 63, 95, 79, 111, 0, 0 }, 166 | { 64, 64, 0, 0, 79, 95, 95, 111, 0, 0 }, 167 | { 64, 64, 0, 0, 95, 95, 111, 111, 0, 0 }, 168 | { 64, 64, 0, 0, 111, 95, 127, 111, 0, 0 }, 169 | { 64, 64, 0, 0, 127, 95, 143, 111, 0, 0 }, 170 | { 64, 64, 0, 0, 143, 95, 159, 111, 0, 0 }, 171 | { 64, 64, 0, 0, 159, 95, 175, 111, 0, 0 }, 172 | { 64, 64, 0, 0, 175, 95, 191, 111, 0, 0 }, 173 | { 64, 64, 0, 0, 191, 95, 207, 111, 0, 0 }, 174 | { 64, 64, 0, 0, 207, 95, 223, 111, 0, 0 }, 175 | { 64, 64, 0, 0, 223, 95, 239, 111, 0, 0 }, 176 | { 64, 64, 0, 0, 239, 95, 255, 111, 0, 0 }, 177 | { 64, 64, 0, 0, 0, 111, 15, 127, 0, 0 }, 178 | { 64, 64, 0, 0, 15, 111, 31, 127, 0, 0 }, 179 | { 64, 64, 0, 0, 31, 111, 47, 127, 0, 0 }, 180 | { 64, 64, 0, 0, 47, 111, 63, 127, 0, 0 }, 181 | { 64, 64, 0, 0, 63, 111, 79, 127, 0, 0 }, 182 | { 64, 64, 0, 0, 79, 111, 95, 127, 0, 0 }, 183 | { 64, 64, 0, 0, 95, 111, 111, 127, 0, 0 }, 184 | { 64, 64, 0, 0, 111, 111, 127, 127, 0, 0 }, 185 | { 64, 64, 0, 0, 127, 111, 143, 127, 0, 0 }, 186 | { 64, 64, 0, 0, 143, 111, 159, 127, 0, 0 }, 187 | { 64, 64, 0, 0, 159, 111, 175, 127, 0, 0 }, 188 | { 64, 64, 0, 0, 175, 111, 191, 127, 0, 0 }, 189 | { 64, 64, 0, 0, 191, 111, 207, 127, 0, 0 }, 190 | { 64, 64, 0, 0, 207, 111, 223, 127, 0, 0 }, 191 | { 64, 64, 0, 0, 223, 111, 239, 127, 0, 0 }, 192 | { 64, 64, 0, 0, 239, 111, 255, 127, 0, 0 }, 193 | { 64, 64, 0, 0, 0, 127, 15, 143, 0, 0 }, 194 | { 64, 64, 0, 0, 15, 127, 31, 143, 0, 0 }, 195 | { 64, 64, 0, 0, 31, 127, 47, 143, 0, 0 }, 196 | { 64, 64, 0, 0, 47, 127, 63, 143, 0, 0 }, 197 | { 64, 64, 0, 0, 63, 127, 79, 143, 0, 0 }, 198 | { 64, 64, 0, 0, 79, 127, 95, 143, 0, 0 }, 199 | { 64, 64, 0, 0, 95, 127, 111, 143, 0, 0 }, 200 | { 64, 64, 0, 0, 111, 127, 127, 143, 0, 0 }, 201 | { 64, 64, 0, 0, 127, 127, 143, 143, 0, 0 }, 202 | { 64, 64, 0, 0, 143, 127, 159, 143, 0, 0 }, 203 | { 64, 64, 0, 0, 159, 127, 175, 143, 0, 0 }, 204 | { 64, 64, 0, 0, 175, 127, 191, 143, 0, 0 }, 205 | { 64, 64, 0, 0, 191, 127, 207, 143, 0, 0 }, 206 | { 64, 64, 0, 0, 207, 127, 223, 143, 0, 0 }, 207 | { 64, 64, 0, 0, 223, 127, 239, 143, 0, 0 }, 208 | { 64, 64, 0, 0, 239, 127, 255, 143, 0, 0 }, 209 | { 64, 64, 0, 0, 0, 143, 15, 159, 0, 0 }, 210 | { 64, 64, 0, 0, 15, 143, 31, 159, 0, 0 }, 211 | { 64, 64, 0, 0, 31, 143, 47, 159, 0, 0 }, 212 | { 64, 64, 0, 0, 47, 143, 63, 159, 0, 0 }, 213 | { 64, 64, 0, 0, 63, 143, 79, 159, 0, 0 }, 214 | { 64, 64, 0, 0, 79, 143, 95, 159, 0, 0 }, 215 | { 64, 64, 0, 0, 95, 143, 111, 159, 0, 0 }, 216 | { 64, 64, 0, 0, 111, 143, 127, 159, 0, 0 }, 217 | { 64, 64, 0, 0, 127, 143, 143, 159, 0, 0 }, 218 | { 64, 64, 0, 0, 143, 143, 159, 159, 0, 0 }, 219 | { 64, 64, 0, 0, 159, 143, 175, 159, 0, 0 }, 220 | { 64, 64, 0, 0, 175, 143, 191, 159, 0, 0 }, 221 | { 64, 64, 0, 0, 191, 143, 207, 159, 0, 0 }, 222 | { 64, 64, 0, 0, 207, 143, 223, 159, 0, 0 }, 223 | { 64, 64, 0, 0, 223, 143, 239, 159, 0, 0 }, 224 | { 64, 64, 0, 0, 239, 143, 255, 159, 0, 0 }, 225 | { 64, 64, 0, 0, 0, 159, 15, 175, 0, 0 }, 226 | { 64, 64, 0, 0, 15, 159, 31, 175, 0, 0 }, 227 | { 64, 64, 0, 0, 31, 159, 47, 175, 0, 0 }, 228 | { 64, 64, 0, 0, 47, 159, 63, 175, 0, 0 }, 229 | { 64, 64, 0, 0, 63, 159, 79, 175, 0, 0 }, 230 | { 64, 64, 0, 0, 79, 159, 95, 175, 0, 0 }, 231 | { 64, 64, 0, 0, 95, 159, 111, 175, 0, 0 }, 232 | { 64, 64, 0, 0, 111, 159, 127, 175, 0, 0 }, 233 | { 64, 64, 0, 0, 127, 159, 143, 175, 0, 0 }, 234 | { 64, 64, 0, 0, 143, 159, 159, 175, 0, 0 }, 235 | { 64, 64, 0, 0, 159, 159, 175, 175, 0, 0 }, 236 | { 64, 64, 0, 0, 175, 159, 191, 175, 0, 0 }, 237 | { 64, 64, 0, 0, 191, 159, 207, 175, 0, 0 }, 238 | { 64, 64, 0, 0, 207, 159, 223, 175, 0, 0 }, 239 | { 64, 64, 0, 0, 223, 159, 239, 175, 0, 0 }, 240 | { 64, 64, 0, 0, 239, 159, 255, 175, 0, 0 }, 241 | { 64, 64, 0, 0, 0, 175, 15, 191, 0, 0 }, 242 | { 64, 64, 0, 0, 15, 175, 31, 191, 0, 0 }, 243 | { 64, 64, 0, 0, 31, 175, 47, 191, 0, 0 }, 244 | { 64, 64, 0, 0, 47, 175, 63, 191, 0, 0 }, 245 | { 64, 64, 0, 0, 63, 175, 79, 191, 0, 0 }, 246 | { 64, 64, 0, 0, 79, 175, 95, 191, 0, 0 }, 247 | { 64, 64, 0, 0, 95, 175, 111, 191, 0, 0 }, 248 | { 64, 64, 0, 0, 111, 175, 127, 191, 0, 0 }, 249 | { 64, 64, 0, 0, 127, 175, 143, 191, 0, 0 }, 250 | { 64, 64, 0, 0, 143, 175, 159, 191, 0, 0 }, 251 | { 64, 64, 0, 0, 159, 175, 175, 191, 0, 0 }, 252 | { 64, 64, 0, 0, 175, 175, 191, 191, 0, 0 }, 253 | { 64, 64, 0, 0, 191, 175, 207, 191, 0, 0 }, 254 | { 64, 64, 0, 0, 207, 175, 223, 191, 0, 0 }, 255 | { 64, 64, 0, 0, 223, 175, 239, 191, 0, 0 }, 256 | { 64, 64, 0, 0, 239, 175, 255, 191, 0, 0 }, 257 | { 64, 64, 0, 0, 0, 191, 15, 207, 0, 0 }, 258 | { 64, 64, 0, 0, 15, 191, 31, 207, 0, 0 }, 259 | { 64, 64, 0, 0, 31, 191, 47, 207, 0, 0 }, 260 | { 64, 64, 0, 0, 47, 191, 63, 207, 0, 0 }, 261 | { 64, 64, 0, 0, 63, 191, 79, 207, 0, 0 }, 262 | { 64, 64, 0, 0, 79, 191, 95, 207, 0, 0 }, 263 | { 64, 64, 0, 0, 95, 191, 111, 207, 0, 0 }, 264 | { 64, 64, 0, 0, 111, 191, 127, 207, 0, 0 }, 265 | { 64, 64, 0, 0, 127, 191, 143, 207, 0, 0 }, 266 | { 64, 64, 0, 0, 143, 191, 159, 207, 0, 0 }, 267 | { 64, 64, 0, 0, 159, 191, 175, 207, 0, 0 }, 268 | { 64, 64, 0, 0, 175, 191, 191, 207, 0, 0 }, 269 | { 64, 64, 0, 0, 191, 191, 207, 207, 0, 0 }, 270 | { 64, 64, 0, 0, 207, 191, 223, 207, 0, 0 }, 271 | { 64, 64, 0, 0, 223, 191, 239, 207, 0, 0 }, 272 | { 64, 64, 0, 0, 239, 191, 255, 207, 0, 0 }, 273 | { 64, 64, 0, 0, 0, 207, 15, 223, 0, 0 }, 274 | { 64, 64, 0, 0, 15, 207, 31, 223, 0, 0 }, 275 | { 64, 64, 0, 0, 31, 207, 47, 223, 0, 0 }, 276 | { 64, 64, 0, 0, 47, 207, 63, 223, 0, 0 }, 277 | { 64, 64, 0, 0, 63, 207, 79, 223, 0, 0 }, 278 | { 64, 64, 0, 0, 79, 207, 95, 223, 0, 0 }, 279 | { 64, 64, 0, 0, 95, 207, 111, 223, 0, 0 }, 280 | { 64, 64, 0, 0, 111, 207, 127, 223, 0, 0 }, 281 | { 64, 64, 0, 0, 127, 207, 143, 223, 0, 0 }, 282 | { 64, 64, 0, 0, 143, 207, 159, 223, 0, 0 }, 283 | { 64, 64, 0, 0, 159, 207, 175, 223, 0, 0 }, 284 | { 64, 64, 0, 0, 175, 207, 191, 223, 0, 0 }, 285 | { 64, 64, 0, 0, 191, 207, 207, 223, 0, 0 }, 286 | { 64, 64, 0, 0, 207, 207, 223, 223, 0, 0 }, 287 | { 64, 64, 0, 0, 223, 207, 239, 223, 0, 0 }, 288 | { 64, 64, 0, 0, 239, 207, 255, 223, 0, 0 }, 289 | { 64, 64, 0, 0, 0, 223, 15, 239, 0, 0 }, 290 | { 64, 64, 0, 0, 15, 223, 31, 239, 0, 0 }, 291 | { 64, 64, 0, 0, 31, 223, 47, 239, 0, 0 }, 292 | { 64, 64, 0, 0, 47, 223, 63, 239, 0, 0 }, 293 | { 64, 64, 0, 0, 63, 223, 79, 239, 0, 0 }, 294 | { 64, 64, 0, 0, 79, 223, 95, 239, 0, 0 }, 295 | { 64, 64, 0, 0, 95, 223, 111, 239, 0, 0 }, 296 | { 64, 64, 0, 0, 111, 223, 127, 239, 0, 0 }, 297 | { 64, 64, 0, 0, 127, 223, 143, 239, 0, 0 }, 298 | { 64, 64, 0, 0, 143, 223, 159, 239, 0, 0 }, 299 | { 64, 64, 0, 0, 159, 223, 175, 239, 0, 0 }, 300 | { 64, 64, 0, 0, 175, 223, 191, 239, 0, 0 }, 301 | { 64, 64, 0, 0, 191, 223, 207, 239, 0, 0 }, 302 | { 64, 64, 0, 0, 207, 223, 223, 239, 0, 0 }, 303 | { 64, 64, 0, 0, 223, 223, 239, 239, 0, 0 }, 304 | { 64, 64, 0, 0, 239, 223, 255, 239, 0, 0 }, 305 | { 64, 64, 0, 0, 0, 239, 15, 255, 0, 0 }, 306 | { 64, 64, 0, 0, 15, 239, 31, 255, 0, 0 }, 307 | { 64, 64, 0, 0, 31, 239, 47, 255, 0, 0 }, 308 | { 64, 64, 0, 0, 47, 239, 63, 255, 0, 0 }, 309 | { 64, 64, 0, 0, 63, 239, 79, 255, 0, 0 }, 310 | { 64, 64, 0, 0, 79, 239, 95, 255, 0, 0 }, 311 | { 64, 64, 0, 0, 95, 239, 111, 255, 0, 0 }, 312 | { 64, 64, 0, 0, 111, 239, 127, 255, 0, 0 }, 313 | { 64, 64, 0, 0, 127, 239, 143, 255, 0, 0 }, 314 | { 64, 64, 0, 0, 143, 239, 159, 255, 0, 0 }, 315 | { 64, 64, 0, 0, 159, 239, 175, 255, 0, 0 }, 316 | { 64, 64, 0, 0, 175, 239, 191, 255, 0, 0 }, 317 | { 64, 64, 0, 0, 191, 239, 207, 255, 0, 0 }, 318 | { 64, 64, 0, 0, 207, 239, 223, 255, 0, 0 }, 319 | { 64, 64, 0, 0, 223, 239, 239, 255, 0, 0 }, 320 | { 64, 64, 0, 0, 239, 239, 255, 255, 0, 0 }, 321 | }; 322 | 323 | static FontOffset FontCharacterData[] = 324 | { 325 | {0, 0, 0}, 326 | {0, 0, 0}, 327 | {40, 0, 0}, //Japanese ... 328 | {0, 0, 0}, 329 | {0, 0, 0}, 330 | {0, 0, 0}, 331 | {0, 0, 0}, 332 | {0, 0, 0}, 333 | {0, 0, 0}, 334 | {0, 0, 0}, 335 | {0, 0, 0}, 336 | {0, 0, 0}, 337 | {0, 0, 0}, 338 | {0, 0, 0}, 339 | {0, 0, 0}, 340 | {0, 0, 0}, 341 | {0, 0, 0}, 342 | {0, 0, 0}, 343 | {0, 0, 0}, 344 | {0, 0, 0}, 345 | {0, 0, 0}, 346 | {0, 0, 0}, 347 | {0, 0, 0}, 348 | {0, 0, 0}, 349 | {0, 0, 0}, 350 | {0, 0, 0}, 351 | {0, 0, 0}, 352 | {0, 0, 0}, 353 | {0, 0, 0}, 354 | {0, 0, 0}, 355 | {0, 0, 0}, 356 | {10, 0, 0}, // separator 357 | {32, 0, 0}, // space 358 | {18, 0, 0}, // ! 359 | {23, 0, 0}, // " 360 | {42, 0, 0}, // # 361 | {21, 0, 0}, // $ 362 | {49, 0, 0}, // % 363 | {46, 0, 0}, // & 364 | {10, 0, 0}, // ' 365 | {18, 0, 0}, // ( 366 | {18, 0, 0}, // ) 367 | {22, 0, 0}, // * 368 | {36, 0, 0}, // + 369 | {10, 0, 0}, // , 370 | {18, 0, 0}, // - 371 | {8, 0, 0}, // . 372 | {26, 0, 0}, // / 373 | {34, 0, 0}, // 0 374 | {15, 0, 0}, // 1 375 | {36, 0, 0}, // 2 376 | {37, 0, 0}, // 3 377 | {36, 0, 0}, // 4 378 | {34, 0, 0}, // 5 379 | {34, 0, 0}, // 6 380 | {29, 0, 0}, // 7 381 | {36, 0, 0}, // 8 382 | {35, 0, 0}, // 9 383 | {12, 0, 0}, // : 384 | {12, 0, 0}, // ; 385 | {36, 0, 0}, // < 386 | {36, 0, 0}, // = 387 | {36, 0, 0}, // > 388 | {34, 0, 0}, // ? 389 | {55, 0, 0}, // @ 390 | {36, 0, 0}, // A 391 | {33, 0, 0}, // B 392 | {36, 0, 0}, // C 393 | {32, 0, 0}, // D 394 | {27, 0, 0}, // E 395 | {29, 0, 0}, // F 396 | {34, 0, 0}, // G 397 | {32, 0, 0}, // H 398 | {12, 0, 0}, // I 399 | {22, 0, 0}, // J 400 | {36, 0, 0}, // K 401 | {23, 0, 0}, // L 402 | {42, 0, 0}, // M 403 | {31, 0, 0}, // N 404 | {37, 0, 0}, // O 405 | {32, 0, 0}, // P 406 | {36, 0, 0}, // Q 407 | {38, 0, 0}, // R 408 | {34, 0, 0}, // S 409 | {26, 0, 0}, // T 410 | {33, 0, 0}, // U 411 | {35, 0, 0}, // V 412 | {54, 0, 0}, // W 413 | {40, 0, 0}, // X 414 | {38, 0, 0}, // Y 415 | {34, 0, 0}, // Z 416 | {18, 0, 0}, // [ 417 | {27, 0, 0}, // yen 418 | {18, 0, 0}, // ] 419 | {36, 0, 0}, // ^ 420 | {30, 0, 0}, // _ 421 | {15, 0, 0}, // ` 422 | {28, -2, 0}, // a 423 | {30, 0, 0}, // b 424 | {28, 0, 0}, // c 425 | {28, 0, 0}, // d 426 | {26, -2, 0}, //e 427 | {25, 0, 0}, // f 428 | {28, 0, 0}, // g 429 | {30, 0, 0}, // h 430 | {11, 0, 0}, // i 431 | {19, 0, 0}, // j 432 | {29, 0, 0}, // k 433 | {8, 4, 0}, // l 434 | {42, 0, 0}, // m 435 | {26, 0, 0}, // n 436 | {28, 0, 0}, // o 437 | {27, 0, 0}, // p 438 | {27, 0, 0}, // q 439 | {16, -2, 0}, // r 440 | {28, 0, 0}, // s 441 | {19, 0, 0}, // t 442 | {28, 0, 0}, // u 443 | {32, 4, 0}, // v 444 | {41, 0, 0}, // w 445 | {30, 0, 0}, // x 446 | {31, 0, 0}, // y 447 | {25, 0, 0}, // z 448 | {22, 0, 0}, // { 449 | {6, 0, 0}, // | 450 | {22, 0, 0}, // } 451 | {40, 0, 0}, // ~ 452 | {11, 0, 0}, // dot in the middle 453 | // European letters from here 454 | {32, 0, 0}, 455 | {32, 0, 0}, 456 | {32, 0, 0}, 457 | {32, 0, 0}, 458 | {32, 0, 0}, 459 | {32, 0, 0}, 460 | {32, 0, 0}, 461 | {32, 0, 0}, 462 | {32, 0, 0}, 463 | {32, 0, 0}, 464 | {32, 0, 0}, 465 | {32, 0, 0}, 466 | {32, 0, 0}, 467 | {32, 0, 0}, 468 | {32, 0, 0}, 469 | {32, 0, 0}, 470 | {32, 0, 0}, 471 | {32, 0, 0}, 472 | {32, 0, 0}, 473 | {32, 0, 0}, 474 | {32, 0, 0}, 475 | {32, 0, 0}, 476 | {32, 0, 0}, 477 | {32, 0, 0}, 478 | {32, 0, 0}, 479 | {32, 0, 0}, 480 | {32, 0, 0}, 481 | {32, 0, 0}, 482 | {32, 0, 0}, 483 | {32, 0, 0}, 484 | {32, 0, 0}, 485 | {32, 0, 0}, 486 | {32, 0, 0}, 487 | {32, 0, 0}, 488 | {32, 0, 0}, 489 | {32, 0, 0}, 490 | {32, 0, 0}, 491 | {32, 0, 0}, 492 | {32, 0, 0}, 493 | {32, 0, 0}, 494 | {32, 0, 0}, 495 | {32, 0, 0}, 496 | {32, 0, 0}, 497 | {32, 0, 0}, 498 | {32, 0, 0}, 499 | {32, 0, 0}, 500 | {32, 0, 0}, 501 | {32, 0, 0}, 502 | {32, 0, 0}, 503 | {32, 0, 0}, 504 | {32, 0, 0}, 505 | {32, 0, 0}, 506 | {32, 0, 0}, 507 | {32, 0, 0}, 508 | {32, 0, 0}, 509 | {32, 0, 0}, 510 | {32, 0, 0}, 511 | {32, 0, 0}, 512 | {32, 0, 0}, 513 | {32, 0, 0}, 514 | {32, 0, 0}, 515 | {32, 0, 0}, 516 | {32, 0, 0}, 517 | {32, 0, 0}, 518 | {32, 0, 0}, 519 | {32, 0, 0}, 520 | {32, 0, 0}, 521 | {32, 0, 0}, 522 | {32, 0, 0}, 523 | {32, 0, 0}, 524 | {32, 0, 0}, 525 | {32, 0, 0}, 526 | {32, 0, 0}, 527 | {32, 0, 0}, 528 | {32, 0, 0}, 529 | {32, 0, 0}, 530 | {32, 0, 0}, 531 | {32, 0, 0}, 532 | {32, 0, 0}, 533 | {32, 0, 0}, 534 | {32, 0, 0}, 535 | {32, 0, 0}, 536 | {32, 0, 0}, 537 | {32, 0, 0}, 538 | {32, 0, 0}, 539 | {32, 0, 0}, 540 | {32, 0, 0}, 541 | {32, 0, 0}, 542 | {32, 0, 0}, 543 | {32, 0, 0}, 544 | {32, 0, 0}, 545 | {32, 0, 0}, 546 | {32, 0, 0}, 547 | {32, 0, 0}, 548 | {32, 0, 0}, 549 | {32, 0, 0}, 550 | {32, 0, 0}, 551 | {32, 0, 0}, 552 | {32, 0, 0}, 553 | {32, 0, 0}, 554 | {32, 0, 0}, 555 | {32, 0, 0}, 556 | {32, 0, 0}, 557 | {32, 0, 0}, 558 | {32, 0, 0}, 559 | {32, 0, 0}, 560 | {32, 0, 0}, 561 | {32, 0, 0}, 562 | {32, 0, 0}, 563 | {32, 0, 0}, 564 | {32, 0, 0}, 565 | {32, 0, 0}, 566 | {32, 0, 0}, 567 | {32, 0, 0}, 568 | {32, 0, 0}, 569 | {32, 0, 0}, 570 | {32, 0, 0}, 571 | {32, 0, 0}, 572 | {32, 0, 0}, 573 | {32, 0, 0}, 574 | {32, 0, 0}, 575 | {32, 0, 0}, 576 | {32, 0, 0}, 577 | {32, 0, 0}, 578 | {32, 0, 0}, 579 | {32, 0, 0}, 580 | {32, 0, 0}, 581 | {32, 0, 0} 582 | }; 583 | 584 | // Misc 585 | NJS_TEXNAME SubtitleTexname[1]; 586 | NJS_TEXLIST SubtitleTexlist = { arrayptrandlength(SubtitleTexname) }; 587 | 588 | NJS_TEXNAME SubtitleJPTexname[44]; 589 | NJS_TEXLIST SubtitleJPTexlist = {arrayptrandlength(SubtitleJPTexname)}; 590 | 591 | unsigned __int16 SubtitleArray[256]; 592 | TextLine RecapArray[256]; 593 | TextLine MissionArray[256]; 594 | 595 | SubtitleCodepage JapaneseSubtitleCodepage[] = { 596 | { 0x8140, 0 }, 597 | { 0x8240, 1 }, 598 | { 0x8340, 2 }, 599 | { 0x8440, 3 }, 600 | { 0x8740, 4 }, 601 | { 0x8840, 5 }, 602 | { 0x8940, 6 }, 603 | { 0x8A40, 7 }, 604 | { 0x8B40, 8 }, 605 | { 0x8C40, 9 }, 606 | { 0x8D40, 10 }, 607 | { 0x8E40, 11 }, 608 | { 0x8F40, 12 }, 609 | { 0x9040, 13 }, 610 | { 0x9140, 14 }, 611 | { 0x9240, 15 }, 612 | { 0x9340, 16 }, 613 | { 0x9440, 17 }, 614 | { 0x9540, 18 }, 615 | { 0x9640, 19 }, 616 | { 0x9740, 20 }, 617 | { 0x9840, 21 }, 618 | { 0x9940, 22 }, 619 | { 0x9A40, 23 }, 620 | { 0x9B40, 24 }, 621 | { 0x9C40, 25 }, 622 | { 0x9D40, 26 }, 623 | { 0x9E40, 27 }, 624 | { 0x9F40, 28 }, 625 | { 0xE040, 29 }, 626 | { 0xE140, 30 }, 627 | { 0xE240, 31 }, 628 | { 0xE340, 32 }, 629 | { 0xE440, 33 }, 630 | { 0xE540, 34 }, 631 | { 0xE640, 35 }, 632 | { 0xE740, 36 }, 633 | { 0xE840, 37 }, 634 | { 0xE940, 38 }, 635 | { 0xEA40, 39 }, 636 | { 0xFA40, 40 }, 637 | { 0xFB40, 41 }, 638 | { 0xFC40, 42 }, 639 | }; 640 | -------------------------------------------------------------------------------- /HD_GUI/Subtitles.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Subtitles.h" 5 | #include "Common.h" 6 | 7 | FunctionPointer(void, DrawFileSelectWindows, (float pos_x, float pos_y, float pos_z, float width, float height), 0x4343E0); 8 | DataPointer(float, MissionTextAlpha, 0x3C8307C); 9 | 10 | static float RecapScreenY = 0; 11 | static int NumberOfTextLines = 0; 12 | static ListenToRecapMode ListenToRecap; 13 | static float GlobalRecapAlphaForFadeout = 1.0f; 14 | static float SubtitleShadowX = 1.0f; 15 | static float SubtitleShadowY = 1.0f; 16 | static float MissionScreenScale = 1.0f; 17 | static int SubtitleFontColorR = 255; 18 | static int SubtitleFontColorG = 255; 19 | static int SubtitleFontColorB = 255; 20 | static int RecapFontColorR = 255; 21 | static int RecapFontColorG = 255; 22 | static int RecapFontColorB = 255; 23 | static float RecapSpacing = 5.0f; 24 | static float SubtitleSpacing = 6.0f; 25 | bool korean = false; 26 | 27 | static FontOffset JapaneseCharacterData = { 60, 0, 0 }; 28 | static FontOffset KoreanCharacterData = { 60, 0, 0 }; 29 | static FontOffset KoreanSpaceCharacterData = { 24, 0, 0 }; 30 | static FontOffset JapaneseSpaceCharacterData = { 24, 0, 0 }; 31 | 32 | bool IsJapaneseCharacter(unsigned __int16 character) 33 | { 34 | if (!korean) 35 | return character > 0x8000; 36 | if (character > 0xFF) 37 | return true; 38 | return false; 39 | } 40 | 41 | FontOffset const& GetFontCharacterData(unsigned __int16 character) 42 | { 43 | // force space width to 32 in Japanese 44 | if (korean) 45 | { 46 | if (!TextLanguage && character == 0x20) return KoreanSpaceCharacterData; 47 | else if (IsJapaneseCharacter(character)) return KoreanCharacterData; 48 | else if (character == 0x02) return KoreanCharacterData; 49 | else return FontCharacterData[character & 0xFF]; 50 | } 51 | if (!TextLanguage && character == 0x20) return JapaneseSpaceCharacterData; 52 | else if (IsJapaneseCharacter(character)) return JapaneseCharacterData; 53 | else return FontCharacterData[character & 0xFF]; 54 | } 55 | 56 | float CalculateSpacingBetweenCharacters(unsigned __int16 character_a, unsigned __int16 character_b, float halfwidth_spacing, float fullwidth_spacing) 57 | { 58 | if (IsJapaneseCharacter(character_a) || IsJapaneseCharacter(character_b)) return fullwidth_spacing; 59 | else return halfwidth_spacing + FontCharacterData[character_b & 0xFF].offset_x; 60 | } 61 | 62 | float CalculateSpacingInArray(unsigned __int16* array, int next_character_index, float halfwidth_spacing, float fullwidth_spacing) 63 | { 64 | if (next_character_index == 0) return 0; 65 | else return CalculateSpacingBetweenCharacters(array[next_character_index - 1], array[next_character_index], halfwidth_spacing, fullwidth_spacing); 66 | } 67 | 68 | float CalculateRecapSpacing(unsigned __int16* array, int next_character_index) 69 | { 70 | return CalculateSpacingInArray(array, next_character_index, RecapSpacing, 0); 71 | } 72 | 73 | float CalculateSubtitleSpacing(unsigned __int16* array, int next_character_index) 74 | { 75 | return CalculateSpacingInArray(array, next_character_index, SubtitleSpacing, 5.0f); 76 | } 77 | 78 | int GetTexidForCodepage(unsigned __int16 character) 79 | { 80 | if (korean) 81 | { 82 | //PrintDebug("Char: %X, %d\n", character, (character - 0xAC00) % 256); 83 | if (character >= 0xAC00 && character <= 0xD7A3) 84 | return (character - 0xAC00) / 256; 85 | else 86 | return 0; 87 | } 88 | for (unsigned int i = 0; i < LengthOfArray(JapaneseSubtitleCodepage); i++) 89 | { 90 | if (character >= JapaneseSubtitleCodepage[i].StartChar && character <= JapaneseSubtitleCodepage[i].StartChar + 255) return i; 91 | } 92 | return 0; 93 | } 94 | 95 | void DrawCharacter(NJS_SPRITE* sprite, unsigned __int16 index, char mode, float parameter) 96 | { 97 | //index = 0x9EF7; 98 | unsigned __int16 character = 0; 99 | short texid = 0; 100 | float FontAlpha = 1.0f; 101 | float pos_x_bk = sprite->p.x; 102 | float pos_y_bk = sprite->p.y; 103 | float scale_x_bk = sprite->sx; 104 | float scale_y_bk = sprite->sy; 105 | if (IsJapaneseCharacter(index)) 106 | { 107 | if (korean) 108 | { 109 | sprite->p.x -= sprite->sx * 0.1f * 64; 110 | sprite->p.y -= sprite->sy * 0.1f * 64; 111 | //sprite->sx *= 1.2f; 112 | //sprite->sy *= 1.2f; 113 | } 114 | else 115 | { 116 | sprite->p.x -= sprite->sx * 0.1f * 64; 117 | sprite->p.y -= sprite->sy * 0.1f * 64; 118 | sprite->sx *= 1.2f; 119 | sprite->sy *= 1.2f; 120 | } 121 | } 122 | int v2_bk = 0; 123 | int uvdif = 0; 124 | float dif = MissionScreenScale - sprite->p.y; 125 | float finalscale = 1.0f; 126 | float depth = -1.0f; 127 | //PrintDebug("Mscale dif: %f\n", dif); 128 | if (mode == 1) // Recap screen / parameter is Y position 129 | { 130 | if (parameter >= 300) FontAlpha = max(0, (50 - (parameter - 300)) / 50.0f); 131 | else if (parameter <= 100) FontAlpha = max(0, (40 - (100 - parameter)) / 40.0f); 132 | else FontAlpha = 1.0f; 133 | //PrintDebug("Y: %f, FA: %f\n", YPosition, FontAlpha); 134 | } 135 | else if (mode == 2) // "File deleted" text 136 | { 137 | FontAlpha = 1.0f; 138 | GlobalRecapAlphaForFadeout = 1.0f; 139 | } 140 | else if (mode == 3) // Mission tutorial text / parameter is eh 141 | { 142 | FontAlpha = 1.0f - MissionTextAlpha; 143 | GlobalRecapAlphaForFadeout = 1.0f; 144 | } 145 | // Japanese 146 | if (IsJapaneseCharacter(index)) 147 | { 148 | njSetTexture(&SubtitleJPTexlist); 149 | sprite->tlist = &SubtitleJPTexlist; 150 | if (korean) 151 | { 152 | character = index % 256; 153 | } 154 | else 155 | { 156 | if (index < 0x8140) character = 1; 157 | else character = (index - 0x8140) % 256; 158 | } 159 | texid = GetTexidForCodepage(index); 160 | } 161 | // English etc. 162 | else 163 | { 164 | njSetTexture(&SubtitleTexlist); 165 | sprite->tlist = &SubtitleTexlist; 166 | character = index % 256; 167 | texid = 0; 168 | } 169 | //SubtitleFont[character].cy = 32; 170 | //SubtitleFont[character].sy = 32; 171 | //SubtitleFont[character].v2 = SubtitleFont[character].v1+8; 172 | SubtitleFont[character].texid = texid; 173 | // Apply transformations 174 | if (mode == 3) 175 | { 176 | depth = -1.15f; 177 | v2_bk = SubtitleFont[character].v2; 178 | if (dif <= 47.0f) 179 | { 180 | finalscale = max(0, dif / 47.0f); 181 | if (finalscale < 0.28f) finalscale = 0; 182 | uvdif = SubtitleFont[character].v2 - SubtitleFont[character].v1; 183 | SubtitleFont[character].v2 = SubtitleFont[character].v1 + int((float)uvdif * finalscale); 184 | SubtitleFont[character].sy = int(64.0f* finalscale); 185 | sprite->sy *= float(SubtitleFont[character].sy)/64.0f; 186 | //PrintDebug("Scale: %f, sy: %f, texsy: %d, v2:%d \n", finalscale, sprite->sy, SubtitleFont[character].sy, SubtitleFont[character].v2); 187 | } 188 | } 189 | // Draw font shadow 190 | if (SubtitleShadowX != 0 || SubtitleShadowY != 0) 191 | { 192 | if (mode) SetMaterialAndSpriteColor_Float(max(0, FontAlpha * GlobalRecapAlphaForFadeout), 0, 0, 0); 193 | else SetMaterialAndSpriteColor_Float(GlobalSpriteColor.a, 0, 0, 0); 194 | sprite->p.x += SubtitleShadowX; 195 | sprite->p.y += SubtitleShadowY; 196 | if (mode != 3 || !TextLanguage) njDrawSprite2D_DrawNow(sprite, character, depth, NJD_SPRITE_ALPHA | NJD_SPRITE_COLOR); 197 | else njDrawSprite2D_Queue(sprite, character, -1.15f, NJD_SPRITE_ALPHA | NJD_SPRITE_COLOR, (QueuedModelFlagsB)0); 198 | sprite->p.x -= SubtitleShadowX; 199 | sprite->p.y -= SubtitleShadowY; 200 | } 201 | // Draw text 202 | //PrintDebug("Drawing character %X, texid %d, id %d, alpha %f, y %f\n", index, texid, character, FontAlpha, parameter); 203 | if (mode) SetMaterialAndSpriteColor_Float(max(0, FontAlpha * GlobalRecapAlphaForFadeout), max(0, GlobalRecapAlphaForFadeout * RecapFontColorR / 255.0f), max(0, GlobalRecapAlphaForFadeout * RecapFontColorG / 255.0f), max(0, GlobalRecapAlphaForFadeout * RecapFontColorB / 255.0f)); 204 | else SetMaterialAndSpriteColor_Float(GlobalSpriteColor.a, SubtitleFontColorR / 255.0f, SubtitleFontColorG / 255.0f, SubtitleFontColorB / 255.0f); 205 | //SetMaterialAndSpriteColor_Float(1, 1, 1, 1); 206 | // Japanese mission tutorial text should be drawn immediately to avoid overriding texture ids by next characters 207 | if (mode != 3 || !TextLanguage) njDrawSprite2D_DrawNow(sprite, character, depth, NJD_SPRITE_ALPHA | NJD_SPRITE_COLOR); 208 | else njDrawSprite2D_Queue(sprite, character, -1.15f, NJD_SPRITE_ALPHA | NJD_SPRITE_COLOR, (QueuedModelFlagsB)0); 209 | // Remove transformations 210 | if (mode == 3) 211 | { 212 | SubtitleFont[character].sy = 64; 213 | SubtitleFont[character].v2 = v2_bk; 214 | } 215 | sprite->p.x = pos_x_bk; 216 | sprite->p.y = pos_y_bk; 217 | sprite->sx = scale_x_bk; 218 | sprite->sy = scale_y_bk; 219 | } 220 | 221 | void AddSubtitleCharacter(unsigned __int16* array, unsigned __int16 character) 222 | { 223 | for (int i = 0; i < 255; i++) 224 | { 225 | if (array[i] == 0) 226 | { 227 | array[i] = character; 228 | array++; 229 | return; 230 | } 231 | } 232 | } 233 | 234 | void ClearTextArray(unsigned __int16* array) 235 | { 236 | for (int i = 0; i < 255; i++) 237 | { 238 | array[i] = 0; 239 | } 240 | } 241 | 242 | void ParseSubtitle(const char* string) 243 | { 244 | unsigned __int16* array = nullptr; 245 | unsigned __int16 character = 0; 246 | 247 | if (ListenToRecap == ListenToRecapMode::Listen) 248 | { 249 | NumberOfTextLines++; 250 | } 251 | 252 | if (GameMode != GameModes_Adventure_Story && GameMode != 0x14) //Check if not on recap screen or mission tutorial screen 253 | { 254 | array = SubtitleArray; 255 | } 256 | else array = RecapArray[NumberOfTextLines - 1].LineString_S; 257 | 258 | ClearTextArray(array); 259 | /* 260 | PrintDebug("Text string:"); 261 | for (int i = 0; i < strlen(string); i++) 262 | { 263 | PrintDebug("%X ", string[i]); 264 | } 265 | PrintDebug("Text string end\n"); 266 | */ 267 | WCHAR str_conv[514]; 268 | if (korean) 269 | { 270 | memset(str_conv, 0, 0x400u); 271 | MultiByteToWideChar(949, 0, string, 0xFFFFFFFF, str_conv, strlen(string)); 272 | for (unsigned int i = 0; i < strlen(string); i++) 273 | { 274 | character = str_conv[i]; 275 | //PrintDebug("%X ", character); 276 | switch (character) 277 | { 278 | case 0x2026: 279 | AddSubtitleCharacter(array, 0x2); 280 | if (!MissionScreenState) 281 | i++; 282 | break; 283 | case 0x300C: // Left bracket 284 | AddSubtitleCharacter(array, 0x91); 285 | if (!MissionScreenState) 286 | i++; 287 | break; 288 | case 0x300D: // Right bracket 289 | AddSubtitleCharacter(array, 0x93); 290 | if (!MissionScreenState) 291 | i++; 292 | break; 293 | default: 294 | AddSubtitleCharacter(array, character); 295 | break; 296 | } 297 | } 298 | } 299 | else 300 | { 301 | for (unsigned int i = 0; i < strlen(string); i++) 302 | { 303 | // Here's a bunch of hardcoded Japanese characters because the game uses it in English too and because I'm tired of this shit 304 | if (TextLanguage == 1 && string[i] == 0xFFFFFF81) 305 | { 306 | // Square 307 | if (string[i + 1] == 0xFFFFFFA1) 308 | { 309 | AddSubtitleCharacter(array, 0x01); 310 | } 311 | // ... 312 | if (string[i + 1] == 0x63) 313 | { 314 | AddSubtitleCharacter(array, 0x2); 315 | } 316 | // ' 317 | if (string[i + 1] == 0x65) 318 | { 319 | AddSubtitleCharacter(array, 0x27); 320 | } 321 | // ! 322 | if (string[i + 1] == 0x49) 323 | { 324 | AddSubtitleCharacter(array, 0x21); 325 | } 326 | // ? 327 | if (string[i + 1] == 0x48) 328 | { 329 | AddSubtitleCharacter(array, 0x3F); 330 | } 331 | // Skip the next character because it's zenkaku 332 | AddSubtitleCharacter(array, 0x20); 333 | i++; 334 | } 335 | // Read as zenkaku 336 | else if (TextLanguage <= 1 && string[i] & 0xFFFFFF00) 337 | { 338 | character = 0x100 * (string[i] & 0xFF) + abs(string[i + 1] & 0xFF); 339 | //PrintDebug("%X ", character); 340 | i++; 341 | AddSubtitleCharacter(array, character); 342 | } 343 | // Read as hankaku 344 | else 345 | { 346 | character = string[i] & 0xFF; 347 | //PrintDebug("%X ", character); 348 | AddSubtitleCharacter(array, character); 349 | } 350 | } 351 | } 352 | // Calculate recap line length 353 | if (ListenToRecap == ListenToRecapMode::Listen) 354 | { 355 | TextLine& LastRecapArray = RecapArray[NumberOfTextLines - 1]; 356 | for (int i = 0; i < 255; i++) 357 | { 358 | // Calculate the line's width in pixels (at 1.0x) with character spacing 359 | if (array[i] == 0) break; 360 | else if (array[i] != 0x07 && array[i] != 0x09) 361 | { 362 | LastRecapArray.LineLength += (int)(CalculateRecapSpacing(LastRecapArray.LineString_S, i) + GetFontCharacterData(LastRecapArray.LineString_S[i]).width); 363 | } 364 | } 365 | } 366 | } 367 | 368 | Trampoline* DisplaySubtitleThing_t = nullptr; 369 | static void __cdecl DisplaySubtitleThing_r(SubtitleThing* a1, const char* a2) 370 | { 371 | TARGET_DYNAMIC(DisplaySubtitleThing)(a1, a2); 372 | //PrintDebug("Subtitle: %s\n", a2); 373 | ParseSubtitle(a2); 374 | } 375 | 376 | Trampoline* DisplayRecapThing_t = nullptr; 377 | static void __cdecl DisplayRecapThing_r(ObjectMaster* a1) 378 | { 379 | EntityData1* SubtitleEntity = a1->Data1; 380 | TARGET_DYNAMIC(DisplayRecapThing)(a1); 381 | RecapScreenY = SubtitleEntity->Position.y; 382 | //PrintDebug("Ass: %f and %f", SubtitleEntity->Position.x, SubtitleEntity->Position.y); 383 | } 384 | 385 | void LoadFontdata(const IniFile* config) 386 | { 387 | //PrintDebug("\n"); 388 | SubtitleFontColorR = config->getInt("General", "SubtitleFontColorR", 255); 389 | SubtitleFontColorG = config->getInt("General", "SubtitleFontColorG", 255); 390 | SubtitleFontColorB = config->getInt("General", "SubtitleFontColorB", 255); 391 | SubtitleSpacing = config->getFloat("General", "SubtitleSpacing", 6.0f); 392 | RecapFontColorR = config->getInt("General", "RecapFontColorR", 255); 393 | RecapFontColorG = config->getInt("General", "RecapFontColorG", 255); 394 | RecapFontColorB = config->getInt("General", "RecapFontColorB", 255); 395 | RecapSpacing = config->getFloat("General", "RecapSpacing", 6.0f); 396 | SubtitleShadowX = config->getFloat("General", "ShadowXOffset", 1.0f); 397 | SubtitleShadowY = config->getFloat("General", "ShadowYOffset", 1.0f); 398 | for (unsigned int i = 0; i < LengthOfArray(FontCharacterData); i++) 399 | { 400 | FontCharacterData[i].width = 32; 401 | FontCharacterData[i].offset_x = 0; 402 | FontCharacterData[i].offset_y = 0; 403 | //PrintDebug("[%d]\n", i); 404 | std::string w = std::to_string(i); 405 | FontCharacterData[i].width = config->getInt(w, "Width"); 406 | FontCharacterData[i].offset_x = config->getInt(w, "OffsetX"); 407 | FontCharacterData[i].offset_y = config->getInt(w, "OffsetY"); 408 | //PrintDebug("Width=%d\n", FontCharacterData[i].width); 409 | //PrintDebug("OffsetX=%d\n", FontCharacterData[i].offset_x); 410 | //PrintDebug("OffsetY=%d\n", FontCharacterData[i].offset_y); 411 | //PrintDebug("\n"); 412 | } 413 | } 414 | 415 | void BuildFontINI() 416 | { 417 | PrintDebug("\n"); 418 | PrintDebug("[General]\n"); 419 | PrintDebug("SubtitleFontColorR=199\n"); 420 | PrintDebug("SubtitleFontColorG=199\n"); 421 | PrintDebug("SubtitleFontColorB=217\n"); 422 | PrintDebug("SubtitleSpacing=6.0\n"); 423 | PrintDebug("RecapFontColorR=199\n"); 424 | PrintDebug("RecapFontColorG=199\n"); 425 | PrintDebug("RecapFontColorB=217\n"); 426 | PrintDebug("RecapFontColorB=217\n"); 427 | PrintDebug("RecapSpacing=5.0\n"); 428 | PrintDebug("\n"); 429 | for (unsigned int i = 0; i < LengthOfArray(FontCharacterData); i++) 430 | { 431 | PrintDebug("[%d]\n", i); 432 | PrintDebug("Width=%d\n", FontCharacterData[i].width); 433 | PrintDebug("OffsetX=%d\n", FontCharacterData[i].offset_x); 434 | PrintDebug("OffsetY=%d\n", FontCharacterData[i].offset_y); 435 | PrintDebug("\n"); 436 | } 437 | } 438 | 439 | int CalculateLineLength(int start_char) 440 | { 441 | int result = 0; 442 | for (unsigned int i = start_char; i < LengthOfArray(SubtitleArray); i++) 443 | { 444 | if (SubtitleArray[i] == 0 || SubtitleArray[i] == 0x0A) 445 | { 446 | break; 447 | } 448 | else if (SubtitleArray[i] != 0x09 && SubtitleArray[i] != 0x07) 449 | { 450 | result += (int)(CalculateSubtitleSpacing(SubtitleArray, i) + GetFontCharacterData(SubtitleArray[i]).width); 451 | } 452 | } 453 | //PrintDebug("Line length for line starting at %d: %d\n", start_char, result); 454 | return result; 455 | } 456 | 457 | float CalculateLongestLineLength() 458 | { 459 | /*PrintDebug("\nSubtitle array:"); 460 | for (int i = 0; i < LengthOfArray(SubtitleArray); i++) 461 | { 462 | PrintDebug("%X ", SubtitleArray[i] % 256); 463 | } 464 | PrintDebug("\nSubtitle array over\n");*/ 465 | int linenumber = 0; 466 | int line1 = 0; 467 | int line2 = 0; 468 | int line3 = 0; 469 | int line4 = 0; 470 | int result = 0; 471 | int spaceadd = 0; 472 | for (unsigned int cursor = 0; cursor < LengthOfArray(SubtitleArray); cursor++) 473 | { 474 | if (SubtitleArray[cursor] == 0x0A) 475 | { 476 | linenumber++; 477 | } 478 | else if (SubtitleArray[cursor] == 0) 479 | { 480 | result = max(max(line1, line2), max(line3, line4)); 481 | goto results; 482 | break; 483 | } 484 | else if (SubtitleArray[cursor] != 0x09 && SubtitleArray[cursor] != 0x07) 485 | { 486 | spaceadd = (int)(CalculateSubtitleSpacing(SubtitleArray, cursor) + GetFontCharacterData(SubtitleArray[cursor]).width); 487 | //Add spacing 488 | switch (linenumber) 489 | { 490 | case 0: 491 | line1 += spaceadd; 492 | break; 493 | case 1: 494 | line2 += spaceadd; 495 | break; 496 | case 2: 497 | line3 += spaceadd; 498 | break; 499 | case 3: 500 | line4 += spaceadd; 501 | break; 502 | } 503 | } 504 | } 505 | goto results; 506 | results: 507 | //PrintDebug("1: %d, 2: %d, 3: %d, 4: %d, longest line: %d\n", line1, line2, line3, line4, result); 508 | return (float)result; 509 | } 510 | 511 | void DrawMissionTutorialTextHook(NJS_SPRITE* sp, Int n, Float pri, NJD_SPRITE attr, QueuedModelFlagsB queue_flags) 512 | { 513 | float ResolutionScale = (float)VerticalResolution / 480.0f; 514 | float FontAlpha = 1.0f; 515 | float OldOffsetX = 0; 516 | float OffsetY = 0; 517 | NJS_SPRITE SubtitleCharacterSprite = {{ 0, 0, 0 }, 0.4f, 0.4f, 0, &SubtitleTexlist, SubtitleFont}; 518 | //Set up scaling 519 | SubtitleCharacterSprite.sx = 0.4f; 520 | SubtitleCharacterSprite.sy = 0.4f; 521 | for (int u = 0; u < NumberOfTextLines; u++) 522 | { 523 | //PrintDebug("Length for line %d: %i\n", u, RecapArray[u].LineLength); 524 | // Calculate centering 525 | OldOffsetX = sp->p.x; 526 | SubtitleCharacterSprite.p.y = sp->p.y + OffsetY; 527 | for (int i = 0; i < 255; i++) 528 | { 529 | if (RecapArray[u].LineString_S[i] == 0) break; 530 | // Calculate X position 531 | if (i == 0) SubtitleCharacterSprite.p.x = OldOffsetX; 532 | else 533 | { 534 | SubtitleCharacterSprite.p.x = OldOffsetX + SubtitleCharacterSprite.sx * (GetFontCharacterData(RecapArray[u].LineString_S[i - 1]).width + CalculateRecapSpacing(RecapArray[u].LineString_S, i)); 535 | } 536 | // Draw 537 | if (RecapArray[u].LineString_S[i] != 0x0A && RecapArray[u].LineString_S[i] != 0x07 && RecapArray[u].LineString_S[i] != 0x09) 538 | { 539 | DrawCharacter(&SubtitleCharacterSprite, RecapArray[u].LineString_S[i], 3, OffsetY); 540 | } 541 | OldOffsetX = SubtitleCharacterSprite.p.x; 542 | } 543 | OffsetY += 68.0f * SubtitleCharacterSprite.sx; 544 | } 545 | } 546 | 547 | void DrawSubtitleHook(NJS_SPRITE* sp, Int n, Float pri, NJD_SPRITE attr, QueuedModelFlagsB queue_flags) 548 | { 549 | NJS_SPRITE SubtitleCharacterSprite = {{ 0, 0, 0 }, 0.4f, 0.4f, 0, &SubtitleTexlist, SubtitleFont}; 550 | float scaled320 = 320.0f; 551 | if (sp->p.x <= 90) scaled320 = 320.0f; else scaled320 = HorizontalResolution / 2.0f; 552 | // Calculate newlines 553 | float HorizontalOffset_Initial = 0; 554 | float HorizontalOffset_Current = 0; 555 | float VerticalOffset = 0; 556 | int LineStart = 0; 557 | // Set subtitle position and texlist 558 | SubtitleCharacterSprite.p.x = sp->p.x; 559 | SubtitleCharacterSprite.p.y = sp->p.y; 560 | // Set font scale - for Mission Stat screen it needs to be smaller to fit mission descriptions into the small frame 561 | if (MissionScreenState) 562 | { 563 | SubtitleCharacterSprite.sx = 0.28f; 564 | SubtitleCharacterSprite.sy = 0.28f; 565 | } 566 | else 567 | { 568 | SubtitleCharacterSprite.sx = 0.4f; 569 | SubtitleCharacterSprite.sy = 0.4f; 570 | } 571 | for (unsigned int i = 0; i < LengthOfArray(SubtitleArray); i++) 572 | { 573 | if (SubtitleArray[i] == 0) break; 574 | // Calculate horizontal centering 575 | if (MissionScreenState) HorizontalOffset_Initial = 7.0f * 32.0f * SubtitleCharacterSprite.sx; 576 | // Fixed offset for mission stat screen 577 | else 578 | { 579 | // 0x09 as the first character centers the line 580 | if (SubtitleArray[LineStart] == 0x09) 581 | { 582 | HorizontalOffset_Initial = scaled320 - (CalculateLineLength(LineStart) / 2.0f) * SubtitleCharacterSprite.sx; 583 | } 584 | // Otherwise (e.g. two lines) center by the longest line 585 | else 586 | { 587 | HorizontalOffset_Initial = scaled320 - (CalculateLongestLineLength() / 2.0f) * SubtitleCharacterSprite.sx; 588 | } 589 | } 590 | // If not newline or spacing, draw the character 591 | if (SubtitleArray[i] != 0x0A && SubtitleArray[i] != 0x09 && SubtitleArray[i] != 0x07 && SubtitleArray[i] != 0i8) 592 | { 593 | // Add spacing 594 | if (i != 0) 595 | HorizontalOffset_Current += SubtitleCharacterSprite.sx * (GetFontCharacterData(SubtitleArray[i - 1]).width + CalculateSubtitleSpacing(SubtitleArray, i)); 596 | //PrintDebug("Letter %d, width %d, hz:%f\n", SubtitleArray[i] & 0xFF, FontCharacterData[SubtitleArray[i] & 0xFF].width, HorizontalOffset_Current); 597 | SubtitleCharacterSprite.p.x = HorizontalOffset_Initial + HorizontalOffset_Current; 598 | SubtitleCharacterSprite.p.y = sp->p.y + VerticalOffset + SubtitleCharacterSprite.sx * GetFontCharacterData(SubtitleArray[i]).offset_y; 599 | DrawCharacter(&SubtitleCharacterSprite, SubtitleArray[i], 0, 0); 600 | } 601 | else if (SubtitleArray[i] == 0x0A) 602 | { 603 | VerticalOffset += 68.0f * SubtitleCharacterSprite.sx; 604 | HorizontalOffset_Current = 0; 605 | LineStart = i + 1; 606 | } 607 | } 608 | } 609 | 610 | void DrawSaveDeletedTextHook(NJS_TEXTURE_VTX* points, Int count, Uint32 gbix, Int flag) 611 | { 612 | //PrintDebug("XP: %f\n", points->x); 613 | float scaled320 = points->x <= 60 ? 320.0f: HorizontalResolution / 2.0f; 614 | float ResolutionScale = (float)VerticalResolution / 480.0f; 615 | float FontAlpha = 1.0f; 616 | float OldOffsetX = points[0].x; 617 | NJS_SPRITE SubtitleCharacterSprite = {{ 0, 0, 0 }, 0.4f, 0.4f, 0, &SubtitleTexlist, SubtitleFont}; 618 | OldOffsetX = scaled320 - (CalculateLineLength(0) / 2.0f) * SubtitleCharacterSprite.sx; 619 | // Set up scaling 620 | SubtitleCharacterSprite.sx = 0.4f; 621 | SubtitleCharacterSprite.sy = 0.4f; 622 | for (unsigned int i = 0; i < LengthOfArray(SubtitleArray); i++) 623 | { 624 | if (SubtitleArray[i] == 0) 625 | break; 626 | // Calculate X position 627 | if (i == 0) 628 | SubtitleCharacterSprite.p.x = OldOffsetX; 629 | else if (SubtitleArray[i] != 0x09) 630 | { 631 | SubtitleCharacterSprite.p.x = OldOffsetX + SubtitleCharacterSprite.sx * (GetFontCharacterData(SubtitleArray[i - 1]).width + CalculateSubtitleSpacing(SubtitleArray, i)); 632 | } 633 | // Set Y position 634 | SubtitleCharacterSprite.p.y = points[0].y; 635 | // Draw character 636 | DrawCharacter(&SubtitleCharacterSprite, SubtitleArray[i], 2, 0); 637 | OldOffsetX = SubtitleCharacterSprite.p.x; 638 | } 639 | } 640 | 641 | void DrawRecapTextHook(NJS_TEXTURE_VTX* points, Int count, Uint32 gbix, Int flag) 642 | { 643 | float ResolutionScale = (float)VerticalResolution / 480.0f; 644 | float FontAlpha = 1.0f; 645 | float OldOffsetX = 0; 646 | float OffsetY = 0; 647 | NJS_SPRITE SubtitleCharacterSprite = {{ 0, 0, 0 }, 0.4f, 0.4f, 0, &SubtitleTexlist, SubtitleFont}; 648 | // Set up scaling 649 | SubtitleCharacterSprite.sx = 0.4f * ResolutionScale; 650 | SubtitleCharacterSprite.sy = 0.4f * ResolutionScale; 651 | float LeftCorner = ((float)HorizontalResolution - ResolutionScale * 640.0f)/2.0f; 652 | //PrintDebug("Left: %f\n", LeftCorner); 653 | for (int u = 0; u < NumberOfTextLines; u++) 654 | { 655 | //PrintDebug("Length for line %d: %i\n", u, RecapArray[u].LineLength); 656 | // Calculate centering 657 | if (RecapArray[u].LineString_S[0] == 0x07 || RecapArray[u].LineString_S[0] == 0x09) OldOffsetX = ((float)HorizontalResolution / 2.0f) - SubtitleCharacterSprite.sx * (RecapArray[u].LineLength / 2); 658 | else OldOffsetX = LeftCorner + 64 * ResolutionScale; 659 | for (int i = 0; i < 255; i++) 660 | { 661 | if (RecapArray[u].LineString_S[i] == 0) break; 662 | // Calculate X position 663 | if (i == 0) SubtitleCharacterSprite.p.x = OldOffsetX; 664 | else 665 | { 666 | SubtitleCharacterSprite.p.x = OldOffsetX + SubtitleCharacterSprite.sx * (GetFontCharacterData(RecapArray[u].LineString_S[i - 1]).width + CalculateRecapSpacing(RecapArray[u].LineString_S, i)); 667 | } 668 | // Calculate Y position 669 | OffsetY = SubtitleCharacterSprite.sx * GetFontCharacterData(RecapArray[u].LineString_S[i]).offset_y; 670 | SubtitleCharacterSprite.p.y = (u * 40 + 118 + RecapScreenY) * ResolutionScale + OffsetY; 671 | // Draw 672 | DrawCharacter(&SubtitleCharacterSprite, RecapArray[u].LineString_S[i], 1, (SubtitleCharacterSprite.p.y - OffsetY) / ResolutionScale); 673 | OldOffsetX = SubtitleCharacterSprite.p.x; 674 | } 675 | } 676 | } 677 | 678 | void RecapStart(SubtitleThing* a1) 679 | { 680 | //PrintDebug("Recap start\n"); 681 | if (ListenToRecap != ListenToRecapMode::Done) 682 | { 683 | ListenToRecap = ListenToRecapMode::Listen; 684 | NumberOfTextLines = 0; 685 | for (unsigned int i = 0; i < LengthOfArray(RecapArray); i++) 686 | { 687 | RecapArray[i].LineLength = 0; 688 | ClearTextArray(RecapArray[i].LineString_S); 689 | } 690 | } 691 | DoTextThing_Start(a1); 692 | } 693 | 694 | void MissionStart(SubtitleThing* a1) 695 | { 696 | //PrintDebug("Mission start\n"); 697 | if (ListenToRecap != ListenToRecapMode::Done) 698 | { 699 | ListenToRecap = ListenToRecapMode::Listen; 700 | NumberOfTextLines = 0; 701 | for (unsigned int i = 0; i < LengthOfArray(RecapArray); i++) 702 | { 703 | RecapArray[i].LineLength = 0; 704 | ClearTextArray(RecapArray[i].LineString_S); 705 | } 706 | } 707 | DoTextThing_Start(a1); 708 | } 709 | 710 | void RecapStop(SubtitleThing* a1) 711 | { 712 | //PrintDebug("Recap stop\n"); 713 | if (ListenToRecap != ListenToRecapMode::Done) 714 | { 715 | ListenToRecap = ListenToRecapMode::Done; 716 | } 717 | DoTextThing_Stop(a1); 718 | } 719 | 720 | void MissionStop() 721 | { 722 | if (ListenToRecap != ListenToRecapMode::Done) 723 | { 724 | ListenToRecap = ListenToRecapMode::Done; 725 | } 726 | } 727 | 728 | void MissionWindowHook(float pos_x, float pos_y, float pos_z, float width, float height) 729 | { 730 | DrawFileSelectWindows(pos_x, pos_y, pos_z, width, height); 731 | //PrintDebug("Height: %f\n", height); 732 | MissionScreenScale = pos_y+height; 733 | } 734 | 735 | void LoadSubtitleFont() 736 | { 737 | LoadPVM("SUBTITLE", &SubtitleTexlist); 738 | LoadPVM(korean ? "SUBTITLE_KR" : "SUBTITLE_JP", &SubtitleJPTexlist); 739 | helperFunctionsGlobal->RegisterPermanentTexlist(&SubtitleTexlist); 740 | helperFunctionsGlobal->RegisterPermanentTexlist(&SubtitleJPTexlist); 741 | } 742 | 743 | void Subtitles_Init(const char* path, const HelperFunctions& helperFunctions) 744 | { 745 | // Subtitle hooks 746 | WriteCall((void*)0x6431D3, MissionWindowHook); 747 | DisplaySubtitleThing_t = new Trampoline(0x40E570, 0x40E575, DisplaySubtitleThing_r); 748 | DisplayRecapThing_t = new Trampoline(0x642300, 0x642306, DisplayRecapThing_r); 749 | // Disable all the stuff that sets up the "Now saving" text but nothing else 750 | WriteData<5>((char*)0x40BE6C, 0x90); 751 | WriteData<5>((char*)0x40BE92, 0x90); 752 | WriteData<5>((char*)0x40BEA1, 0x90); 753 | WriteData<5>((char*)0x40BEAB, 0x90); 754 | WriteData<5>((char*)0x40BF27, 0x90); 755 | WriteCall((void*)0x40D7DA, DrawSubtitleHook); 756 | WriteCall((void*)0x642363, RecapStart); 757 | WriteCall((void*)0x6423EE, RecapStop); 758 | WriteCall((void*)0x642427, DrawRecapTextHook); 759 | WriteCall((void*)0x421906, DrawSaveDeletedTextHook); 760 | WriteCall((void*)0x642EF6, MissionStart); 761 | WriteCall((void*)0x642F36, MissionStop); 762 | WriteCall((void*)0x6430B2, DrawMissionTutorialTextHook); 763 | // Blacklist subtitle global indices in mipmap generation to speed up loading 764 | for (Uint32 i = 3489688888; i < 3489688933;i++) 765 | helperFunctions.MipmapBlacklistGBIX(i); 766 | // Load fontdata settings 767 | const std::string s_path(path); 768 | const std::string s_config_ini(helperFunctions.GetReplaceablePath("SYSTEM\\fontdata.ini")); 769 | const IniFile* const config = new IniFile(s_config_ini); 770 | LoadFontdata(config); 771 | delete config; 772 | if (GetModuleHandle(L"sadx-korean-mod") != nullptr) 773 | { 774 | korean = true; 775 | SubtitleJPTexlist.nbTexture = 44; 776 | } 777 | } 778 | 779 | void Subtitles_OnFrame() 780 | { 781 | if (GameMode != GameModes_Adventure_Story) 782 | { 783 | ListenToRecap = ListenToRecapMode::Idle; 784 | GlobalRecapAlphaForFadeout = 1.0f; 785 | } 786 | else if (RecapScreenMode == 2 && GlobalRecapAlphaForFadeout > 0.0f) 787 | GlobalRecapAlphaForFadeout = max(0.0f, GlobalRecapAlphaForFadeout - 0.05f); 788 | } --------------------------------------------------------------------------------