impreza0109
Posts: 1
Joined: Mon Dec 14, 2020 6:03 am
PC Specification: i5 3570k, RTX 2070 Super, W10

Re: Subtitle Fix

Sun Dec 20, 2020 7:10 am

jlnsrk wrote:
Fri Nov 08, 2019 5:08 pm
Hello Mirillis Team,

so I have been having an issue with Splash Player for quite some time now. The subtitles of some Anime would not be shown properly. To remedy this I made a plugin for your tool whose effect can be seen in the following attachments.

Before:
Image

After:
Image

I would like to make my tool available to other people in binary form, however I understand that Splash Player is 100% the property of Mirillis and hence I would like to ask your permission before I do this to prevent any kind of issue from occurring from me having done this work.

I am attaching this code in case you guys would like to review it.

Code: Select all

#include <Windows.h>
#include <TlHelp32.h>
#include <intrin.h>

typedef int (__cdecl* Type_InitSubtitleFont)( wchar_t *Str, int, int, int, int, int, int, int, int );
Type_InitSubtitleFont pInitSubtitleFont;

int __cdecl hkInitSubtitleFont( wchar_t *Str, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8 ) // D3D12
{
	int Len = wcslen( Str );
	
	int SkipIndex = 0;
	
	for( size_t i = 0, j = 7; i < Len && j > 0; i++ )
	{
		if( Str[i] == ',' )
		{
			if( j < 2 )
			{
				SkipIndex = i + 1;
			}
			j--;
		}		
	}

	return pInitSubtitleFont( &Str[ SkipIndex ], a1, a2, a3, a4, a5, a6, a7, a8 );
}


typedef int( __cdecl* Type_RenderSubtitleLine )( HDC hdc, wchar_t* Str, int a3, int a4, int a5, int a6, int a7, int a8 );
Type_RenderSubtitleLine pRenderSubtitleLine;

int __cdecl hkRenderSubtitleLine( HDC hdc, wchar_t* Str, int a3, int a4, int a5, int a6, int a7, int a8 )// GDI
{
	int Len = wcslen( Str );

	int SkipIndex = 0;

	for( size_t i = 0, j = 7; i < Len && j > 0; i++ )
	{
		if( Str[ i ] == ',' )
		{
			if( j < 2 )
			{
				SkipIndex = i + 1;
			}
			j--;
		}
	}
	return pRenderSubtitleLine( hdc, &Str[ SkipIndex ], a3, a4, a5, a6, a7, a8 );
}

bool bDataCompare( const BYTE* pData, const BYTE* bMask, const char* szMask )
{
	for( ; *szMask; ++szMask, ++pData, ++bMask )
		if( *szMask == 'x' && *pData != *bMask )
			return false;
	return ( *szMask ) == NULL;
}

DWORD dwFindPattern( DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask )
{
	for( DWORD i = 0; i < dwLen; i++ )
		if( bDataCompare( ( BYTE* ) ( dwAddress + i ), bMask, szMask ) )
			return ( DWORD ) ( dwAddress + i );
	return NULL;
}

