diff --git a/LunaTranslator/LunaTranslator/LunaTranslator.py b/LunaTranslator/LunaTranslator/LunaTranslator.py index 99149c2c..6c1c7289 100644 --- a/LunaTranslator/LunaTranslator/LunaTranslator.py +++ b/LunaTranslator/LunaTranslator/LunaTranslator.py @@ -147,14 +147,22 @@ class MAINUI() : return ss def textgetmethod(self,text,is_auto_run=True,embedcallback=None,onlytrans=False): _autolock(self.solvegottextlock) + needclear=True if onlytrans==False: self.currentsignature=time.time() if type(text)==str: - if text[:len('')]=='': + if text.startswith(''): self.translation_ui.displayres.emit('',globalconfig['rawtextcolor'],text[len(''):],onlytrans) self.currenttext=text self.currentread=text return + elif text.startswith(''): + length=len('') + idx=text.find('') + warningtext=text[length:idx] + text=text[idx+length+1:] + self.translation_ui.displaystatus.emit(warningtext,'red',True,False) + needclear=False else: msgs=[ ('',globalconfig['rawtextcolor'],False), @@ -226,11 +234,11 @@ class MAINUI() : print_exc() hira=[] if globalconfig['refresh_on_get_trans']==False: - self.translation_ui.displayraw1.emit(hira,text,globalconfig['rawtextcolor'] ,onlytrans) + self.translation_ui.displayraw1.emit(hira,text,globalconfig['rawtextcolor'] ,onlytrans,needclear) _showrawfunction=None _showrawfunction_sig=0 else: - _showrawfunction=functools.partial(self.translation_ui.displayraw1.emit,hira,text,globalconfig['rawtextcolor'],onlytrans ) + _showrawfunction=functools.partial(self.translation_ui.displayraw1.emit,hira,text,globalconfig['rawtextcolor'],onlytrans,needclear) _showrawfunction_sig=time.time() text_solved,optimization_params= self.solvebeforetrans(text) diff --git a/LunaTranslator/LunaTranslator/gui/rangeselect.py b/LunaTranslator/LunaTranslator/gui/rangeselect.py index 757c7bad..6cf2a6cc 100644 --- a/LunaTranslator/LunaTranslator/gui/rangeselect.py +++ b/LunaTranslator/LunaTranslator/gui/rangeselect.py @@ -1,5 +1,5 @@ from PyQt5.QtWidgets import QWidget,QDesktopWidget,QMainWindow,QLabel,QPushButton,QStatusBar,QDialog,QApplication -from PyQt5.QtGui import QBitmap,QPainter,QPen,QBrush,QFont,QMouseEvent,QCursor +from PyQt5.QtGui import QBitmap,QPainter,QPen,QColor,QFont,QMouseEvent,QCursor from PyQt5.QtCore import Qt,QPoint,QRect,QEvent,pyqtSignal import gobject @@ -64,10 +64,10 @@ class rangeselct(QMainWindow) : super(rangeselct, self).__init__(parent) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)#|Qt.WindowStaysOnTopHint ) + self.rectlabel=QLabel(self) + self.setAttribute(Qt.WA_TranslucentBackground) def reset(self): - self.setStyleSheet('''background-color:black; ''') - self.setWindowOpacity(globalconfig['OCR_mask_Opacity']) num_screens = QDesktopWidget().screenCount() x,y,x2,y2=9999,9999,0,0 for i in range(num_screens): @@ -77,14 +77,15 @@ class rangeselct(QMainWindow) : x2=max(x2,_rect.x()+_rect.width()) y2=max(y2,_rect.y()+_rect.height()) self.setGeometry(x,y,x2-x,y2-y) + self.rectlabel.setGeometry(x,y,x2-x,y2-y) self.setCursor(Qt.CrossCursor) - self.image=QApplication.primaryScreen().grabWindow(0,x,y,x2-x,y2-y) self.is_drawing = False self.setMouseTracking(True) self.start_point = QPoint() self.end_point = QPoint() self.startauto=False self.clickrelease=False + self.rectlabel.setStyleSheet(" border:%spx solid %s; background-color: rgba(0,0,0, 0.01)" %(globalconfig['ocrrangewidth'],globalconfig['ocrrangecolor'] )) def immediateend(self): try: @@ -98,20 +99,16 @@ class rangeselct(QMainWindow) : if self.is_drawing: pp = QPainter(self ) - pen = QPen() - pen.setStyle(Qt.NoPen) + pen = QPen(QColor(globalconfig['ocrrangecolor'])) + pen.setWidth(globalconfig['ocrrangewidth']) pp.setPen(pen) - brush = QBrush(Qt.white) - pp.setBrush(brush) - #print(QRect(self.start_point, self.end_point),self.image.size()) - #pp.drawRect(QRect(self.start_point, self.end_point)) _x1=self.start_point.x() _y1=self.start_point.y() _x2=self.end_point.x() _y2=self.end_point.y() - _sp=QPoint(min(_x1,_x2),min(_y1,_y2)) - _ep=QPoint(max(_x1,_x2),max(_y1,_y2)) - pp.drawPixmap(QRect(_sp,_ep),self.image.copy(QRect(_sp,_ep))) + _sp=QPoint(min(_x1,_x2)-globalconfig['ocrrangewidth'],min(_y1,_y2)-globalconfig['ocrrangewidth']) + _ep=QPoint(max(_x1,_x2)+globalconfig['ocrrangewidth'],max(_y1,_y2)+globalconfig['ocrrangewidth']) + self.rectlabel.setGeometry(QRect(_sp,_ep)) def mousePressEvent(self, event) : if event.button() == Qt.LeftButton: if self.clickrelease: diff --git a/LunaTranslator/LunaTranslator/gui/settingpage1.py b/LunaTranslator/LunaTranslator/gui/settingpage1.py index 3547db1a..a9d1eee6 100644 --- a/LunaTranslator/LunaTranslator/gui/settingpage1.py +++ b/LunaTranslator/LunaTranslator/gui/settingpage1.py @@ -31,7 +31,8 @@ def gethookgrid(self) : [], [('区分人名和文本',5),getsimpleswitch(globalconfig,'allow_set_text_name')], [('使用YAPI注入',5),getsimpleswitch(globalconfig,'use_yapi')], - + [], + [('获取最新提取器核心&错误反馈&游戏支持',8),(makehtml("https://github.com/HIllya51/LunaHook"),8,"link")] ] return grids @@ -180,7 +181,7 @@ def setTabOne_direct(self) : ], [ ('HOOK',3),(getsimpleswitch(globalconfig['sourcestatus2']['texthook'],'use',name='texthook',parent=self,callback= functools.partial(yuitsu_switch,self,globalconfig['sourcestatus2'],'sourceswitchs','texthook',gobject.baseobject.starttextsource),pair='sourceswitchs'),1), '', - ('Experimental',3),(getsimpleswitch(globalconfig['sourcestatus2']['fridahook'],'use',name='fridahook',parent=self,callback= functools.partial(yuitsu_switch,self,globalconfig['sourcestatus2'],'sourceswitchs','fridahook',gobject.baseobject.starttextsource),pair='sourceswitchs'),1), + ('FridaScripts',3),(getsimpleswitch(globalconfig['sourcestatus2']['fridahook'],'use',name='fridahook',parent=self,callback= functools.partial(yuitsu_switch,self,globalconfig['sourcestatus2'],'sourceswitchs','fridahook',gobject.baseobject.starttextsource),pair='sourceswitchs'),1), ] , @@ -205,7 +206,7 @@ def setTabOne_lazy(self) : - tab=self.makesubtab_lazy(['HOOK设置','OCR设置','剪贴板','内嵌翻译','Experimental'], + tab=self.makesubtab_lazy(['HOOK设置','OCR设置','剪贴板','内嵌翻译','FridaScripts'], [ lambda:self.makescroll(self.makegrid(gethookgrid(self))), lambda:self.makescroll(self.makegrid(getocrgrid(self))), diff --git a/LunaTranslator/LunaTranslator/gui/settingpage_ocr.py b/LunaTranslator/LunaTranslator/gui/settingpage_ocr.py index dc8c864f..faa54e3f 100644 --- a/LunaTranslator/LunaTranslator/gui/settingpage_ocr.py +++ b/LunaTranslator/LunaTranslator/gui/settingpage_ocr.py @@ -66,7 +66,6 @@ def getocrgrid(self) : [(("选取OCR范围后立即进行一次识别"),12),getsimpleswitch(globalconfig ,'ocrafterrangeselect')], [(("选取OCR范围后显示范围框"),12),getsimpleswitch(globalconfig ,'showrangeafterrangeselect')], [(("OCR识别易错内容修正"),12),getsimpleswitch(ocrerrorfix ,'use'),getcolorbutton(globalconfig,'',callback= functools.partial( postconfigdialog,self,ocrerrorfix['args'],'OCR识别易错内容修正'),icon='fa.gear',constcolor="#FF69B4")], - [(("范围选取遮罩透明度"),12),(getspinbox(0.01,1,globalconfig ,'OCR_mask_Opacity',double=True,step=0.01,dec=2),4),], ] return grids diff --git a/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py b/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py index cfa3108b..7da42619 100644 --- a/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py +++ b/LunaTranslator/LunaTranslator/gui/settingpage_xianshishezhi.py @@ -206,63 +206,15 @@ def setTabThree_lazy(self) : ] commonfsgrid=[ - [('缩放方式',4),(getsimplecombobox(_TRL(['Magpie10','ALT+ENTER', 'SW_SHOWMAXIMIZED','LosslessScaling']),globalconfig,'fullscreenmethod_3'),6)] + [('缩放方式',4),(getsimplecombobox(_TRL(['Magpie','ALT+ENTER', 'SW_SHOWMAXIMIZED','LosslessScaling','Magpie10_External']),globalconfig,'fullscreenmethod_3'),6)] ] - sfm=getsimplecombobox(['宽高比','全屏'],globalconfig['lossless'],'scalingFitMode') - sf=getspinbox(1,10,globalconfig['lossless'],'scaleFactor',double=True,step=0.1,dec=1) - rbs=getsimpleswitch(globalconfig['lossless'],'resizeBeforeScale') - wm=getsimpleswitch(globalconfig['lossless'],'windowedMode') - def setenables(): - sfm.setEnabled(globalconfig['lossless']['scalingMode']==0) - sf.setEnabled(globalconfig['lossless']['scalingMode']==1) - rbs.setEnabled(globalconfig['lossless']['scalingMode']==1) - wm.setEnabled(globalconfig['lossless']['scalingMode']==1) - sharp=getspinbox(0,10,globalconfig['lossless'],'sharpness') - sub1=getsimpleswitch(globalconfig['lossless'],'scalingSubtype1',callback=lambda _:setsubtype()) - sub2=getsimplecombobox(['小','中','大','非常大','极大'],globalconfig['lossless'],'scalingSubtype2',callback=lambda _:setsubtype()) - sub3=getsimpleswitch(globalconfig['lossless'],'scalingSubtype3',callback=lambda _:setsubtype()) - vrs=getsimpleswitch(globalconfig['lossless'],'VRS') - def setsubtype(): - vrs.setEnabled( globalconfig['lossless']['scalingType'] in [6]) - sharp.setEnabled( globalconfig['lossless']['scalingType'] in [1,2,8,9]) - sub1.setEnabled( globalconfig['lossless']['scalingType'] in [1]) - sub2.setEnabled( globalconfig['lossless']['scalingType'] in [6]) - sub3.setEnabled( globalconfig['lossless']['scalingType'] in [8]) - if globalconfig['lossless']['scalingType']==1: - globalconfig['lossless']['scalingSubtype']=int(globalconfig['lossless']['scalingSubtype1']) - elif globalconfig['lossless']['scalingType']==6: - globalconfig['lossless']['scalingSubtype']=globalconfig['lossless']['scalingSubtype2'] - elif globalconfig['lossless']['scalingType']==8: - globalconfig['lossless']['scalingSubtype']=int(globalconfig['lossless']['scalingSubtype3']) - setenables() - setsubtype() + losslessgrid=[ + [('Magpie10_路径',4),(getcolorbutton(globalconfig,'',callback=lambda x: getsomepath1(self,'Magpie10_路径',globalconfig,'magpie10path','Magpie10_路径',isdir=True),icon='fa.gear',constcolor="#FF69B4"),1)], + [('Hook Magpie进程使其不会退出缩放',4),getsimpleswitch(globalconfig,'hookmagpie')], + [], [('LosslessScaling_路径',4),(getcolorbutton(globalconfig,'',callback=lambda x: getsomepath1(self,'LosslessScaling_路径',globalconfig['lossless'],'path','LosslessScaling_路径',isdir=True),icon='fa.gear',constcolor="#FF69B4"),1)], - [('缩放模式',4),(getsimplecombobox(['自动','自定义'],globalconfig['lossless'],'scalingMode',lambda _: setenables()),6),''], - [('',4),(sfm,6)], - [('',4),('缩放系数',4),(sf,2)], - [('',4),('缩放前调整大小',4),(rbs,2)], - [('',4),('视窗模式',4),(wm,2)], - [('缩放类型',4),(getsimplecombobox(['Off','AMD FSR','NVIDIA Image Scaling','整数缩放','近邻缩放','xBR','Anime4K','锐化双线性','LS1','Bicubic CAS'],globalconfig['lossless'],'scalingType',callback=lambda _:setsubtype()),6)], - [('',4),('锐度',4),(sharp,2)], - [('',4),('优化版本',4),(sub1,2)], - [('',4),('尺寸',4),(sub2,2)], - [('',4),('性能',4),(sub3,2)], - [('',4),('VRS',4),(vrs,2)], - [('Frame Generation',4),(getsimplecombobox(['Off','LSFI'],globalconfig['lossless'],'frameGeneration'),6)], - [('光标选项',4)], - [('',4),('固定光标',4),(getsimpleswitch(globalconfig['lossless'],'clipCursor'),2)], - [('',4),('调整光标速度',4),(getsimpleswitch(globalconfig['lossless'],'cursorSensitivity'),2)], - [('',4),('隐藏光标',4),(getsimpleswitch(globalconfig['lossless'],'hideCursor'),2)], - [('',4),('缩放光标',4),(getsimpleswitch(globalconfig['lossless'],'scaleCursor'),2)], - [('渲染选项',4)], - [('',4),('Sycn Interval',4),(getspinbox(0,4,globalconfig['lossless'],'syncInterval'),2)], - [('',4),('双缓冲',4),(getsimpleswitch(globalconfig['lossless'],'doubleBuffering'),2)], - [('',4),('VRR支持',4),(getsimpleswitch(globalconfig['lossless'],'vrrSupport'),2)], - [('',4),('HDR支持',4),(getsimpleswitch(globalconfig['lossless'],'hdrSupport'),2)], - [('',4),('允许撕裂',4),(getsimpleswitch(globalconfig['lossless'],'allowTearing'),2)], - [('',4),('传统捕获API',4),(getsimpleswitch(globalconfig['lossless'],'legacyCaptureApi'),2)], - [('',4),('绘制帧率',4),(getsimpleswitch(globalconfig['lossless'],'drawFps'),2)], + [('Hook LosslessScaling进程使其不会退出缩放',4),getsimpleswitch(globalconfig,'hooklossless')], ] tab=self.makesubtab_lazy(['文本设置', '界面设置','窗口缩放'],[ lambda:self.makescroll(self.makegrid(textgrid ) ), @@ -270,7 +222,7 @@ def setTabThree_lazy(self) : lambda:self.makevbox( [ self.makegrid(commonfsgrid ), - self.makesubtab_lazy(['Magpie10','LosslessScaling'],[ + self.makesubtab_lazy(['Magpie','外部缩放软件'],[ lambda:self.makescroll(self.makegrid(innermagpie ) ), lambda:self.makescroll(self.makegrid(losslessgrid ) ) diff --git a/LunaTranslator/LunaTranslator/gui/translatorUI.py b/LunaTranslator/LunaTranslator/gui/translatorUI.py index 8deefdda..3add9bf9 100644 --- a/LunaTranslator/LunaTranslator/gui/translatorUI.py +++ b/LunaTranslator/LunaTranslator/gui/translatorUI.py @@ -29,7 +29,7 @@ from gui.usefulwidget import resizableframeless from gui.dialog_savedgame import browserdialog class QUnFrameWindow(resizableframeless): displayres = pyqtSignal(str,str,str ,bool) - displayraw1 = pyqtSignal(list, str,str,bool ) + displayraw1 = pyqtSignal(list, str,str,bool,bool) displaystatus=pyqtSignal(str,str,bool,bool) showhideuisignal=pyqtSignal() hookfollowsignal=pyqtSignal(int,tuple) @@ -92,7 +92,7 @@ class QUnFrameWindow(resizableframeless): except: print_exc() - def showraw(self,hira,res,color ,onlyshowhist): + def showraw(self,hira,res,color ,onlyshowhist,clear): #print(res,onlyshowhist) gobject.baseobject.transhis.getnewsentencesignal.emit(res) if onlyshowhist: @@ -102,11 +102,11 @@ class QUnFrameWindow(resizableframeless): else: _res=res if globalconfig['isshowhira'] and globalconfig['isshowrawtext']: - self.showline(True,[hira,_res],color , 2 ) + self.showline(clear,[hira,_res],color , 2 ) elif globalconfig['isshowrawtext']: - self.showline(True,[hira,_res],color,1) + self.showline(clear,[hira,_res],color,1) else: - self.showline(True,None,None,1) + self.showline(clear,None,None,1) gobject.baseobject.edittextui.getnewsentencesignal.emit(res) def showstatus(self,res,color,clear,origin): diff --git a/LunaTranslator/LunaTranslator/myutils/fullscreen.py b/LunaTranslator/LunaTranslator/myutils/fullscreen.py index 3d13ec63..9b856448 100644 --- a/LunaTranslator/LunaTranslator/myutils/fullscreen.py +++ b/LunaTranslator/LunaTranslator/myutils/fullscreen.py @@ -1,11 +1,12 @@ import os,json,math import windows from myutils.config import globalconfig ,magpie10_config -from myutils.hwnd import letfullscreen,recoverwindow,pid_running +from myutils.hwnd import letfullscreen,recoverwindow,ListProcess,injectdll from traceback import print_exc from myutils.subproc import subproc_w -import time,threading +import time,subprocess from myutils.wrapper import threader +import re class fullscreen(): def __init__(self,_externalfsend) -> None: self.savewindowstatus=None @@ -17,93 +18,160 @@ class fullscreen(): self.__call__(self.lasthwnd,not self.status) @property def fsmethod(self):return globalconfig['fullscreenmethod_3'] - # def runmagpie10(self): - # exes=[_[1] for _ in ListProcess()] - # if os.path.join(globalconfig['magpie10path'],'Magpie.exe').replace('/','\\') not in exes: - # subproc_w(os.path.join(globalconfig['magpie10path'],'Magpie.exe'),cwd=globalconfig['magpie10path'] ,name='magpie10' ) - - # def _1(self,hwnd,full): - # self.runmagpie10() - # windows.SetForegroundWindow(hwnd ) - # time.sleep(0.1) - # configpath=os.path.join(globalconfig['magpie10path'],'config/config.json') - # if os.path.exists(configpath)==False: - # configpath=os.path.join(os.environ['LOCALAPPDATA'],'Magpie/config/config.json') - # if os.path.exists(configpath)==False: - # return - # with open(configpath,'r',encoding='utf8') as ff: - # config=json.load(ff) - # shortcuts=config['shortcuts']['scale'] - # mp1={'SHIFT': 16, 'WIN': 91,'CTRL': 17,'ALT': 18} - # mp={ - # 0x100:'WIN', - # 0x200:'CTRL', - # 0x400:'ALT', - # 0x800:'SHIFT' - # } + + def internal_stopped(self): + self._externalfsend() + self.status=False + + @threader + def _wait_lossless_stop_external(self): + while windows.FindWindow("LosslessScaling",None)==0: + time.sleep(0.5) + while windows.FindWindow("LosslessScaling",None): + time.sleep(0.5) + self.internal_stopped() + def runlossless(self): + exes=[_[1] for _ in ListProcess()] + path=globalconfig['lossless']['path'] + pexe=os.path.join(path,'LosslessScaling.exe') + if pexe.replace('/','\\') not in exes: + subproc_w(pexe,cwd=path ,name='LosslessScaling' ) + time.sleep(1) + if globalconfig['hooklossless']: + for pid,exe in ListProcess(): + if exe==pexe.replace('/','\\'): + dll=os.path.abspath('./files/plugins/hookmagpie.dll') + injecter=os.path.abspath('./files/plugins/shareddllproxy{}.exe'.format('64')) + injectdll(pid,injecter,dll) + break + def _external_lossless(self,hwnd,full): - # for k in mp: - # if shortcuts&k !=0: - # windows.keybd_event(mp1[mp[k]],0,0,0) + if full: + self.runlossless() + #self._wait_lossless_stop_external() + + windows.SetForegroundWindow(hwnd ) + time.sleep(0.1) + configpath=os.path.join(os.environ['LOCALAPPDATA'],'Lossless Scaling/Settings.xml') + if os.path.exists(configpath)==False: + return + with open(configpath,'r',encoding='utf8') as ff: + config=ff.read() + + Hotkey=re.findall('(.*?)',config)[0] + hotkHotkeyModifierKeysey=re.findall('(.*?)',config)[0] + - # k2=shortcuts &0xff - # windows.keybd_event(k2,0,0,0) - # windows.keybd_event(k2, 0, windows.KEYEVENTF_KEYUP, 0) - # for k in mp: - # if shortcuts&k !=0: - # windows.keybd_event(mp1[mp[k]],0,windows.KEYEVENTF_KEYUP,0) - def _4(self,hwnd,full): - if full: - self.engine= subproc_w(r'./files/plugins/shareddllproxy64.exe lossless "{}" "{}" {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}'.format(globalconfig['lossless']['path'],hwnd, - - globalconfig['lossless']['scalingMode'], - globalconfig['lossless']['scalingFitMode'], - globalconfig['lossless']['scalingType'], - globalconfig['lossless']['scalingSubtype'], - globalconfig['lossless']['scaleFactor'], - globalconfig['lossless']['resizeBeforeScale'], - globalconfig['lossless']['windowedMode'], - globalconfig['lossless']['sharpness'], - globalconfig['lossless']['VRS'], - globalconfig['lossless']['clipCursor'], - globalconfig['lossless']['cursorSensitivity'], - globalconfig['lossless']['hideCursor'], - globalconfig['lossless']['scaleCursor'], - globalconfig['lossless']['doubleBuffering'], - globalconfig['lossless']['vrrSupport'], - globalconfig['lossless']['hdrSupport'], - globalconfig['lossless']['allowTearing'], - globalconfig['lossless']['legacyCaptureApi'], - globalconfig['lossless']['drawFps'], - globalconfig['lossless']['gpuId'], - globalconfig['lossless']['displayId'], - globalconfig['lossless']['captureOffsetLeft'], - globalconfig['lossless']['captureOffsetTop'], - globalconfig['lossless']['captureOffsetRight'], - globalconfig['lossless']['captureOffsetBottom'], - globalconfig['lossless']['multiDisplayMode'], - os.getpid(), - globalconfig['lossless']['frameGeneration'], - globalconfig['lossless']['syncInterval']),cwd=globalconfig['lossless']['path']) - self._waitenginestop() - else: - endevent =windows.AutoHandle(windows.CreateEvent(False, False,'LOSSLESS_WAITFOR_STOP_SIGNAL'+str(self.engine.pid))) - windows.SetEvent(endevent) - def _waitenginestop(self): - def _waitexternalend(): - #self.engine.wait() - while pid_running(self.engine.pid): + mods=hotkHotkeyModifierKeysey.split(' ') + + vkcode=windows.MapVirtualKey(Hotkey) + mp1={'Shift': 16, 'Windows': 91,'Control': 17,'Alt': 18} + for k in mods: + windows.keybd_event(mp1[k],0,0,0) + windows.keybd_event(vkcode,0,0,0) + windows.keybd_event(vkcode, 0, windows.KEYEVENTF_KEYUP, 0) + for k in mods: + windows.keybd_event(mp1[k],0, windows.KEYEVENTF_KEYUP,0) + def runmagpie10(self): + if windows.FindWindow('Magpie_Hotkey',None)==0: + subproc_w(os.path.join(globalconfig['magpie10path'],'Magpie.exe'),cwd=globalconfig['magpie10path'] ,name='magpie10' ) + while windows.FindWindow('Magpie_Hotkey',None)==0: time.sleep(0.5) - self._externalfsend() - self.status=False - threading.Thread(target=_waitexternalend ).start() + if globalconfig['hookmagpie']: + pid=windows.GetWindowThreadProcessId(windows.FindWindow('Magpie_Hotkey',None)) + dll=os.path.abspath('./files/plugins/hookmagpie.dll') + injecter=os.path.abspath('./files/plugins/shareddllproxy{}.exe'.format('64')) + injectdll([pid],injecter,dll) + @threader + def _wait_magpie_stop_external(self): + while windows.FindWindow("Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22",None)==0: + time.sleep(0.5) + while windows.FindWindow("Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22",None): + time.sleep(0.5) + self.internal_stopped() + def _external_magpie10(self,hwnd,full): + + + + configpath=os.path.join(globalconfig['magpie10path'],'config/config.json') + if os.path.exists(configpath)==False: + configpath=os.path.join(os.environ['LOCALAPPDATA'],'Magpie/config/config.json') + if os.path.exists(configpath)==False: + return + with open(configpath,'r',encoding='utf8') as ff: + config=json.load(ff) + autoRestore=config['autoRestore'] + shortcuts=config['shortcuts']['scale'] + mp1={'SHIFT': 16, 'WIN': 91,'CTRL': 17,'ALT': 18} + mp={ + 0x100:'WIN', + 0x200:'CTRL', + 0x400:'ALT', + 0x800:'SHIFT' + } + + if full: + self.runmagpie10() + if autoRestore==False: + self._wait_magpie_stop_external() + + windows.SetForegroundWindow(hwnd ) + time.sleep(0.1) + + for k in mp: + if shortcuts&k !=0: + windows.keybd_event(mp1[mp[k]],0,0,0) + + k2=shortcuts &0xff + windows.keybd_event(k2,0,0,0) + windows.keybd_event(k2, 0, windows.KEYEVENTF_KEYUP, 0) + for k in mp: + if shortcuts&k !=0: + windows.keybd_event(mp1[mp[k]],0,windows.KEYEVENTF_KEYUP,0) + # def _4(self,hwnd,full): + # if full: + # self.engine= subproc_w(r'./files/plugins/shareddllproxy64.exe lossless "{}" "{}" {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}'.format(globalconfig['lossless']['path'],hwnd, + + # globalconfig['lossless']['scalingMode'], + # globalconfig['lossless']['scalingFitMode'], + # globalconfig['lossless']['scalingType'], + # globalconfig['lossless']['scalingSubtype'], + # globalconfig['lossless']['scaleFactor'], + # globalconfig['lossless']['resizeBeforeScale'], + # globalconfig['lossless']['windowedMode'], + # globalconfig['lossless']['sharpness'], + # globalconfig['lossless']['VRS'], + # globalconfig['lossless']['clipCursor'], + # globalconfig['lossless']['cursorSensitivity'], + # globalconfig['lossless']['hideCursor'], + # globalconfig['lossless']['scaleCursor'], + # globalconfig['lossless']['doubleBuffering'], + # globalconfig['lossless']['vrrSupport'], + # globalconfig['lossless']['hdrSupport'], + # globalconfig['lossless']['allowTearing'], + # globalconfig['lossless']['legacyCaptureApi'], + # globalconfig['lossless']['drawFps'], + # globalconfig['lossless']['gpuId'], + # globalconfig['lossless']['displayId'], + # globalconfig['lossless']['captureOffsetLeft'], + # globalconfig['lossless']['captureOffsetTop'], + # globalconfig['lossless']['captureOffsetRight'], + # globalconfig['lossless']['captureOffsetBottom'], + # globalconfig['lossless']['multiDisplayMode'], + # os.getpid(), + # globalconfig['lossless']['frameGeneration'], + # globalconfig['lossless']['syncInterval']),cwd=globalconfig['lossless']['path']) + # self._waitenginestop() + # else: + # endevent =windows.AutoHandle(windows.CreateEvent(False, False,'LOSSLESS_WAITFOR_STOP_SIGNAL'+str(self.engine.pid))) + # windows.SetEvent(endevent) + @threader def _waitenginestop_magpie(self): self.engine.wait() - self._externalfsend() - self.status=False - def _0(self,hwnd,full): + self.internal_stopped() + def _magpie_builtin(self,hwnd,full): if full: profiles_index=globalconfig['profiles_index'] if profiles_index>len(magpie10_config['profiles']): @@ -128,25 +196,27 @@ class fullscreen(): # return # WM_DESTORYHOST=RegisterWindowMessage( "MAGPIE_WM_DESTORYHOST") # SendMessage(hwnd, WM_DESTORYHOST) - def _2(self,hwnd,full): + def _alt_enter(self,hwnd,full): windows.SetForegroundWindow(hwnd ) windows.keybd_event(18,0,0,0) # alt windows.keybd_event(13,0,0,0) # enter windows.keybd_event(13, 0, windows.KEYEVENTF_KEYUP, 0) windows.keybd_event(18, 0, windows.KEYEVENTF_KEYUP, 0) - def _3(self,hwnd,full): + def _SW_SHOWMAXIMIZED(self,hwnd,full): if full: self.savewindowstatus=letfullscreen(hwnd) else: recoverwindow(hwnd,self.savewindowstatus) + @threader def __call__(self, hwnd=0,full=False): try: [ - self._0, - self._2, - self._3, - self._4 + self._magpie_builtin, + self._alt_enter, + self._SW_SHOWMAXIMIZED, + self._external_lossless, + self._external_magpie10 ][self.fsmethod](hwnd,full) self.status=full self.lasthwnd=hwnd diff --git a/LunaTranslator/LunaTranslator/myutils/hwnd.py b/LunaTranslator/LunaTranslator/myutils/hwnd.py index b151bd23..7495468e 100644 --- a/LunaTranslator/LunaTranslator/myutils/hwnd.py +++ b/LunaTranslator/LunaTranslator/myutils/hwnd.py @@ -3,7 +3,7 @@ import threading from PyQt5.QtGui import QPixmap,QColor ,QIcon from PyQt5.QtWidgets import QApplication import gobject -import os +import os,subprocess import time,winrtutils,winsharedutils,hashlib from myutils.wrapper import threader def pid_running(pid): @@ -200,7 +200,14 @@ def getScreenRate() : windows.ReleaseDC(None, hDC); __rate = round(dpiX, 2) return __rate - +def injectdll(injectpids,injecter,dll): + pid=' '.join([str(_) for _ in injectpids]) + if any(map(testprivilege,injectpids))==False: + windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE) + else: + ret=subprocess.run('"{}" dllinject {} "{}"'.format(injecter,pid,dll)).returncode + if(ret==0): + windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE) def mouseselectwindow(callback): diff --git a/LunaTranslator/LunaTranslator/ocrengines/local.py b/LunaTranslator/LunaTranslator/ocrengines/local.py index 15e40572..05020f3c 100644 --- a/LunaTranslator/LunaTranslator/ocrengines/local.py +++ b/LunaTranslator/LunaTranslator/ocrengines/local.py @@ -2,8 +2,6 @@ import os from myutils.config import globalconfig,_TR,static_data -import requests -import base64 from ocrengines.baseocrclass import baseocr from ctypes import CDLL,c_char_p ,create_string_buffer,c_uint32,POINTER,c_int32 import os @@ -54,14 +52,27 @@ class OCR(baseocr): def initocr(self): self._ocr=ocrwrapper() self._savelang=None + self.isusingjaasen=False self.checkchange() def checkchange(self): if self._savelang==self.srclang: return + + self.isusingjaasen=False self._ocr.trydestroy() - - path='./files/ocr/{}'.format(static_data["language_list_translator_inner"][globalconfig["srclang3"]]) + + innerlang=static_data["language_list_translator_inner"][globalconfig["srclang3"]] + path='./files/ocr/{}'.format(innerlang) + failed=False if not(os.path.exists(path+'/det.onnx') and os.path.exists(path+'/rec.onnx') and os.path.exists(path+'/dict.txt') ): + failed=True + if(innerlang=='en'): + path2='./files/ocr/{}'.format('ja') + if (os.path.exists(path2+'/det.onnx') and os.path.exists(path2+'/rec.onnx') and os.path.exists(path2+'/dict.txt') ): + path=path2 + failed=False + self.isusingjaasen=True + if failed: raise Exception(_TR('未下载该语言的OCR模型,请从软件主页下载模型解压到files/ocr路径后使用') ) self._ocr.init(path+'/det.onnx',path+'/rec.onnx',path+'/dict.txt') self._savelang=self.srclang @@ -78,4 +89,7 @@ class OCR(baseocr): box.append([int(_) for _ in ls[i*2].split(',')]) text.append(ls[i*2+1]) - return self.common_solve_text_orientation(box,text) \ No newline at end of file + res=self.common_solve_text_orientation(box,text) + if self.isusingjaasen: + res=''+_TR('找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳')+''+res + return res \ No newline at end of file diff --git a/LunaTranslator/LunaTranslator/textsource/texthook.py b/LunaTranslator/LunaTranslator/textsource/texthook.py index 5085eada..c3b16fe3 100644 --- a/LunaTranslator/LunaTranslator/textsource/texthook.py +++ b/LunaTranslator/LunaTranslator/textsource/texthook.py @@ -8,7 +8,7 @@ import windows,subprocess from myutils.config import globalconfig ,savehook_new_data ,_TR,static_data from textsource.textsourcebase import basetext from myutils.utils import checkchaos -from myutils.hwnd import testprivilege +from myutils.hwnd import testprivilege,injectdll from myutils.wrapper import threader from ctypes import CDLL,c_bool,POINTER,Structure,c_int,pointer,c_wchar_p,c_uint64,sizeof,c_void_p,cast,c_wchar,c_uint32,c_uint8,c_uint,c_char,c_short from ctypes.wintypes import DWORD,LPCWSTR,HANDLE @@ -158,13 +158,7 @@ class texthook(basetext ): print(injecter,os.path.exists(injecter)) print(dll,os.path.exists(dll)) #subprocess.Popen('"{}" dllinject {} "{}"'.format(injecter,pid,dll)) - pid=' '.join([str(_) for _ in injectpids]) - if any(map(testprivilege,injectpids))==False: - windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE) - else: - ret=subprocess.run('"{}" dllinject {} "{}"'.format(injecter,pid,dll)).returncode - if(ret==0): - windows.ShellExecute(0,'runas',injecter,'dllinject {} "{}"'.format(pid,dll),None,windows.SW_HIDE) + injectdll(injectpids,injecter,dll) @threader def onprocconnect(self,pid): self.connectedpids.append(pid) diff --git a/LunaTranslator/LunaTranslator/windows.py b/LunaTranslator/LunaTranslator/windows.py index 19a46702..b15a0a88 100644 --- a/LunaTranslator/LunaTranslator/windows.py +++ b/LunaTranslator/LunaTranslator/windows.py @@ -3,7 +3,7 @@ from ctypes import c_int,POINTER,pointer,c_uint,windll,c_char_p,create_unicode_ from ctypes import Structure,c_int,POINTER,c_uint,WINFUNCTYPE,c_void_p,sizeof,byref import ctypes from traceback import print_exc -from ctypes.wintypes import RECT,POINT,HWND,BOOL,WORD,DWORD,BYTE ,LPCWSTR,HANDLE +from ctypes.wintypes import RECT,POINT,HWND,BOOL,WORD,DWORD,BYTE ,LPCWSTR,HANDLE,UINT WAIT_TIMEOUT = 258 SW_HIDE = 0 @@ -748,4 +748,12 @@ class AutoHandle(HANDLE): CloseHandle(self) - \ No newline at end of file + +_MapVirtualKey=_user32.MapVirtualKeyW +_MapVirtualKey.argtypes=UINT,UINT +_MapVirtualKey.restype=UINT +MAPVK_VK_TO_VSC=0 +MAPVK_VSC_TO_VK=1 +MAPVK_VK_TO_CHAR=2 +def MapVirtualKey(char,uMapType=MAPVK_VK_TO_CHAR): + return _MapVirtualKey(ord(char),uMapType) \ No newline at end of file diff --git a/LunaTranslator/files/defaultconfig/config.json b/LunaTranslator/files/defaultconfig/config.json index 78d4f384..3b0e9a3c 100644 --- a/LunaTranslator/files/defaultconfig/config.json +++ b/LunaTranslator/files/defaultconfig/config.json @@ -12,6 +12,8 @@ "read_translator": 0, "disappear_delay": 5, "network":0, + "hookmagpie":true, + "hooklossless":true, "direct_filterrepeat":false, "allow_set_text_name":false, "embedded": { @@ -94,7 +96,6 @@ 500, 500 ], - "OCR_mask_Opacity":0.5, "ocr_stable_sim": 0, "ocr_diff_sim": 0.95, "autorun": true, diff --git a/LunaTranslator/files/defaultconfig/static_data.json b/LunaTranslator/files/defaultconfig/static_data.json index 123bc860..efa0c332 100644 --- a/LunaTranslator/files/defaultconfig/static_data.json +++ b/LunaTranslator/files/defaultconfig/static_data.json @@ -1,5 +1,5 @@ { - "version":"v2.36.4", + "version":"v2.36.5", "language_list_show":["简体中文","日本語","English","Русский язык","Español","한국어","Français","繁體中文","Tiếng Việt","Türkçe","Polski","Українська Мова","Italiano","اللغة العربية","ภาษาไทย"] , "language_list_translator":["简体中文","日文","英文","俄语","西班牙语","韩语","法语","繁体中文","越南语","土耳其语","波兰语","乌克兰语","意大利语","阿拉伯语","泰语"], "language_list_translator_inner":["zh", "ja", "en","ru","es","ko","fr","cht","vi","tr","pl","uk","it","ar","th"], @@ -277,7 +277,8 @@ "./files/plugins/LunaHook/LunaHook32.dll", "./files/plugins/LunaHook/LunaHook64.dll", "./files/plugins/LoaderDll.dll", - "./files/plugins/LocaleEmulator.dll" + "./files/plugins/LocaleEmulator.dll", + "./files/plugins/hookmagpie.dll" ], "64":[ "./files/plugins/DLL64/winsharedutils64.dll", diff --git a/LunaTranslator/files/lang/ar.json b/LunaTranslator/files/lang/ar.json index e72f38c4..29a7bf56 100644 --- a/LunaTranslator/files/lang/ar.json +++ b/LunaTranslator/files/lang/ar.json @@ -662,7 +662,6 @@ "Sakura部署教程": "ساكورا نشر البرنامج التعليمي", "Github仓库": "مستودع جيتوب", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "استخدام المعلومات الواردة أعلاه في الترجمة ( عادة ما يكون هناك بعض التحسن ، ولكن يمكن أن يؤدي إلى إبطاء )", - "范围选取遮罩透明度": "مجموعة اختيار قناع الشفافية", "文本缓冲区长度": "نص طول المخزن المؤقت", "显示/隐藏历史翻译和调试输出": "عرض / إخفاء تاريخ الترجمة وتصحيح الأخطاء الناتج", "历史翻译和调试输出": "تاريخ الترجمة وتصحيح الأخطاء الناتج", @@ -701,5 +700,10 @@ "语言自适应": "التكيف اللغوي", "去除重复字符": "إزالة الأحرف المكررة", "游戏内叠加层": "لعبة التراص الداخلي", - "内联效果参数": "مضمنة تأثير المعلمة" + "内联效果参数": "مضمنة تأثير المعلمة", + "获取最新提取器核心&错误反馈&游戏支持": "الحصول على أحدث المستخلص الأساسية و ردود فعل خاطئة و دعم اللعبة", + "外部缩放软件": "برامج التكبير الخارجي", + "Hook Magpie进程使其不会退出缩放": "هوك ماجي العملية بحيث لا تخرج من التكبير", + "Hook LosslessScaling进程使其不会退出缩放": "هوك looslessscaling العملية بحيث لا تخرج من التكبير", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "لا يمكن العثور على نموذج التعرف على اللغة الإنجليزية ، واستخدام نموذج اليابانية بدلا من ذلك ، قد لا تعمل بشكل جيد" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/cht.json b/LunaTranslator/files/lang/cht.json index 32f7c396..01cc9f1e 100644 --- a/LunaTranslator/files/lang/cht.json +++ b/LunaTranslator/files/lang/cht.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Sakura部署教程", "Github仓库": "Github倉庫", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "利用上文資訊翻譯(通常會有一定的效果提升,但會導致變慢)", - "范围选取遮罩透明度": "範圍選取遮罩透明度", "文本缓冲区长度": "文字緩衝區長度", "显示/隐藏历史翻译和调试输出": "顯示/隱藏歷史翻譯和調試輸出", "历史翻译和调试输出": "歷史翻譯和調試輸出", @@ -701,5 +700,10 @@ "语言自适应": "語言自我調整", "去除重复字符": "去除重複字元", "游戏内叠加层": "遊戲內疊加層", - "内联效果参数": "內聯效果參數" + "内联效果参数": "內聯效果參數", + "获取最新提取器核心&错误反馈&游戏支持": "獲取最新提取器覈心&錯誤迴響&遊戲支持", + "外部缩放软件": "外部縮放軟件", + "Hook Magpie进程使其不会退出缩放": "Hook Magpie行程使其不會退出縮放", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling行程使其不會退出縮放", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "找不到英語識別模型,正在使用日語模型作為代替,可能效果不佳" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/en.json b/LunaTranslator/files/lang/en.json index daabfffb..5b473625 100644 --- a/LunaTranslator/files/lang/en.json +++ b/LunaTranslator/files/lang/en.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Sakura Deployment Tutorial", "Github仓库": "Github warehouse", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Translate using the information provided in the previous text (usually with some improvement in effectiveness, but it can lead to slower translation)", - "范围选取遮罩透明度": "Range selection mask transparency", "文本缓冲区长度": "Text buffer length", "显示/隐藏历史翻译和调试输出": "Show/hide historical translation and debugging output", "历史翻译和调试输出": "Historical translation and debugging output", @@ -701,5 +700,10 @@ "语言自适应": "Language Adaptation", "去除重复字符": "Remove duplicate characters", "游戏内叠加层": "In-game overlay layer", - "内联效果参数": "Inline effect parameters" + "内联效果参数": "Inline effect parameters", + "获取最新提取器核心&错误反馈&游戏支持": "Get the latest extractor core&error feedback&game support", + "外部缩放软件": "External scaling software", + "Hook Magpie进程使其不会退出缩放": "Hook Magpie process prevents it from exiting scaling", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling process prevents it from exiting scaling", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Unable to find English recognition model, using Japanese model as a substitute, may not be effective" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/es.json b/LunaTranslator/files/lang/es.json index 4b9ff226..4c53703e 100644 --- a/LunaTranslator/files/lang/es.json +++ b/LunaTranslator/files/lang/es.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Guía de despliegue Sakura", "Github仓库": "Almacén github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Traducción utilizando la información anterior (generalmente tiene un cierto efecto de mejora, pero puede causar lentitud)", - "范围选取遮罩透明度": "Transparencia de la máscara de selección de alcance", "文本缓冲区长度": "Longitud del colchón de texto", "显示/隐藏历史翻译和调试输出": "Mostrar / ocultar la traducción histórica y depurar la salida", "历史翻译和调试输出": "Traducción histórica y salida de depuración", @@ -701,5 +700,10 @@ "语言自适应": "Adaptación lingüística", "去除重复字符": "Eliminar caracteres duplicados", "游戏内叠加层": "Capa superpuesta en el juego", - "内联效果参数": "Parámetros de efecto en línea" + "内联效果参数": "Parámetros de efecto en línea", + "获取最新提取器核心&错误反馈&游戏支持": "Obtener el último núcleo del extractor & comentarios erróneos & soporte del juego", + "外部缩放软件": "Software de zoom externo", + "Hook Magpie进程使其不会退出缩放": "El proceso Hook magpie hace que no salga del zoom", + "Hook LosslessScaling进程使其不会退出缩放": "El proceso Hook losslessscaling hace que no salga del zoom", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "No se puede encontrar el modelo de reconocimiento inglés, se está utilizando el modelo japonés como sustituto y puede no funcionar bien." } \ No newline at end of file diff --git a/LunaTranslator/files/lang/fr.json b/LunaTranslator/files/lang/fr.json index 578ad3e1..07d8f987 100644 --- a/LunaTranslator/files/lang/fr.json +++ b/LunaTranslator/files/lang/fr.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Tutoriel de déploiement Sakura", "Github仓库": "Entrepôt github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Utilisez les informations ci - dessus pour traduire (il y a généralement une certaine augmentation de l'effet, mais cela entraîne un ralentissement)", - "范围选取遮罩透明度": "Gamme sélectionner masque transparence", "文本缓冲区长度": "Longueur du tampon de texte", "显示/隐藏历史翻译和调试输出": "Afficher / masquer la traduction historique et la sortie de débogage", "历史翻译和调试输出": "Traduction historique et sortie de débogage", @@ -701,5 +700,10 @@ "语言自适应": "Adaptation linguistique", "去除重复字符": "Supprimer les caractères dupliqués", "游戏内叠加层": "Couches superposées dans le jeu", - "内联效果参数": "Paramètres d'effet inline" + "内联效果参数": "Paramètres d'effet inline", + "获取最新提取器核心&错误反馈&游戏支持": "Obtenez le dernier extractor Core & BUG Feedback & Game support", + "外部缩放软件": "Logiciel de zoom externe", + "Hook Magpie进程使其不会退出缩放": "Le processus Hook Magpie ne quitte pas le zoom", + "Hook LosslessScaling进程使其不会退出缩放": "Hook losslesscaling processus pour ne pas quitter le zoom", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Impossible de trouver le modèle de reconnaissance anglais, le modèle japonais est utilisé à la place, peut ne pas fonctionner correctement" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/it.json b/LunaTranslator/files/lang/it.json index 1cb7011c..67c23c57 100644 --- a/LunaTranslator/files/lang/it.json +++ b/LunaTranslator/files/lang/it.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Tutorial sull'implementazione di Sakura", "Github仓库": "Magazzino Github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Tradurre utilizzando le informazioni fornite nel testo precedente (di solito con qualche miglioramento in efficacia, ma può portare a una traduzione più lenta)", - "范围选取遮罩透明度": "Trasparenza maschera di selezione intervallo", "文本缓冲区长度": "Lunghezza buffer di testo", "显示/隐藏历史翻译和调试输出": "Mostra/nasconde l'output storico di traduzione e debug", "历史翻译和调试输出": "Risultato storico di traduzione e debug", @@ -701,5 +700,10 @@ "语言自适应": "Adattamento linguistico", "去除重复字符": "Rimuovi caratteri duplicati", "游戏内叠加层": "Livello di sovrapposizione in gioco", - "内联效果参数": "Parametri degli effetti in linea" + "内联效果参数": "Parametri degli effetti in linea", + "获取最新提取器核心&错误反馈&游戏支持": "Ottieni l'ultimo core&error feedback & supporto al gioco dell'estrattore", + "外部缩放软件": "Software di ridimensionamento esterno", + "Hook Magpie进程使其不会退出缩放": "Il processo Hook Magpie impedisce di uscire dalla scala", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling processo impedisce di uscire dalla scalabilità", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Impossibile trovare il modello di riconoscimento inglese, utilizzando il modello giapponese come sostituto, potrebbe non essere efficace" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ja.json b/LunaTranslator/files/lang/ja.json index 1f4bc48f..8e659b36 100644 --- a/LunaTranslator/files/lang/ja.json +++ b/LunaTranslator/files/lang/ja.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Sakura導入チュートリアル", "Github仓库": "Github倉庫", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "上記の情報翻訳を利用する(通常は一定の効果が上がるが、遅くなる)", - "范围选取遮罩透明度": "範囲選択マスクの透明度", "文本缓冲区长度": "テキストバッファ長", "显示/隐藏历史翻译和调试输出": "履歴翻訳とデバッグ出力の表示/非表示", "历史翻译和调试输出": "履歴翻訳とデバッグ出力", @@ -701,5 +700,10 @@ "语言自适应": "げんごてきおう", "去除重复字符": "繰り返し文字を削除", "游戏内叠加层": "ゲーム内のオーバーレイレイヤ", - "内联效果参数": "インラインエフェクトパラメータ" + "内联效果参数": "インラインエフェクトパラメータ", + "获取最新提取器核心&错误反馈&游戏支持": "最新の抽出コア&エラーフィードバック&ゲームサポートの取得", + "外部缩放软件": "外部ズームソフトウェア", + "Hook Magpie进程使其不会退出缩放": "Hook Magpieプロセスはスケールを終了しないようにする", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScalingプロセスはスケーリングを終了しないようにする", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "英語認識モデルが見つからず、代わりに日本語モデルを使用しているため、効果がない可能性があります" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ko.json b/LunaTranslator/files/lang/ko.json index 426089b3..21f7bb49 100644 --- a/LunaTranslator/files/lang/ko.json +++ b/LunaTranslator/files/lang/ko.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Sakura 배포 자습서", "Github仓库": "Github 창고", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "위의 정보를 사용하여 번역 (일반적으로 효과가 향상되지만 느려질 수 있음)", - "范围选取遮罩透明度": "범위 선택 마스크 투명도", "文本缓冲区长度": "텍스트 버퍼 길이", "显示/隐藏历史翻译和调试输出": "히스토리 번역 및 디버그 출력 표시 / 숨기기", "历史翻译和调试输出": "역사 번역 및 디버그 출력", @@ -701,5 +700,10 @@ "语言自适应": "언어 적응", "去除重复字符": "중복 문자 제거", "游戏内叠加层": "게임 내 중첩층", - "内联效果参数": "인라인 효과 매개변수" + "内联效果参数": "인라인 효과 매개변수", + "获取最新提取器核心&错误反馈&游戏支持": "최신 추출기 코어 & 오류 피드백 & 게임 지원 받기", + "外部缩放软件": "외부 확대 / 축소 소프트웨어", + "Hook Magpie进程使其不会退出缩放": "Hook Magpie 프로세스로 인해 줌이 종료되지 않습니다.", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling 프로세스로 인해 줌이 종료되지 않습니다.", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "영어 인식 모델을 찾을 수 없습니다. 대신 일본어 모델을 사용하고 있습니다. 효과가 없을 수 있습니다" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/pl.json b/LunaTranslator/files/lang/pl.json index 136c8fe9..a0c56019 100644 --- a/LunaTranslator/files/lang/pl.json +++ b/LunaTranslator/files/lang/pl.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Samouczek wdrażania Sakury", "Github仓库": "Magazyn Github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Przetłumacz za pomocą informacji podanych w poprzednim tekście (zwykle z pewną poprawą skuteczności, ale może to prowadzić do wolniejszego tłumaczenia)", - "范围选取遮罩透明度": "Przejrzystość maski wyboru zakresu", "文本缓冲区长度": "Długość bufora tekstu", "显示/隐藏历史翻译和调试输出": "Pokaż/ukryj historyczne tłumaczenie i wyjście debugowania", "历史翻译和调试输出": "Historiczne tłumaczenie i debugowanie", @@ -701,5 +700,10 @@ "语言自适应": "Dostosowanie języka", "去除重复字符": "Usuń duplikaty znaków", "游戏内叠加层": "Warstwa nakładki w grze", - "内联效果参数": "Parametry efektu liniowego" + "内联效果参数": "Parametry efektu liniowego", + "获取最新提取器核心&错误反馈&游戏支持": "Uzyskaj najnowszą informację zwrotną o błędach ekstraktora i wsparcie gry", + "外部缩放软件": "Oprogramowanie do skalowania zewnętrznego", + "Hook Magpie进程使其不会退出缩放": "Proces Hook Magpie zapobiega zakończeniu skalowania", + "Hook LosslessScaling进程使其不会退出缩放": "Proces Hook Losslessless Scaling zapobiega zakończeniu skalowania", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Nie można znaleźć angielskiego modelu rozpoznawania, używając modelu japońskiego jako substytutu, może nie być skuteczny" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ru.json b/LunaTranslator/files/lang/ru.json index ef4a5a15..d3f42fd6 100644 --- a/LunaTranslator/files/lang/ru.json +++ b/LunaTranslator/files/lang/ru.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Курс развертывания Sakura", "Github仓库": "Склад Github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Использование вышеприведенного перевода информации (обычно имеет определенный эффект улучшения, но приводит к замедлению)", - "范围选取遮罩透明度": "Выберите прозрачность покрытия", "文本缓冲区长度": "Длина буфера текста", "显示/隐藏历史翻译和调试输出": "Показать / скрыть исторический перевод и отладочный вывод", "历史翻译和调试输出": "Исторический перевод и отладка вывода", @@ -701,5 +700,10 @@ "语言自适应": "Язык адаптируется", "去除重复字符": "Удалить повторяющиеся символы", "游戏内叠加层": "Слой наложения внутри игры", - "内联效果参数": "Параметры эффекта подключения" + "内联效果参数": "Параметры эффекта подключения", + "获取最新提取器核心&错误反馈&游戏支持": "Получите последние ядра экстрактора и обратную связь с ошибками & Поддержка игры", + "外部缩放软件": "Программное обеспечение для внешнего масштабирования", + "Hook Magpie进程使其不会退出缩放": "Процесс Hook Magpie не выводит из масштабирования", + "Hook LosslessScaling进程使其不会退出缩放": "Процесс Hook LosslessScaling не выводит из масштабирования", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Не найдена модель распознавания на английском языке, вместо нее используется японская модель, которая может быть неэффективной" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/th.json b/LunaTranslator/files/lang/th.json index 6fc1ed04..9432d1d5 100644 --- a/LunaTranslator/files/lang/th.json +++ b/LunaTranslator/files/lang/th.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Sakura Deployment กวดวิชา", "Github仓库": "คลังสินค้า Github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "ใช้ประโยชน์จากการแปลข้อมูลข้างต้น (มักจะมีผลบางอย่างเพิ่มขึ้น แต่ทำให้ช้าลง)", - "范围选取遮罩透明度": "ช่วงการเลือกหน้ากาก ความโปร่งใส", "文本缓冲区长度": "ความยาวบัฟเฟอร์ข้อความ", "显示/隐藏历史翻译和调试输出": "แสดง / ซ่อนการแปลประวัติและการแก้จุดบกพร่องเอาท์พุท", "历史翻译和调试输出": "การแปลประวัติและการแก้จุดบกพร่องเอาท์พุท", @@ -701,5 +700,10 @@ "语言自适应": "การปรับภาษา", "去除重复字符": "ลบอักขระที่ซ้ำกัน", "游戏内叠加层": "ซ้อนทับในเกม", - "内联效果参数": "พารามิเตอร์ผลกระทบแบบอินไลน์" + "内联效果参数": "พารามิเตอร์ผลกระทบแบบอินไลน์", + "获取最新提取器核心&错误反馈&游戏支持": "รับแกนดูดล่าสุดและข้อเสนอแนะข้อผิดพลาดและการสนับสนุนเกม", + "外部缩放软件": "ซอฟต์แวร์ซูมภายนอก", + "Hook Magpie进程使其不会退出缩放": "กระบวนการ Hook Magpie ทำให้ไม่ออกจากการซูม", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling กระบวนการทำให้มันไม่ออกจากซูม", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "ไม่พบแบบจำลองการจำแนกภาษาอังกฤษและใช้แบบจำลองภาษาญี่ปุ่นแทนอาจไม่ได้ผล" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/tr.json b/LunaTranslator/files/lang/tr.json index 0367e082..a9062157 100644 --- a/LunaTranslator/files/lang/tr.json +++ b/LunaTranslator/files/lang/tr.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Sakura Deployment Tutorial", "Github仓库": "Github deposu", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Önceki metinde verilen bilgileri kullanarak çevirin (genelde etkinliğinde bazı gelişmelerle, fakat daha yavaş çeviriye yol açabilir)", - "范围选取遮罩透明度": "Aralık seçim maskesi transparency", "文本缓冲区长度": "Metin buffer uzunluğu", "显示/隐藏历史翻译和调试输出": "Tarihi çevirimi ve arızasızlandırma çıkışını göster/gizle", "历史翻译和调试输出": "Tarihi çeviri ve hata ayıklama çıkışı", @@ -701,5 +700,10 @@ "语言自适应": "Dil Yönetimi", "去除重复字符": "Çift karakterleri sil", "游戏内叠加层": "Oyun üzerindeki katı", - "内联效果参数": "İçeri etkisi parametreleri" + "内联效果参数": "İçeri etkisi parametreleri", + "获取最新提取器核心&错误反馈&游戏支持": "Son ekstraktör çekirdek&hata geri veri&oyunu desteğini alın", + "外部缩放软件": "Dışarı skalama yazılımı", + "Hook Magpie进程使其不会退出缩放": "Hook Magpie süreci ölçeklenmesini engelledi", + "Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling süreç ölçeklenmesini engelledi", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "İngilizce tanıma modeli bulamadı. Japon modeli yerine koyarak kullanarak etkili olabilir." } \ No newline at end of file diff --git a/LunaTranslator/files/lang/uk.json b/LunaTranslator/files/lang/uk.json index 77d5d0c1..0a6be8ab 100644 --- a/LunaTranslator/files/lang/uk.json +++ b/LunaTranslator/files/lang/uk.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Навчення розробки Sakura", "Github仓库": "Сховище Github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Переклад за допомогою інформації, наданої у попередньому тексті (зазвичай, з деяким покращенням ефективності, але це може призвести до повільнішого перекладу)", - "范围选取遮罩透明度": "Прозорість маски вибору діапазону", "文本缓冲区长度": "Довжина текстового буфера", "显示/隐藏历史翻译和调试输出": "Показувати/сховати історичний переклад і вивід зневаджування", "历史翻译和调试输出": "Історічний переклад і вивід зневаджування", @@ -701,5 +700,10 @@ "语言自适应": "Адаптація мови", "去除重复字符": "Вилучити дублікатні символи", "游戏内叠加层": "Шир перекладу у грі", - "内联效果参数": "Параметри вхідних ефектів" + "内联效果参数": "Параметри вхідних ефектів", + "获取最新提取器核心&错误反馈&游戏支持": "Отримати останню підтримку гри для відтворення & помилок ядра екстрактора", + "外部缩放软件": "Зовнішнє програмне забезпечення масштабу", + "Hook Magpie进程使其不会退出缩放": "Процес Hook Magpie забороняє їй вийти з масштабу", + "Hook LosslessScaling进程使其不会退出缩放": "Процес безвтратного розміруScaling забороняє їй вийти з розміру", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Не вдалося знайти англійську модель розпізнавання, використовуючи японську модель як заміну, може бути неефективною" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/vi.json b/LunaTranslator/files/lang/vi.json index 24fd9ab1..2de89427 100644 --- a/LunaTranslator/files/lang/vi.json +++ b/LunaTranslator/files/lang/vi.json @@ -662,7 +662,6 @@ "Sakura部署教程": "Hướng dẫn triển khai Sakura", "Github仓库": "Kho Github", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Sử dụng thông tin trên để dịch (thường có một số hiệu ứng tăng lên, nhưng có thể dẫn đến chậm hơn)", - "范围选取遮罩透明度": "Phạm vi chọn Mask Transparency", "文本缓冲区长度": "Chiều dài bộ đệm văn bản", "显示/隐藏历史翻译和调试输出": "Hiển thị/ẩn lịch sử dịch và đầu ra gỡ lỗi", "历史翻译和调试输出": "Lịch sử dịch và gỡ lỗi đầu ra", @@ -701,5 +700,10 @@ "语言自适应": "Thích nghi ngôn ngữ", "去除重复字符": "Loại bỏ các ký tự trùng lặp", "游戏内叠加层": "Lớp phủ trong trò chơi", - "内联效果参数": "Tham số hiệu ứng nội tuyến" + "内联效果参数": "Tham số hiệu ứng nội tuyến", + "获取最新提取器核心&错误反馈&游戏支持": "Nhận lõi Extractor mới nhất&Phản hồi lỗi&Hỗ trợ trò chơi", + "外部缩放软件": "Phần mềm Zoom ngoài", + "Hook Magpie进程使其不会退出缩放": "Quá trình Hook Magpie làm cho nó không thoát khỏi zoom", + "Hook LosslessScaling进程使其不会退出缩放": "Quá trình Hook LosslessScaling làm cho nó không thoát khỏi zoom", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Không tìm thấy mô hình nhận dạng tiếng Anh, đang sử dụng mô hình tiếng Nhật thay thế và có thể không hoạt động tốt" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/zh.json b/LunaTranslator/files/lang/zh.json index 2971d276..36a3ae78 100644 --- a/LunaTranslator/files/lang/zh.json +++ b/LunaTranslator/files/lang/zh.json @@ -661,7 +661,6 @@ "Sakura部署教程": "", "Github仓库": "", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "", - "范围选取遮罩透明度": "", "文本缓冲区长度": "", "显示/隐藏历史翻译和调试输出": "", "历史翻译和调试输出": "", @@ -701,5 +700,10 @@ "API接口格式如下,可根据自己的设置进行修改IP和端口。": "", "去除重复字符": "", "游戏内叠加层": "", - "内联效果参数": "" + "内联效果参数": "", + "获取最新提取器核心&错误反馈&游戏支持": "", + "外部缩放软件": "", + "Hook Magpie进程使其不会退出缩放": "", + "Hook LosslessScaling进程使其不会退出缩放": "", + "找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "" } \ No newline at end of file diff --git a/LunaTranslator/pack.py b/LunaTranslator/pack.py index 88e39583..551ce21e 100644 --- a/LunaTranslator/pack.py +++ b/LunaTranslator/pack.py @@ -6,7 +6,7 @@ if x86: nuitkadist=r'..\build\x86\LunaTranslator_main.dist' targetdir=r'..\build\LunaTranslator_x86' launch=r'..\plugins\builds\_x86' - downlevel=f'C:\Windows\SysWOW64\downlevel' + downlevel=r'C:\Windows\SysWOW64\downlevel' target='LunaTranslator_x86.zip' baddll='DLL64' else: @@ -15,7 +15,7 @@ else: launch=r'..\plugins\builds\_x64' nuitkadist=r'..\build\x64\LunaTranslator_main.dist' targetdir=r'..\build\LunaTranslator' - downlevel=f'C:\Windows\system32\downlevel' + downlevel=r'C:\Windows\system32\downlevel' targetdir_in=rf'{targetdir}\LunaTranslator' def get_import_table(file_path): pe = pefile.PE(file_path) diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 9ce41b72..ace9b2b8 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -28,4 +28,4 @@ add_subdirectory(exec) add_subdirectory(shareddllproxy) add_subdirectory(winrtutils) add_subdirectory(winsharedutils) - \ No newline at end of file +add_subdirectory(hookmagpie) \ No newline at end of file diff --git a/plugins/hookmagpie/.gitignore b/plugins/hookmagpie/.gitignore new file mode 100644 index 00000000..d20b5f12 --- /dev/null +++ b/plugins/hookmagpie/.gitignore @@ -0,0 +1 @@ +minhook \ No newline at end of file diff --git a/plugins/hookmagpie/CMakeLists.txt b/plugins/hookmagpie/CMakeLists.txt new file mode 100644 index 00000000..0596a431 --- /dev/null +++ b/plugins/hookmagpie/CMakeLists.txt @@ -0,0 +1,9 @@ + + +if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) + add_library(hookmagpie MODULE hookmagpie.cpp) + add_subdirectory(minhook) + target_link_libraries(hookmagpie minhook ${Detours}) +endif() + + \ No newline at end of file diff --git a/plugins/hookmagpie/hookmagpie.cpp b/plugins/hookmagpie/hookmagpie.cpp new file mode 100644 index 00000000..cf30b8d2 --- /dev/null +++ b/plugins/hookmagpie/hookmagpie.cpp @@ -0,0 +1,295 @@ +#include +#include +#include +#include +#include +#include +#include +namespace Win32Utils{ +static HANDLE SafeHandle(HANDLE h) noexcept { return (h == INVALID_HANDLE_VALUE) ? nullptr : h; } +struct HandleCloser { void operator()(HANDLE h) noexcept { assert(h != INVALID_HANDLE_VALUE); if (h) CloseHandle(h); } }; + +using ScopedHandle = std::unique_ptr::type, HandleCloser>; +std::wstring GetPathOfWnd(HWND hWnd) { + ScopedHandle hProc; + + DWORD dwProcId = 0; + if (GetWindowThreadProcessId(hWnd, &dwProcId)) { + hProc.reset(SafeHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcId))); + if (!hProc) { + } + } else { + } + + if (!hProc) { + static const auto getProcessHandleFromHwnd = (HANDLE (WINAPI*)(HWND))GetProcAddress( + LoadLibraryEx(L"Oleacc.dll", NULL, 0), "GetProcessHandleFromHwnd"); + if (getProcessHandleFromHwnd) { + hProc.reset(getProcessHandleFromHwnd(hWnd)); + if (!hProc) { + } + } + + if (!hProc) { + return {}; + } + } + + std::wstring fileName(MAX_PATH, 0); + DWORD size = MAX_PATH; + if (!QueryFullProcessImageName(hProc.get(), 0, fileName.data(), &size)) { + return {}; + } + + fileName.resize(size); + return fileName; +} +} +namespace StrUtils{ +template +static void ToLowerCase(std::basic_string& str) noexcept { + for (CHAR_T& c : str) { + c = tolower(c); + } +} +} +static std::wstring GetExeName(HWND hWnd) noexcept { + std::wstring exeName = Win32Utils::GetPathOfWnd(hWnd); + exeName = exeName.substr(exeName.find_last_of(L'\\') + 1); + StrUtils::ToLowerCase(exeName); + return exeName; +} +bool(*IsValidSrcWindow)(HWND); + +struct hook_stack +{ + +#ifndef _WIN64 + uintptr_t _eflags; //pushfd + uintptr_t edi, // pushad + esi, + ebp, + esp, + ebx, + edx, + ecx, // this + eax; // 0x28 + +#else + uintptr_t r15, + r14, + r13, + r12, + r11, + r10, + r9, + r8, + rdi, + rsi, + rbp, + rsp, + rdx, + rcx, + rbx, + rax; +#endif + uintptr_t eflags; // pushaf + union + { + uintptr_t stack[1]; // beginning of the runtime stack + uintptr_t retaddr; + BYTE base[1]; + }; + +}; + + +uintptr_t findEnclosingAlignedFunction_strict(uintptr_t start, uintptr_t back_range) +{ + start &= ~0xf; + for (uintptr_t i = start, j = start - back_range; i > j; i-=0x10) { + DWORD k = *(DWORD *)(i-4); + if (k == 0xcccccccc + || k == 0x90909090 + || k == 0xccccccc3 + || k == 0x909090c3 + ) + return i; + } + return 0; +} +bool checkislunawindow(HWND hwndSrc) +{ + wchar_t title[100]; + GetWindowText(hwndSrc,title,100); + if (wcscmp(title,L"LunaTranslator")==0||GetExeName(hwndSrc) == L"lunatranslator_main.exe"||GetExeName(hwndSrc) == L"lunatranslator.exe") + return true; + else return false; +} +class hooks{ +public: +void IsValidSrcWindow_hooked(uintptr_t lpDataBase) +{ + auto stack=(hook_stack*)(lpDataBase-sizeof(hook_stack)+sizeof(uintptr_t)); + auto hwndSrc=(HWND)(stack->rcx); + if (checkislunawindow(hwndSrc)) + { + //MessageBoxW(0,GetExeName(hwndSrc).c_str(),L"",0); + stack->rcx=(uintptr_t)FindWindow(L"Shell_TrayWnd",nullptr); + } +} +hooks(LPVOID location){ + BYTE common_hook[] = { + 0x9c, // push rflags + 0x50, // push rax + 0x53, // push rbx + 0x51, // push rcx + 0x52, // push rdx + 0x54, // push rsp + 0x55, // push rbp + 0x56, // push rsi + 0x57, // push rdi + 0x41, 0x50, // push r8 + 0x41, 0x51, // push r9 + 0x41, 0x52, // push r10 + 0x41, 0x53, // push r11 + 0x41, 0x54, // push r12 + 0x41, 0x55, // push r13 + 0x41, 0x56, // push r14 + 0x41, 0x57, // push r15 + // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention + // https://stackoverflow.com/questions/43358429/save-value-of-xmm-registers + 0x48, 0x83, 0xec, 0x20, // sub rsp,0x20 + 0xf3, 0x0f, 0x7f, 0x24, 0x24, // movdqu [rsp],xmm4 + 0xf3, 0x0f, 0x7f, 0x6c, 0x24, 0x10, // movdqu [rsp+0x10],xmm5 + 0x48, 0x8d, 0x94, 0x24, 0xa8, 0x00, 0x00, 0x00, // lea rdx,[rsp+0xa8] + 0x48, 0xb9, 0,0,0,0,0,0,0,0, // mov rcx,@this + 0x48, 0xb8, 0,0,0,0,0,0,0,0, // mov rax,@TextHook::Send + 0x48, 0x89, 0xe3, // mov rbx,rsp + 0x48, 0x83, 0xe4, 0xf0, // and rsp,0xfffffffffffffff0 ; align stack + 0xff, 0xd0, // call rax + 0x48, 0x89, 0xdc, // mov rsp,rbx + 0xf3, 0x0f, 0x6f, 0x6c, 0x24, 0x10, // movdqu xmm5,XMMWORD PTR[rsp + 0x10] + 0xf3, 0x0f, 0x6f, 0x24, 0x24, // movdqu xmm4,XMMWORD PTR[rsp] + 0x48, 0x83, 0xc4, 0x20, // add rsp,0x20 + 0x41, 0x5f, // pop r15 + 0x41, 0x5e, // pop r14 + 0x41, 0x5d, // pop r13 + 0x41, 0x5c, // pop r12 + 0x41, 0x5b, // pop r11 + 0x41, 0x5a, // pop r10 + 0x41, 0x59, // pop r9 + 0x41, 0x58, // pop r8 + 0x5f, // pop rdi + 0x5e, // pop rsi + 0x5d, // pop rbp + 0x5c, // pop rsp + 0x5a, // pop rdx + 0x59, // pop rcx + 0x5b, // pop rbx + 0x58, // pop rax + 0x9d, // pop rflags + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] + 0,0,0,0,0,0,0,0 // @original + }; + int this_offset = 50, send_offset = 60, original_offset = 126; + DWORD _; + VirtualProtect(location, 10, PAGE_EXECUTE_READWRITE, &_); + auto trampoline=VirtualAlloc(0,sizeof(common_hook),MEM_COMMIT,PAGE_EXECUTE_READWRITE); + void* original; + MH_STATUS error; + if ((error = MH_CreateHook(location, trampoline, &original)) != MH_OK) + return; + + *(hooks**)(common_hook + this_offset) = this; + *(void(hooks::**)(uintptr_t))(common_hook + send_offset) = &hooks::IsValidSrcWindow_hooked; + *(void**)(common_hook + original_offset) = original; + memcpy(trampoline, common_hook, sizeof(common_hook)); + MH_EnableHook(location); +} +}; +void starthookmagpie() +{ + uintptr_t IsValidSrcWindow=0; + + + wchar_t target[]=L"Shell_TrayWnd"; + auto base=(uintptr_t)GetModuleHandle(L"Magpie.App.dll"); + BYTE lea[]={0x48,0x8D,0x05}; + //.text:0000000180146AD0 48 8D 05 91 87 10 00 lea rax, aShellTraywnd ; "Shell_TrayWnd" + //.rdata:000000018024F268 53 00 68 00 65 00 6C 00 6C 00+text "UTF-16LE", 'Shell_TrayWnd',0 + + __try{ + for(int i=0;i<0x1000000;i++) + { + if(memcmp(lea,(LPVOID)(i+base),3)==0) + { + auto addr=base+i; + auto leastr=(*(int*)(addr+3))+7+addr; + if(IsBadReadPtr((LPVOID)leastr,sizeof(target))==0) + if(wcscmp((wchar_t*)leastr,target)==0) + { + IsValidSrcWindow=findEnclosingAlignedFunction_strict(addr,0x1000); + break; + } + } + } + }__except(EXCEPTION_EXECUTE_HANDLER) { return; } + + if(IsValidSrcWindow==0)return; + + //IsValidSrcWindow=(decltype(IsValidSrcWindow))((uintptr_t)GetModuleHandle(L"Magpie.App.dll")+0x180146860-0x180000000); + MH_Initialize(); + hooks _((LPVOID)IsValidSrcWindow); + // DetourTransactionBegin(); + // DetourUpdateThread(GetCurrentThread()); + // DetourAttach(&(PVOID&)IsValidSrcWindow,IsValidSrcWindow_hooked); + // DetourTransactionCommit(); +} + +auto GetClassNameWs=GetClassNameW; +int +WINAPI +GetClassNameWH( + _In_ HWND hWnd, + _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, + _In_ int nMaxCount + ){ + if(checkislunawindow(hWnd)){ + wcscpy(lpClassName,L"ApplicationManager_ImmersiveShellWindow"); + return TRUE; + } + else + return GetClassNameWs(hWnd,lpClassName,nMaxCount); +} +void starthooklossless() +{ + DetourTransactionBegin(); + DetourUpdateThread(GetCurrentThread()); + DetourAttach(&(PVOID&)GetClassNameWs, GetClassNameWH); + DetourTransactionCommit(); +} +void starthook() +{ + if(GetModuleHandle(L"Magpie.App.dll")) + starthookmagpie(); + else if(GetModuleHandle(L"Lossless.dll")) + starthooklossless(); +} +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + starthook(); + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +