From 8e1355eb3624b510402fcd213fe40322e929faba Mon Sep 17 00:00:00 2001 From: DK22Pac Date: Wed, 8 Mar 2017 12:36:21 +0200 Subject: [PATCH] initial commit --- .gitattributes | 63 +++ .gitignore | 244 +++++++++ directFont.ini | 75 +++ directFont.sln | 28 ++ directFont/CD3DSprite.cpp | 62 +++ directFont/CD3DSprite.h | 31 ++ directFont/CNewFonts.cpp | 468 ++++++++++++++++++ directFont/CNewFonts.h | 63 +++ directFont/Main.cpp | 15 + directFont/directFont.vcxproj | 182 +++++++ directFont/directFont.vcxproj.filters | 26 + directFont/translations/BaseTranslation.h | 5 + directFont/translations/SanLtdTranslation.cpp | 205 ++++++++ directFont/translations/SanLtdTranslation.h | 8 + 14 files changed, 1475 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 directFont.ini create mode 100644 directFont.sln create mode 100644 directFont/CD3DSprite.cpp create mode 100644 directFont/CD3DSprite.h create mode 100644 directFont/CNewFonts.cpp create mode 100644 directFont/CNewFonts.h create mode 100644 directFont/Main.cpp create mode 100644 directFont/directFont.vcxproj create mode 100644 directFont/directFont.vcxproj.filters create mode 100644 directFont/translations/BaseTranslation.h create mode 100644 directFont/translations/SanLtdTranslation.cpp create mode 100644 directFont/translations/SanLtdTranslation.h diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3677a89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,244 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +[Xx]64/ +[Xx]86/ +[Bb]uild/ +bld/ +[Bb]in/ +[Oo]bj/ +[Rr]el*/ +[Dd]bg*/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml + +# TODO: Un-comment the next line if you do not want to checkin +# your web deploy settings because they may include unencrypted +# passwords +#*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# LightSwitch generated files +GeneratedArtifacts/ +ModelManifest.xml + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ diff --git a/directFont.ini b/directFont.ini new file mode 100644 index 0000000..e4b7698 --- /dev/null +++ b/directFont.ini @@ -0,0 +1,75 @@ +; DirectFont by DK22Pac settings +; Version 2.2 +; +; Translator could be NONE or SANLTD +; +[GENERAL] +UseTranslator=NONE +; +; FontName could be USE_FONT1 / USE_FONT2 / USE_FONT3 or USE_DEFAULT +; +; Default fonts: +; 1 FONT_GOTHIC, +; 2 FONT_SUBTITLES, +; 3 FONT_MENU, +; 4 FONT_PRICEDOWN +; +[FONT1] +FontName=Deutsch Gothic +Height=64 +Width=64 +ScaleFactor.x=0.3 +ScaleFactor.y=0.5 +Weight=200 +Italic=0 +CharSet=1 +OutputPrecision=0 +Quality=0 +PitchAndFamily=0 +UpcaseAlways=0 +ReplaceUnderscoreWithSpace=0 +; +[FONT2] +FontName=Bebas Neue +Height=64 +Width=64 +ScaleFactor.x=0.3 +ScaleFactor.y=0.5 +Weight=200 +Italic=0 +CharSet=1 +OutputPrecision=0 +Quality=0 +PitchAndFamily=0 +UpcaseAlways=0 +ReplaceUnderscoreWithSpace=1 +; +[FONT3] +FontName=The Bold Font +Height=64 +Width=64 +ScaleFactor.x=0.5 +ScaleFactor.y=0.8 +Weight=200 +Italic=0 +CharSet=1 +OutputPrecision=0 +Quality=0 +PitchAndFamily=0 +UpcaseAlways=1 +ReplaceUnderscoreWithSpace=1 +; +[FONT4] +FontName=Monofonto +Height=64 +Width=64 +ScaleFactor.x=0.7 +ScaleFactor.y=0.8 +Weight=200 +Italic=0 +CharSet=1 +OutputPrecision=0 +Quality=0 +PitchAndFamily=0 +UpcaseAlways=1 +ReplaceUnderscoreWithSpace=0 \ No newline at end of file diff --git a/directFont.sln b/directFont.sln new file mode 100644 index 0000000..b5be44c --- /dev/null +++ b/directFont.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directFont", "directFont\directFont.vcxproj", "{FF630438-A5EA-4612-A843-77CB56888722}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Dbg|x86 = Dbg|x86 + Dbg-XP|x86 = Dbg-XP|x86 + Rel|x86 = Rel|x86 + Rel-XP|x86 = Rel-XP|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF630438-A5EA-4612-A843-77CB56888722}.Dbg|x86.ActiveCfg = Dbg|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Dbg|x86.Build.0 = Dbg|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Dbg-XP|x86.ActiveCfg = Dbg-XP|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Dbg-XP|x86.Build.0 = Dbg-XP|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Rel|x86.ActiveCfg = Rel|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Rel|x86.Build.0 = Rel|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Rel-XP|x86.ActiveCfg = Rel-XP|Win32 + {FF630438-A5EA-4612-A843-77CB56888722}.Rel-XP|x86.Build.0 = Rel-XP|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/directFont/CD3DSprite.cpp b/directFont/CD3DSprite.cpp new file mode 100644 index 0000000..8d8452c --- /dev/null +++ b/directFont/CD3DSprite.cpp @@ -0,0 +1,62 @@ +#include "CD3DSprite.h" +#include "game_sa\RenderWare.h" + +CD3DSprite::CD3DSprite() { + D3DXCreateSprite(_RwD3DDevice, &m_pSprite); +} + +CD3DSprite::~CD3DSprite() { + m_pSprite->Release(); +} + +HRESULT CD3DSprite::QueryInterface(REFIID iid, LPVOID *ppv) { + return m_pSprite->QueryInterface(iid, ppv); +} + +ULONG CD3DSprite::AddRef() { + return m_pSprite->AddRef(); +} + +ULONG CD3DSprite::Release() { + return m_pSprite->Release(); +} + +HRESULT CD3DSprite::Begin(DWORD Flags) { + return m_pSprite->Begin(Flags); +} + +HRESULT CD3DSprite::End() { + return m_pSprite->End(); +} + +HRESULT CD3DSprite::GetDevice(LPDIRECT3DDEVICE9* ppDevice) { + return m_pSprite->GetDevice(ppDevice); +} + +HRESULT CD3DSprite::GetTransform(D3DXMATRIX *pTransform) { + return m_pSprite->GetTransform(pTransform); +} + +HRESULT CD3DSprite::SetTransform(CONST D3DXMATRIX *pTransform) { + return m_pSprite->SetTransform(pTransform); +} + +HRESULT CD3DSprite::SetWorldViewRH(CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView) { + return m_pSprite->SetWorldViewRH(pWorld, pView); +} + +HRESULT CD3DSprite::SetWorldViewLH(CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView) { + return m_pSprite->SetWorldViewLH(pWorld, pView); +} + +HRESULT CD3DSprite::Flush() { + return m_pSprite->Flush(); +} + +HRESULT CD3DSprite::OnLostDevice() { + return m_pSprite->OnLostDevice(); +} + +HRESULT CD3DSprite::OnResetDevice() { + return m_pSprite->OnResetDevice(); +} \ No newline at end of file diff --git a/directFont/CD3DSprite.h b/directFont/CD3DSprite.h new file mode 100644 index 0000000..62b6277 --- /dev/null +++ b/directFont/CD3DSprite.h @@ -0,0 +1,31 @@ +#pragma once +#include + +class CD3DSprite : public ID3DXSprite { + ID3DXSprite* m_pSprite; +public: + CD3DSprite(); + ~CD3DSprite(); + + // IUnknown + STDMETHOD(QueryInterface)(THIS_ REFIID iid, LPVOID *ppv); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + + // ID3DXSprite + STDMETHOD(GetDevice)(THIS_ LPDIRECT3DDEVICE9* ppDevice); + + STDMETHOD(GetTransform)(THIS_ D3DXMATRIX *pTransform); + STDMETHOD(SetTransform)(THIS_ CONST D3DXMATRIX *pTransform); + + STDMETHOD(SetWorldViewRH)(THIS_ CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView); + STDMETHOD(SetWorldViewLH)(THIS_ CONST D3DXMATRIX *pWorld, CONST D3DXMATRIX *pView); + + STDMETHOD(Begin)(THIS_ DWORD Flags); + STDMETHOD(Draw)(THIS_ LPDIRECT3DTEXTURE9 pTexture, CONST RECT *pSrcRect, CONST D3DXVECTOR3 *pCenter, CONST D3DXVECTOR3 *pPosition, D3DCOLOR Color); + STDMETHOD(Flush)(THIS); + STDMETHOD(End)(THIS); + + STDMETHOD(OnLostDevice)(THIS); + STDMETHOD(OnResetDevice)(THIS); +}; \ No newline at end of file diff --git a/directFont/CNewFonts.cpp b/directFont/CNewFonts.cpp new file mode 100644 index 0000000..56f846f --- /dev/null +++ b/directFont/CNewFonts.cpp @@ -0,0 +1,468 @@ +#include "CNewFonts.h" +#include "plugin.h" +#include "game_sa\CSprite2d.h" +#include "game_sa\CMessages.h" +#include "game_sa\CHudColours.h" +#include "translations\SanLtdTranslation.h" +#include + +using namespace plugin; + +CD3DSprite *CNewFonts::m_pFontSprite; +CNewFont CNewFonts::m_aFonts[4]; +eTranslation CNewFonts::m_Translation; +eFontStyle CNewFonts::m_FontId; +CRGBA CNewFonts::gLetterColors[MAX_TEXT_SIZE]; +unsigned int CNewFonts::gNumLetters; +bool CNewFonts::gShadow; + +bool CNewFont::SetupFont(char *fontName, unsigned int width, int height, float scaleX, float scaleY, unsigned int weight, bool italic, + unsigned int charSet, unsigned int outputPrecision, unsigned int quality, unsigned int pitchAndFamily, bool upperCase, + bool replaceUS) +{ + HRESULT hr = D3DXCreateFont(CNewFonts::GetCurrentDevice(), width, height, weight, 0, italic, charSet, outputPrecision, quality, + pitchAndFamily, fontName, &m_pD3DXFont); + if (hr != S_OK) { + m_pD3DXFont = NULL; + return Error("CNewFont::SetupFont: Can't load \"%s\" font", fontName); + } + m_initialised = true; + strcpy_s(m_fontName, fontName); + m_width = width; + m_height = height; + m_scaleX = scaleX; + m_scaleY = scaleY; + m_weight = weight; + m_italic = italic; + m_charSet = charSet; + m_outputPrecision = outputPrecision; + m_quality = quality; + m_pitchAndFamily = pitchAndFamily; + m_upperCase = upperCase; + m_replaceUS = replaceUS; + return true; +} + +void CNewFont::PrintString(char *text, CRect const& rect, float scale_x, float scale_y, CRGBA const& color, DWORD format, CRGBA const* backgroundColor, + float shadow, float outline, CRGBA const* dropColor) +{ + RECT d3drect; SetRect(&d3drect, rect.m_fLeft, rect.m_fTop, rect.m_fRight, rect.m_fBottom); + if (backgroundColor) + DrawRect(text, rect, scale_x, scale_y, format, *backgroundColor); + RECT d3drect2; SetRect(&d3drect2, d3drect.left / (scale_x / 2), d3drect.top / (scale_y / 2), d3drect.right / (scale_x / 2), d3drect.bottom / (scale_y / 2)); + D3DXMATRIX S, P; + D3DXMatrixScaling(&S, scale_x / 2, scale_y / 2, 1.0f); + CNewFonts::m_pFontSprite->GetTransform(&P); + CNewFonts::m_pFontSprite->SetTransform(&S); + CNewFonts::m_pFontSprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE); + if (shadow > 0.0f) { + RECT shadowRect(d3drect2); + shadowRect.left += shadow; + shadowRect.right += shadow; + shadowRect.top += shadow; + shadowRect.bottom += shadow; + CNewFonts::gShadow = true; + m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &shadowRect, format, D3DCOLOR_ARGB(dropColor->alpha, + dropColor->red, dropColor->green, dropColor->blue)); + } + else if (outline > 0.0f) { + RECT outl1(d3drect2); + outl1.left -= outline; + outl1.right -= outline; + CNewFonts::gShadow = true; + m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &outl1, format, D3DCOLOR_ARGB(dropColor->alpha, + dropColor->red, dropColor->green, dropColor->blue)); + RECT outl2(d3drect2); + outl2.left += outline; + outl2.right += outline; + CNewFonts::gShadow = true; + m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &outl2, format, D3DCOLOR_ARGB(dropColor->alpha, + dropColor->red, dropColor->green, dropColor->blue)); + RECT outl3(d3drect2); + outl3.top -= outline; + outl3.bottom -= outline; + CNewFonts::gShadow = true; + m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &outl3, format, D3DCOLOR_ARGB(dropColor->alpha, + dropColor->red, dropColor->green, dropColor->blue)); + RECT outl4(d3drect2); + outl4.top += outline; + outl4.bottom += outline; + CNewFonts::gShadow = true; + m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &outl4, format, D3DCOLOR_ARGB(dropColor->alpha, + dropColor->red, dropColor->green, dropColor->blue)); + } + CNewFonts::gNumLetters = 0; + CNewFonts::gShadow = false; + m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &d3drect2, format, D3DCOLOR_ARGB(color.alpha, + color.red, color.green, color.blue)); + CNewFonts::m_pFontSprite->SetTransform(&P); + CNewFonts::m_pFontSprite->End(); +} + +void CNewFont::DrawRect(char *text, CRect const& rect, float scale_x, float scale_y, DWORD format, CRGBA const& backgroundColor) { + float x2 = rect.m_fRight; + RECT d3drect; SetRect(&d3drect, rect.m_fLeft, rect.m_fTop, rect.m_fRight, rect.m_fBottom); + RECT d3drect2; SetRect(&d3drect2, d3drect.left / (scale_x / 2), d3drect.top / (scale_y / 2), d3drect.right / (scale_x / 2), d3drect.bottom / (scale_y / 2)); + D3DXMATRIX S, P; + D3DXMatrixScaling(&S, scale_x / 2, scale_y / 2, 1.0f); + CNewFonts::m_pFontSprite->GetTransform(&P); + CNewFonts::m_pFontSprite->SetTransform(&S); + CNewFonts::m_pFontSprite->Begin(0); + this->m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, text, -1, &d3drect2, format | DT_CALCRECT, 0xFFFFFFFF); + CNewFonts::m_pFontSprite->SetTransform(&P); + CNewFonts::m_pFontSprite->End(); + CSprite2d::DrawRect(CRect(d3drect2.left*(scale_x / 2) - 8, d3drect2.top*(scale_y / 2) - 8, x2 + 8, d3drect2.bottom*(scale_y / 2) + 8), backgroundColor); +} + +void CNewFont::ReleaseFont() { + if (this->m_pD3DXFont) { + this->m_pD3DXFont->Release(); + this->m_pD3DXFont = NULL; + } +} + +void CNewFont::OnLost() { + ReleaseFont(); +} + +void CNewFont::OnReset() { + D3DXCreateFont(CNewFonts::GetCurrentDevice(), m_width, m_height, m_weight, 0, m_italic, m_charSet, m_outputPrecision, m_quality, + m_pitchAndFamily, m_fontName, &this->m_pD3DXFont); +} + +float __declspec(naked) _GetWidth() { + __asm add esp, 0x198 + __asm jmp CNewFonts::GetStringWidth +} + +void CNewFonts::Initialise() { + char app[8]; + char fontName[256]; + char scaleFactorStr[16]; + char translation[16]; + unsigned int fontId; + int width; + unsigned int height; + float scaleX; + float scaleY; + unsigned int weight; + bool italic; + unsigned int charSet; + unsigned int outputPrecision; + unsigned int quality; + unsigned int pitchAndFamily; + bool upperCase; + bool replaceUS; + for (int i = 0; i < MAX_NUM_FONTS; i++) { + sprintf(app, "FONT%d", i + 1); + GetPrivateProfileString(app, "FontName", "USE_DEFAULT", fontName, 256, PLUGIN_PATH("directFont.ini")); + if (!strcmp(fontName, "USE_DEFAULT")) { + m_aFonts[i].m_initialised = false; + continue; + } + if (!strncmp(fontName, "USE_FONT", 8)) { + if (!i) { + Error("CNewFonts::Initialise\nCan't apply USE_FONT to first font."); + m_aFonts[i].m_initialised = false; + continue; + } + sscanf(fontName, "USE_FONT%d", &fontId); + if (fontId > MAX_NUM_FONTS) { + Error("CNewFonts::Initialise\nUnknown font used with USE_FONT construction."); + m_aFonts[i].m_initialised = false; + continue; + } + if (fontId == i) { + Error("CNewFonts::Initialise\nCan't apply USE_FONT to this font."); + m_aFonts[i].m_initialised = false; + continue; + } + m_aFonts[i].SetupFont(m_aFonts[fontId].m_fontName, m_aFonts[fontId].m_width, m_aFonts[fontId].m_height, m_aFonts[fontId].m_scaleX, + m_aFonts[fontId].m_scaleY, m_aFonts[fontId].m_weight, m_aFonts[fontId].m_italic, m_aFonts[fontId].m_charSet, + m_aFonts[fontId].m_outputPrecision, m_aFonts[fontId].m_quality, m_aFonts[fontId].m_pitchAndFamily, m_aFonts[fontId].m_upperCase, + m_aFonts[fontId].m_replaceUS); + } + else { + height = GetPrivateProfileInt(app, "Height", 64, PLUGIN_PATH("directFont.ini")); + width = GetPrivateProfileInt(app, "Width", 40, PLUGIN_PATH("directFont.ini")); + GetPrivateProfileString(app, "ScaleFactor.x", "0.6", scaleFactorStr, 16, PLUGIN_PATH("directFont.ini")); + sscanf(scaleFactorStr, "%f", &scaleX); + GetPrivateProfileString(app, "ScaleFactor.y", "0.4", scaleFactorStr, 16, PLUGIN_PATH("directFont.ini")); + sscanf(scaleFactorStr, "%f", &scaleY); + weight = GetPrivateProfileInt(app, "Weight", 500, PLUGIN_PATH("directFont.ini")); + italic = GetPrivateProfileInt(app, "Italic", 0, PLUGIN_PATH("directFont.ini")); + charSet = GetPrivateProfileInt(app, "CharSet", 1, PLUGIN_PATH("directFont.ini")); + outputPrecision = GetPrivateProfileInt(app, "OutputPrecision", 0, PLUGIN_PATH("directFont.ini")); + quality = GetPrivateProfileInt(app, "Quality", 0, PLUGIN_PATH("directFont.ini")); + pitchAndFamily = GetPrivateProfileInt(app, "PitchAndFamily", 0, PLUGIN_PATH("directFont.ini")); + upperCase = GetPrivateProfileInt(app, "UpcaseAlways", 0, PLUGIN_PATH("directFont.ini")); + replaceUS = GetPrivateProfileInt(app, "ReplaceUnderscoreWithSpace", 0, PLUGIN_PATH("directFont.ini")); + m_aFonts[i].SetupFont(fontName, width, height, scaleX, scaleY, weight, italic, charSet, outputPrecision, quality, pitchAndFamily, + upperCase, replaceUS); + } + } + GetPrivateProfileString("GENERAL", "UseTranslator", "NONE", translation, 16, PLUGIN_PATH("directFont.ini")); + if (!strncmp(translation, "NONE", 4)) + m_Translation = TRANSLATION_NONE; + else if (!strncmp(translation, "SANLTD", 6)) + m_Translation = TRANSLATION_SANLTD; + else { + Error("CNewFonts::Initialise\nUnknown translation name."); + m_Translation = TRANSLATION_NONE; + } + patch::RedirectJump(0x71A700, PrintString); + patch::RedirectJump(0x71A0E6, _GetWidth); + patch::SetChar(0x58DCEF, '*'); + patch::RedirectJump(0x719490, SetFontStyle); + m_pFontSprite = new CD3DSprite; +} + +void CNewFonts::Reset() { + for (int i = 0; i < MAX_NUM_FONTS; i++) { + if (m_aFonts[i].m_initialised) + m_aFonts[i].OnReset(); + } + if (m_pFontSprite) + m_pFontSprite->OnResetDevice(); +} + +void CNewFonts::Lost() { + for (int i = 0; i < MAX_NUM_FONTS; i++) { + if (m_aFonts[i].m_initialised) + m_aFonts[i].OnLost(); + } + if (m_pFontSprite) + m_pFontSprite->OnLostDevice(); +} + +void CNewFonts::Shutdown() { + for (int i = 0; i < MAX_NUM_FONTS; i++) { + if (m_aFonts[i].m_initialised) + m_aFonts[i].ReleaseFont(); + } + delete m_pFontSprite; +} + +IDirect3DDevice9 *CNewFonts::GetCurrentDevice() { + return _RwD3DDevice; +} + +void _UpCase(unsigned char *str) { + unsigned char *pStr = str; + while (*pStr) { + if ((*pStr >= 97 && *pStr <= 122) || (*pStr >= 224 && *pStr <= 255)) + *pStr = *pStr - 32; + else if (*pStr == 183) + *pStr = 167; + pStr++; + } +} + +void ReplaceUsWithSpace(unsigned char *str) { + unsigned char *pStr = str; + while (*pStr) { + if (*pStr == '_') + *pStr = ' '; + pStr++; + } +} + +void CNewFonts::PrintString(float x, float y, char *text) { + if (m_aFonts[m_FontId].m_initialised) { + static char taggedText[MAX_TEXT_SIZE]; + CRect *rect; + unsigned int flag; + if (CFont::m_bFontCentreAlign) { + rect = &CRect(x - CFont::m_fFontCentreSize / 2, y, x + CFont::m_fFontCentreSize / 2, SCREEN_HEIGHT); + flag = DT_CENTER; + } + else if (CFont::m_bFontRightAlign) { + rect = &CRect(CFont::m_fRightJustifyWrap, y, x, SCREEN_HEIGHT); + flag = DT_RIGHT; + } + else { + rect = &CRect(x, y, CFont::m_fWrapx, SCREEN_HEIGHT); + flag = DT_LEFT; + } + ProcessTags(taggedText, text); + if (m_Translation == TRANSLATION_SANLTD) { + SanLtdTranslation tr; + tr.TranslateString(taggedText); + } + if (m_aFonts[m_FontId].m_upperCase) + _UpCase((unsigned char *)taggedText); + if (m_aFonts[m_FontId].m_replaceUS) + ReplaceUsWithSpace((unsigned char *)taggedText); + m_aFonts[m_FontId].PrintString(taggedText, *rect, CFont::m_Scale->x * m_aFonts[m_FontId].m_scaleX, + CFont::m_Scale->y * m_aFonts[m_FontId].m_scaleY, *CFont::m_Color, + DT_TOP | DT_NOCLIP | DT_WORDBREAK | flag, CFont::m_bFontBackground ? CFont::m_FontBackgroundColor : NULL, + CFont::m_nFontShadow * 2, CFont::m_nFontOutlineSize * 2, CFont::m_FontDropColor); + } + else + CFont::PrintString(x, y, text); +} + +HRESULT CD3DSprite::Draw(LPDIRECT3DTEXTURE9 pTexture, CONST RECT * pSrcRect, CONST D3DXVECTOR3 * pCenter, + CONST D3DXVECTOR3 * pPosition, D3DCOLOR Color) +{ + HRESULT result; + if (CNewFonts::gShadow) + result = m_pSprite->Draw(pTexture, pSrcRect, pCenter, pPosition, Color); + else { + result = m_pSprite->Draw(pTexture, pSrcRect, pCenter, pPosition, D3DCOLOR_RGBA(CNewFonts::gLetterColors[CNewFonts::gNumLetters].red, + CNewFonts::gLetterColors[CNewFonts::gNumLetters].green, CNewFonts::gLetterColors[CNewFonts::gNumLetters].blue, + CNewFonts::gLetterColors[CNewFonts::gNumLetters].alpha)); + CNewFonts::gNumLetters++; + } + return result; +} + +void CNewFonts::ProcessTags(char *dest, char *src) { + bool bBreak = false; + static char text[MAX_TEXT_SIZE]; + char *pDest = dest; + char *pText = text; + strcpy_s(text, src); + CMessages::InsertPlayerControlKeysInString(text); + CRGBA currColor(*CFont::m_Color); + unsigned int numLetters = 0; + while (true) { + // if string was finished + if (!*pText) + break; + // if we found a tag + if (*pText == '~') { + // process tag + pText++; + // if string was finished + if (!*pText) + break; + // if new line tag + switch (*pText) { + case 'N': + case 'n': + *pDest = '\n'; + pDest++; + pText++; + break; + case 'R': + case 'r': + currColor = CRGBA(HudColour.GetRGB(0, CFont::m_Color->alpha)); + pText++; + break; + case 'G': + case 'g': + currColor = CRGBA(HudColour.GetRGB(1, CFont::m_Color->alpha)); + pText++; + break; + case 'B': + case 'b': + currColor = CRGBA(HudColour.GetRGB(2, CFont::m_Color->alpha)); + pText++; + break; + case 'W': + case 'w': + currColor = CRGBA(HudColour.GetRGB(4, CFont::m_Color->alpha)); + pText++; + break; + case 'H': + case 'h': + currColor = CRGBA(min((float)CFont::m_Color->red * 1.5f, 255.0f), + min((float)CFont::m_Color->green * 1.5f, 255.0f), + min((float)CFont::m_Color->blue * 1.5f, 255.0f), + CFont::m_Color->alpha); + pText++; + break; + case 'Y': + case 'y': + currColor = CRGBA(HudColour.GetRGB(11, CFont::m_Color->alpha)); + pText++; + break; + case 'P': + case 'p': + currColor = CRGBA(HudColour.GetRGB(7, CFont::m_Color->alpha)); + pText++; + break; + case 'l': + currColor = CRGBA(HudColour.GetRGB(5, CFont::m_Color->alpha)); + pText++; + break; + case 'S': + case 's': + currColor = CRGBA(HudColour.GetRGB(4, CFont::m_Color->alpha)); + pText++; + break; + } + // close tag + while (*pText != '~') { + if (!pText) { + *pDest = '\0'; + return; + } + pText++; + } + pText++; + } + else { + *pDest = *pText; + if (*pText != ' ') { + gLetterColors[numLetters] = currColor; + numLetters++; + } + pDest++; + pText++; + } + } + *pDest = '\0'; +} + +float CNewFonts::GetStringWidth(char *str, char bFull, char bScriptText) { + if (m_aFonts[m_FontId].m_initialised) { + static char text[MAX_TEXT_SIZE]; + static char taggedText[MAX_TEXT_SIZE]; + char *pText = taggedText; + strncpy(text, str, CMessages::GetStringLength(str)); + CNewFonts::ProcessTags(taggedText, text); + if (!bFull) + { + while (*pText && *pText != ' ') + pText++; + *pText = '\0'; + } + return CNewFonts::m_aFonts[m_FontId].GetStringWidth(taggedText); + } + else + return CFont::GetStringWidth(str, bFull, bScriptText); +} + +float CNewFont::GetStringWidth(char *str) { + float scale_x = CFont::m_Scale->x * m_scaleX; + float scale_y = CFont::m_Scale->y * m_scaleY; + RECT d3drect; SetRect(&d3drect, 0, 0, 0, 0); + D3DXMATRIX S, P; + D3DXMatrixScaling(&S, scale_x / 2, scale_y / 2, 1.0f); + CNewFonts::m_pFontSprite->GetTransform(&P); + CNewFonts::m_pFontSprite->SetTransform(&S); + CNewFonts::m_pFontSprite->Begin(0); + this->m_pD3DXFont->DrawText(CNewFonts::m_pFontSprite, str, -1, &d3drect, DT_TOP | DT_NOCLIP | DT_SINGLELINE | DT_CALCRECT, 0xFFFFFFFF); + CNewFonts::m_pFontSprite->SetTransform(&P); + CNewFonts::m_pFontSprite->End(); + return (d3drect.right - d3drect.left) * (scale_x / 2); +} + +void CNewFonts::SetFontStyle(eFontStyle style) { + m_FontId = style; + if (style == 2) { + CFont::m_FontTextureId = 0; + CFont::m_FontStyle = 2; + } + else if (style == 3) { + CFont::m_FontTextureId = 1; + CFont::m_FontStyle = 1; + } + else { + CFont::m_FontTextureId = style; + CFont::m_FontStyle = 0; + CFont::m_FontStyle = 0; + } +} \ No newline at end of file diff --git a/directFont/CNewFonts.h b/directFont/CNewFonts.h new file mode 100644 index 0000000..c0cd7f1 --- /dev/null +++ b/directFont/CNewFonts.h @@ -0,0 +1,63 @@ +#pragma once +#include "d3dx9.h" +#include "game_sa\CRect.h" +#include "game_sa\CRGBA.h" +#include "game_sa\CFont.h" +#include "CD3DSprite.h" + +#define MAX_NUM_FONTS 4 +#define MAX_TEXT_SIZE 2048 + +enum eTranslation { + TRANSLATION_NONE = 0, + TRANSLATION_SANLTD = 1 +}; + +class CNewFont { + ID3DXFont *m_pD3DXFont; +public: + char m_fontName[128]; + int m_width; + unsigned int m_height; + unsigned int m_weight; + float m_scaleX; + float m_scaleY; + bool m_italic; + unsigned int m_charSet; + unsigned int m_outputPrecision; + unsigned int m_quality; + unsigned int m_pitchAndFamily; + bool m_upperCase; + bool m_replaceUS; + bool m_initialised; + bool SetupFont(char *fontName, unsigned int width, int height, float scaleX, float scaleY, unsigned int weight, bool italic, + unsigned int charSet, unsigned int outputPrecision, unsigned int quality, unsigned int pitchAndFamily, bool upperCase, bool replaceUS); + void PrintString(char *text, CRect const& rect, float scale_x, float scale_y, CRGBA const& color, DWORD format, + CRGBA const* backgroundColor, float shadow, float outline, CRGBA const* dropColor); + void DrawRect(char *text, CRect const& rect, float scale_x, float scale_y, DWORD format, CRGBA const& backgroundColor); + void ReleaseFont(); + void OnLost(); + void OnReset(); + float GetStringWidth(char *str); +}; + +class CNewFonts { +public: + static eFontStyle m_FontId; + static CD3DSprite *m_pFontSprite; + static CNewFont m_aFonts[MAX_NUM_FONTS]; + static eTranslation m_Translation; + static CRGBA gLetterColors[MAX_TEXT_SIZE]; + static unsigned int gNumLetters; + static bool gShadow; + + static IDirect3DDevice9 *GetCurrentDevice(); + static void Initialise(); + static void Shutdown(); + static void Lost(); + static void Reset(); + static void SetFontStyle(eFontStyle style); + static void PrintString(float x, float y, char *text); + static void ProcessTags(char *dest, char *src); + static float GetStringWidth(char *str, char bFull, char bScriptText); +}; \ No newline at end of file diff --git a/directFont/Main.cpp b/directFont/Main.cpp new file mode 100644 index 0000000..4dd4df2 --- /dev/null +++ b/directFont/Main.cpp @@ -0,0 +1,15 @@ +#include +#include "plugin.h" +#include "CNewFonts.h" + +using namespace plugin; + +class DirectFontPlugin { +public: + DirectFontPlugin() { + Events::initRwEvent += CNewFonts::Initialise; + Events::shutdownRwEvent += CNewFonts::Shutdown; + Events::d3dLostEvent += CNewFonts::Lost; + Events::d3dResetEvent += CNewFonts::Reset; + } +} directFontPlg; \ No newline at end of file diff --git a/directFont/directFont.vcxproj b/directFont/directFont.vcxproj new file mode 100644 index 0000000..5e69970 --- /dev/null +++ b/directFont/directFont.vcxproj @@ -0,0 +1,182 @@ + + + + + Dbg-XP + Win32 + + + Dbg + Win32 + + + Rel-XP + Win32 + + + Rel + Win32 + + + + {ff630438-a5ea-4612-a843-77cb56888722} + directFont + 8.1 + + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + true + v140_xp + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + DynamicLibrary + false + v140_xp + true + MultiByte + + + + + + + + + + + + + + + + + + + + + .asi + D:\Games\Grand Theft Auto - San Andreas\scripts\ + + + .asi + D:\Games\Grand Theft Auto - San Andreas\scripts\ + + + .asi + D:\Games\Grand Theft Auto - San Andreas\scripts\ + $(ProjectName)_d + + + .asi + D:\Games\Grand Theft Auto - San Andreas\scripts\ + $(ProjectName)_d + + + + Level3 + Disabled + true + D:\Projects\plugin-sdk\plugin_sa\;%(AdditionalIncludeDirectories) + MultiThreadedDebug + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + D:\Projects\plugin-sdk\output\lib\plugin_sa\Debug\;%(AdditionalLibraryDirectories) + plugin_d.lib;%(AdditionalDependencies) + Default + Debug + + + + + Level1 + Disabled + false + D:\Projects\plugin-sdk\plugin_sa\;D:\Projects\DXSDK\9.0c\Include;%(AdditionalIncludeDirectories) + MultiThreadedDebug + /Zc:threadSafeInit- %(AdditionalOptions) + _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;_D3D_INCLUDE;%(PreprocessorDefinitions) + Default + false + + + D:\Projects\plugin-sdk\output\lib\plugin_sa\Debug\;D:\Projects\DXSDK\9.0c\Lib\x86;%(AdditionalLibraryDirectories) + plugin_d.lib;d3d9.lib;d3dx9.lib;%(AdditionalDependencies) + Default + Debug + Windows + + + + + Level3 + MaxSpeed + true + true + true + MultiThreaded + D:\Projects\plugin-sdk\plugin_sa\;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + No + UseLinkTimeCodeGeneration + D:\Projects\plugin-sdk\output\lib\plugin_sa\Release\;%(AdditionalLibraryDirectories) + plugin.lib;%(AdditionalDependencies) + + + + + Level1 + MaxSpeed + true + true + true + MultiThreaded + D:\Projects\plugin-sdk\plugin_sa\;D:\Projects\DXSDK\9.0c\Include;%(AdditionalIncludeDirectories) + _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;_D3D_INCLUDE;%(PreprocessorDefinitions) + /Zc:threadSafeInit- %(AdditionalOptions) + + + true + true + No + UseLinkTimeCodeGeneration + D:\Projects\plugin-sdk\output\lib\plugin_sa\Release\;D:\Projects\DXSDK\9.0c\Lib\x86;%(AdditionalLibraryDirectories) + plugin.lib;d3d9.lib;d3dx9.lib;%(AdditionalDependencies) + Windows + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/directFont/directFont.vcxproj.filters b/directFont/directFont.vcxproj.filters new file mode 100644 index 0000000..7ed5fd6 --- /dev/null +++ b/directFont/directFont.vcxproj.filters @@ -0,0 +1,26 @@ + + + + + + + + translations + + + + + + + translations + + + translations + + + + + {6af7e0a6-5f85-4733-80f3-44f7badefe55} + + + \ No newline at end of file diff --git a/directFont/translations/BaseTranslation.h b/directFont/translations/BaseTranslation.h new file mode 100644 index 0000000..f3cdfc2 --- /dev/null +++ b/directFont/translations/BaseTranslation.h @@ -0,0 +1,5 @@ +#pragma once + +class BaseTranslation { + virtual void TranslateString(char *str) = 0; +}; \ No newline at end of file diff --git a/directFont/translations/SanLtdTranslation.cpp b/directFont/translations/SanLtdTranslation.cpp new file mode 100644 index 0000000..7b548f2 --- /dev/null +++ b/directFont/translations/SanLtdTranslation.cpp @@ -0,0 +1,205 @@ +#include "SanLtdTranslation.h" + +void SanLtdTranslation::TranslateString(char *str) { + char *pText = str; + while (*pText) { + switch (*pText) { + case 'A': + *pText = ''; + break; + case 'a': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case 'E': + *pText = ''; + break; + case 'e': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case 'K': + *pText = ''; + break; + case 'k': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '\xAD': + *pText = ''; + break; + case '': + *pText = ''; + break; + case 'O': + *pText = ''; + break; + case 'o': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case 'P': + *pText = ''; + break; + case 'p': + *pText = ''; + break; + case 'C': + *pText = ''; + break; + case 'c': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case 'Y': + *pText = ''; + break; + case 'y': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '\x98': + *pText = ''; + break; + case 'X': + *pText = ''; + break; + case 'x': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '\xA0': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + case '': + *pText = ''; + break; + } + pText++; + } +} \ No newline at end of file diff --git a/directFont/translations/SanLtdTranslation.h b/directFont/translations/SanLtdTranslation.h new file mode 100644 index 0000000..be49ee5 --- /dev/null +++ b/directFont/translations/SanLtdTranslation.h @@ -0,0 +1,8 @@ +#pragma once + +#include "BaseTranslation.h" + +class SanLtdTranslation { +public: + void TranslateString(char *str); +}; \ No newline at end of file