void *DetourFunc( BYTE *src, const BYTE *dst, const int len )
{
	BYTE *jmp = ( BYTE* ) VirtualAlloc( nullptr, len + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
	DWORD dwback;

	VirtualProtect( src, len, PAGE_READWRITE, &dwback );

	__movsb( jmp, src, len );
	
	jmp += len;

	jmp[ 0 ] = 0xE9;
	*( DWORD* ) ( jmp + 1 ) = ( DWORD ) ( src + len - jmp ) - 5;

	src[ 0 ] = 0xE9;
	*( DWORD* ) ( src + 1 ) = ( DWORD ) ( dst - src ) - 5;

	VirtualProtect( src, len, dwback, &dwback );

	return ( jmp - len );
}

DWORD __stdcall dwThread( void* )
{
	HMODULE hmModule = GetModuleHandle( nullptr );

	IMAGE_DOS_HEADER* pDosHeader = reinterpret_cast< IMAGE_DOS_HEADER* >( hmModule );

	if( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
	{
		MessageBoxA( 0, "Error 1", nullptr, 0 );
		return 0;
	}

	IMAGE_NT_HEADERS* pImageNtHeader = reinterpret_cast< IMAGE_NT_HEADERS* >( ( ( DWORD_PTR ) hmModule + pDosHeader->e_lfanew ) );

	if( pImageNtHeader->Signature != IMAGE_NT_SIGNATURE )
	{
		MessageBoxA( 0, "Error 2", nullptr, 0 );
		return 0;
	}

	DWORD dwSize = pImageNtHeader->OptionalHeader.SizeOfCode;
	DWORD dwStart = ( DWORD ) hmModule + pImageNtHeader->OptionalHeader.BaseOfCode;

	DWORD dwAddress = dwFindPattern( dwStart, dwSize, ( BYTE* ) "\x57\x56\x55\x53\x81\xEC\x00\x00\x00\x00\x8B\xB4\x24\x00\x00\x00\x00\xBB\x00\x00\x00\x00\x83\xFE\x00\x0F\x44\x9C\x24\x00\x00\x00\x00\x8D\x84\x24\x00\x00\x00\x00\x50", "xxxxxx????xxx????x????xxxxxxx????xxx????x" );

	if( !dwAddress )
	{
		MessageBoxA( 0, "Error 3", nullptr, 0 );
		return 0;
	}

	pInitSubtitleFont = ( Type_InitSubtitleFont ) DetourFunc( ( BYTE* ) dwAddress, ( BYTE* ) hkInitSubtitleFont, 0xA );

	if( !pInitSubtitleFont )
	{
		MessageBoxA( 0, "Error 4", nullptr, 0 );
		return 0;
	}
	//
	dwAddress = dwFindPattern( dwStart, dwSize, ( BYTE* ) "\x57\x56\x55\x53\x83\xEC\x4C\x8D\x04\x24\x50\xFF\x35\x00\x00\x00\x00", "xxxxxxxxxxxxx????" );

	if( !dwAddress )
	{
		MessageBoxA( 0, "Error 5", nullptr, 0 );
		return 0;
	}

	pRenderSubtitleLine = ( Type_RenderSubtitleLine ) DetourFunc( ( BYTE* ) dwAddress, ( BYTE* ) hkRenderSubtitleLine, 0x7 );

	if( !pRenderSubtitleLine )
	{
		MessageBoxA( 0, "Error 6", nullptr, 0 );
		return 0;
	}

	return 1;
}

extern "C" BOOL __declspec( dllexport ) __stdcall EnumProcesses( DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded )
{
	PROCESSENTRY32 pe32;
	HANDLE hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );

	if( hProcessSnap == INVALID_HANDLE_VALUE )
		return FALSE;

	pe32.dwSize = sizeof( PROCESSENTRY32 );

	DWORD dwNeeded;

	if( lpcbNeeded == nullptr )
	{
		lpcbNeeded = &dwNeeded;
	}

	*lpcbNeeded = 0;


	if( Process32First( hProcessSnap, &pe32 ) )
	{
		do
		{
			if( lpidProcess )
				lpidProcess[ *lpcbNeeded ] = pe32.th32ProcessID;

			*lpcbNeeded++;
		}
		while( cb / sizeof( DWORD ) > *lpcbNeeded );
	}

	return *lpcbNeeded > 0;
}

extern "C" DWORD __declspec( dllexport ) __stdcall GetModuleBaseNameW( HANDLE hProcess, HMODULE hModule, LPWSTR lpBaseName, DWORD nSize )
{
	MODULEENTRY32 me32;

	HANDLE hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, GetProcessId( hProcess ) );

	if( hProcessSnap == INVALID_HANDLE_VALUE )
		return 0;

	me32.dwSize = sizeof( MODULEENTRY32 );

	if( Module32First( hProcessSnap, &me32 ) )
	{
		do
		{
			if( me32.hModule == hModule || me32.modBaseAddr == ( BYTE* ) hModule )
			{
				lstrcpyW( lpBaseName, me32.szModule );
			}
		}
		while( Module32Next( hProcessSnap, &me32 ) );
	}

	return 0;
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		CreateThread( nullptr, 0, reinterpret_cast< LPTHREAD_START_ROUTINE >( &dwThread ), hModule, 0, nullptr );
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

Cheers.
Sorely need this feature to work as well

Saunders
Posts: 4
Joined: Tue Oct 12, 2021 2:11 pm
PC Specification: i5 4440, R9 290, 16GB ram Windows 10

Re: Subtitles Issue

Tue Oct 19, 2021 1:22 pm

I have identical problem. I get some random characters when these leathers appear: Č, Ć, Đ, Š, Ž
They are from "Serbian Latin" keyboard

gadstrikeph
Posts: 1
Joined: Mon Oct 21, 2024 5:43 am
PC Specification: Ryzen 5 5600X, RTX 3060, Win11

Re: Subtitles Issue

Mon Oct 21, 2024 5:46 am

Man. Am getting the same problem as well. Sorry to resurrect the thread. But really getting desperate on getting this issue fixed.

Return to “Splash 2.0”

Who is online

Users browsing this forum: No registered users and 5 guests