Dillinger98
Posts: 2
Joined: Mon Feb 25, 2019 8:57 pm
PC Specification: i5-2400, GTX 960, Windows 10 LTSC

Subtitles Issue

Mon Feb 25, 2019 9:04 pm

So, I love your player to the point that it's become almost impossible for me to watch anything without it. But about 80% of the time, I have an issue with subtitles where "0,Default,,0,0,0,," is displayed before the actual subtitles. Like in this screenshot:
Subtitles.jpg
Subtitles.jpg (107 KiB) Viewed 30914 times

Piotr
Posts: 1472
Joined: Mon Jan 02, 2017 11:20 am
PC Specification: i7-6700, 16GB RAM, GTX 1070

Re: Subtitles Issue

Tue Feb 26, 2019 7:11 am

Please provide us a MediaInfo report of your file. To do this please download (it's free) MediaInfo from here: http://mediaarea.net/en/MediaInfo. Once you have installed MediaInfo please go to your file location and right-click on it. Select MediaInfo. A new Windows with basic information should pop-up. Below you can find more information. Click the button and select "Tree" option. Advanced information will be displayed. Please export the report or simply create a screenshot of your Tree view.
Follow us on Twitter:
http://twitter.com/MirillisTeam
Find us on Facebook:
http://www.facebook.com/Mirillis

Dillinger98
Posts: 2
Joined: Mon Feb 25, 2019 8:57 pm
PC Specification: i5-2400, GTX 960, Windows 10 LTSC

Re: Subtitles Issue

Tue Feb 26, 2019 12:13 pm

Here's the export:

General
Unique ID : 83909131025092312661642662852329734892 (0x3F204F90E8801E40BB8778655BA802EC)
Complete name : D:\TV\Anime\The Disastrous Life of Saiki K 2\[DB]The Disastrous Life of Saiki K 2_-_01_(10bit_BD1080p_x265).mkv
Format : Matroska
Format version : Version 2
File size : 199 MiB
Duration : 23 min 50 s
Overall bit rate : 1 164 kb/s
Encoded date : UTC 2019-01-01 19:55:06
Writing application : mkvmerge v28.1.0 ('Morning Child') 64-bit
Writing library : libebml v1.3.6 + libmatroska v1.4.9
Attachments : AldotheApache.ttf / ARLRDBD.TTF / Aroha.otf / augie.ttf / Bleeding Cowboys.ttf / CHERI__.TTF / CREABBB.TTF / CREABBRG.TTF / Dimbo Regular.ttf / Drawing with markers.ttf / Erase Old Year.ttf / Fontin_Sans_0.otf / Fontin_Sans_BI.ttf / FRABK.TTF / framd.ttf / framdit.ttf / FromWhereYouAre.ttf / HappyNewYear2016.ttf / KLEPTO_.TTF / LeviReBrushed.ttf / ObelixPro-cyr.ttf / Odin Rounded - Bold.otf / OldSansBlack.ttf / olivier_demo.ttf / Outrun future Bold.otf / Outrun future.otf / palab.ttf / PWChalk.ttf / Sassy Molassy.ttf / SHOWG.TTF / TektonPro-BoldExt.otf / Youthanasia_X.ttf

Video
ID : 1
Format : HEVC
Format/Info : High Efficiency Video Coding
Format profile : Main 10@L4@Main
Codec ID : V_MPEGH/ISO/HEVC
Duration : 23 min 50 s
Bit rate : 970 kb/s
Width : 1 920 pixels
Height : 1 080 pixels
Display aspect ratio : 16:9
Frame rate mode : Constant
Frame rate : 23.976 (24000/1001) FPS
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 10 bits
Bits/(Pixel*Frame) : 0.020
Stream size : 165 MiB (83%)
Writing library : x265 2.8+74-fd517ae68f93:[Windows][GCC 8.2.0][64 bit] 10bit
Encoding settings : cpuid=1111039 / frame-threads=3 / numa-pools=8 / wpp / no-pmode / no-pme / no-psnr / no-ssim / log-level=2 / input-csp=1 / input-res=1920x1080 / interlace=0 / total-frames=34286 / level-idc=0 / high-tier=1 / uhd-bd=0 / ref=3 / no-allow-non-conformance / no-repeat-headers / annexb / no-aud / no-hrd / info / hash=0 / no-temporal-layers / open-gop / min-keyint=23 / keyint=250 / gop-lookahead=0 / bframes=4 / b-adapt=2 / b-pyramid / bframe-bias=0 / rc-lookahead=20 / lookahead-slices=6 / scenecut=40 / radl=0 / no-intra-refresh / ctu=64 / min-cu-size=8 / no-rect / no-amp / max-tu-size=32 / tu-inter-depth=1 / tu-intra-depth=1 / limit-tu=0 / rdoq-level=0 / dynamic-rd=0.00 / no-ssim-rd / signhide / no-tskip / nr-intra=0 / nr-inter=0 / no-constrained-intra / strong-intra-smoothing / max-merge=2 / limit-refs=3 / no-limit-modes / me=1 / subme=2 / merange=57 / temporal-mvp / weightp / no-weightb / no-analyze-src-pics / deblock=0:0 / sao / no-sao-non-deblock / rd=3 / no-early-skip / rskip / no-fast-intra / no-tskip-fast / no-cu-lossless / no-b-intra / no-splitrd-skip / rdpenalty=0 / psy-rd=2.00 / psy-rdoq=0.00 / no-rd-refine / no-lossless / cbqpoffs=0 / crqpoffs=0 / rc=crf / crf=21.0 / qcomp=0.60 / qpstep=4 / stats-write=0 / stats-read=0 / ipratio=1.40 / pbratio=1.30 / aq-mode=1 / aq-strength=1.00 / cutree / zone-count=0 / no-strict-cbr / qg-size=32 / no-rc-grain / qpmax=69 / qpmin=0 / no-const-vbv / sar=1 / overscan=0 / videoformat=5 / range=0 / colorprim=2 / transfer=2 / colormatrix=2 / chromaloc=0 / display-window=0 / max-cll=0,0 / min-luma=0 / max-luma=1023 / log2-max-poc-lsb=8 / vui-timing-info / vui-hrd-info / slices=1 / no-opt-qp-pps / no-opt-ref-list-length-pps / no-multi-pass-opt-rps / scenecut-bias=0.05 / no-opt-cu-delta-qp / no-aq-motion / no-hdr / no-hdr-opt / no-dhdr10-opt / no-idr-recovery-sei / analysis-reuse-level=5 / scale-factor=0 / refine-intra=0 / refine-inter=0 / refine-mv=0 / no-limit-sao / ctu-info=0 / no-lowpass-dct / refine-mv-type=0 / copy-pic=1 / max-ausize-factor=1.0 / no-dynamic-refine / no-single-sei
Default : Yes
Forced : No

Audio
ID : 2
Format : AAC LC
Format/Info : Advanced Audio Codec Low Complexity
Codec ID : A_AAC-2
Duration : 23 min 50 s
Bit rate : 132 kb/s
Channel(s) : 2 channels
Channel layout : L R
Sampling rate : 48.0 kHz
Frame rate : 46.875 FPS (1024 SPF)
Compression mode : Lossy
Delay relative to video : 9 ms
Stream size : 22.8 MiB (11%)
Language : Japanese
Default : Yes
Forced : No

Text #1
ID : 3
Format : ASS
Codec ID : S_TEXT/ASS
Codec ID/Info : Advanced Sub Station Alpha
Duration : 23 min 46 s
Bit rate : 19.2 kb/s
Count of elements : 10479
Compression mode : Lossless
Stream size : 3.26 MiB (2%)
Title : English
Language : English
Default : Yes
Forced : No

Text #2
ID : 4
Format : ASS
Codec ID : S_TEXT/ASS
Codec ID/Info : Advanced Sub Station Alpha
Duration : 23 min 46 s
Bit rate : 19.2 kb/s
Count of elements : 10476
Compression mode : Lossless
Stream size : 3.26 MiB (2%)
Title : English (JP Honorifics)
Language : English
Default : No
Forced : No

Menu
00:00:00.000 : en:OP
00:01:30.006 : en:Restarting! Everyday life, "As Usual"
00:05:34.959 : en:Another Christmas Challenge!
00:09:45.043 : en:First Experiences of the Year Are Important
00:13:50.038 : en:Courtside Love Game
00:18:00.079 : en:Dessert Buffet Disaster
00:22:05.032 : en:ED
00:23:34.997 : en:Preview

jlnsrk
Posts: 5
Joined: Mon Dec 25, 2017 4:44 am
PC Specification: AMD RYZEN 1700

Re: Subtitles Issue

Fri Nov 08, 2019 1:00 am

The Problem seems to be that Splash doesn't detect the Advanced SSA format for subtitles from within the mkv container, and instead treats the attached information as a standard text file which then results in additional information available being shown as text.

jlnsrk
Posts: 5
Joined: Mon Dec 25, 2017 4:44 am
PC Specification: AMD RYZEN 1700

Subtitle Fix

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.

noobbox
Posts: 1
Joined: Sun Dec 22, 2019 11:39 am
PC Specification: Windows 7

Re: Subtitles Issue

Sun Dec 22, 2019 1:07 pm

Hello, I'm having the same issue.
My solution was to extract the subtitles from the MKV and remove all the styles

Miruzu
Posts: 1
Joined: Sun Mar 15, 2020 8:25 pm
PC Specification: i5 4690, Radeon RX 480, Win 10

Re: Subtitles Issue

Sun Mar 15, 2020 8:29 pm

Also in the same boat, don't want to stop using Splash, could I get some help with fixing this annoyance?

elswordx
Posts: 1
Joined: Fri Aug 07, 2020 9:29 am
PC Specification: its aight

Re: Subtitle Fix

Fri Aug 07, 2020 9:33 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.
how would you use this code? I was able to export the subtitles and clean/convert them to srt as the other guy suggested but it's really cumbersome

hooke007
Posts: 2
Joined: Mon Jul 13, 2020 5:18 am
PC Specification: win10-RTX2070s-Adobe_rgb_display

Re: Subtitles Issue

Fri Aug 14, 2020 5:14 pm

It seems that splash does not support the Advanced ssa/ass format's subs.

KimuraKhen
Posts: 1
Joined: Thu Nov 12, 2020 11:18 pm
PC Specification: i3 3440 gtx 750ti

Re: Subtitle Fix

Fri Nov 13, 2020 1:13 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.
pls tell me how to use it, or where download the tool/plugin

Return to “Splash 2.0”

Who is online

Users browsing this forum: No registered users and 2 guests