This commit is contained in:
恍兮惚兮 2024-02-12 14:39:49 +08:00
parent 24cd9b7c04
commit 77d889a758
33 changed files with 638 additions and 221 deletions

View File

@ -147,14 +147,22 @@ class MAINUI() :
return ss return ss
def textgetmethod(self,text,is_auto_run=True,embedcallback=None,onlytrans=False): def textgetmethod(self,text,is_auto_run=True,embedcallback=None,onlytrans=False):
_autolock(self.solvegottextlock) _autolock(self.solvegottextlock)
needclear=True
if onlytrans==False: if onlytrans==False:
self.currentsignature=time.time() self.currentsignature=time.time()
if type(text)==str: if type(text)==str:
if text[:len('<notrans>')]=='<notrans>': if text.startswith('<notrans>'):
self.translation_ui.displayres.emit('',globalconfig['rawtextcolor'],text[len('<notrans>'):],onlytrans) self.translation_ui.displayres.emit('',globalconfig['rawtextcolor'],text[len('<notrans>'):],onlytrans)
self.currenttext=text self.currenttext=text
self.currentread=text self.currentread=text
return return
elif text.startswith('<msg_warning_with_text>'):
length=len('<msg_warning_with_text>')
idx=text.find('</msg_warning_with_text>')
warningtext=text[length:idx]
text=text[idx+length+1:]
self.translation_ui.displaystatus.emit(warningtext,'red',True,False)
needclear=False
else: else:
msgs=[ msgs=[
('<msg_info_not_refresh>',globalconfig['rawtextcolor'],False), ('<msg_info_not_refresh>',globalconfig['rawtextcolor'],False),
@ -226,11 +234,11 @@ class MAINUI() :
print_exc() print_exc()
hira=[] hira=[]
if globalconfig['refresh_on_get_trans']==False: 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=None
_showrawfunction_sig=0 _showrawfunction_sig=0
else: 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() _showrawfunction_sig=time.time()
text_solved,optimization_params= self.solvebeforetrans(text) text_solved,optimization_params= self.solvebeforetrans(text)

View File

@ -1,5 +1,5 @@
from PyQt5.QtWidgets import QWidget,QDesktopWidget,QMainWindow,QLabel,QPushButton,QStatusBar,QDialog,QApplication 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 from PyQt5.QtCore import Qt,QPoint,QRect,QEvent,pyqtSignal
import gobject import gobject
@ -64,10 +64,10 @@ class rangeselct(QMainWindow) :
super(rangeselct, self).__init__(parent) super(rangeselct, self).__init__(parent)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)#|Qt.WindowStaysOnTopHint ) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)#|Qt.WindowStaysOnTopHint )
self.rectlabel=QLabel(self)
self.setAttribute(Qt.WA_TranslucentBackground)
def reset(self): def reset(self):
self.setStyleSheet('''background-color:black; ''')
self.setWindowOpacity(globalconfig['OCR_mask_Opacity'])
num_screens = QDesktopWidget().screenCount() num_screens = QDesktopWidget().screenCount()
x,y,x2,y2=9999,9999,0,0 x,y,x2,y2=9999,9999,0,0
for i in range(num_screens): for i in range(num_screens):
@ -77,14 +77,15 @@ class rangeselct(QMainWindow) :
x2=max(x2,_rect.x()+_rect.width()) x2=max(x2,_rect.x()+_rect.width())
y2=max(y2,_rect.y()+_rect.height()) y2=max(y2,_rect.y()+_rect.height())
self.setGeometry(x,y,x2-x,y2-y) self.setGeometry(x,y,x2-x,y2-y)
self.rectlabel.setGeometry(x,y,x2-x,y2-y)
self.setCursor(Qt.CrossCursor) self.setCursor(Qt.CrossCursor)
self.image=QApplication.primaryScreen().grabWindow(0,x,y,x2-x,y2-y)
self.is_drawing = False self.is_drawing = False
self.setMouseTracking(True) self.setMouseTracking(True)
self.start_point = QPoint() self.start_point = QPoint()
self.end_point = QPoint() self.end_point = QPoint()
self.startauto=False self.startauto=False
self.clickrelease=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): def immediateend(self):
try: try:
@ -98,20 +99,16 @@ class rangeselct(QMainWindow) :
if self.is_drawing: if self.is_drawing:
pp = QPainter(self ) pp = QPainter(self )
pen = QPen() pen = QPen(QColor(globalconfig['ocrrangecolor']))
pen.setStyle(Qt.NoPen) pen.setWidth(globalconfig['ocrrangewidth'])
pp.setPen(pen) 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() _x1=self.start_point.x()
_y1=self.start_point.y() _y1=self.start_point.y()
_x2=self.end_point.x() _x2=self.end_point.x()
_y2=self.end_point.y() _y2=self.end_point.y()
_sp=QPoint(min(_x1,_x2),min(_y1,_y2)) _sp=QPoint(min(_x1,_x2)-globalconfig['ocrrangewidth'],min(_y1,_y2)-globalconfig['ocrrangewidth'])
_ep=QPoint(max(_x1,_x2),max(_y1,_y2)) _ep=QPoint(max(_x1,_x2)+globalconfig['ocrrangewidth'],max(_y1,_y2)+globalconfig['ocrrangewidth'])
pp.drawPixmap(QRect(_sp,_ep),self.image.copy(QRect(_sp,_ep))) self.rectlabel.setGeometry(QRect(_sp,_ep))
def mousePressEvent(self, event) : def mousePressEvent(self, event) :
if event.button() == Qt.LeftButton: if event.button() == Qt.LeftButton:
if self.clickrelease: if self.clickrelease:

View File

@ -31,7 +31,8 @@ def gethookgrid(self) :
[], [],
[('区分人名和文本',5),getsimpleswitch(globalconfig,'allow_set_text_name')], [('区分人名和文本',5),getsimpleswitch(globalconfig,'allow_set_text_name')],
[('使用YAPI注入',5),getsimpleswitch(globalconfig,'use_yapi')], [('使用YAPI注入',5),getsimpleswitch(globalconfig,'use_yapi')],
[],
[('获取最新提取器核心&错误反馈&游戏支持',8),(makehtml("https://github.com/HIllya51/LunaHook"),8,"link")]
] ]
return grids 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), '', ('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(gethookgrid(self))),
lambda:self.makescroll(self.makegrid(getocrgrid(self))), lambda:self.makescroll(self.makegrid(getocrgrid(self))),

View File

@ -66,7 +66,6 @@ def getocrgrid(self) :
[(("选取OCR范围后立即进行一次识别"),12),getsimpleswitch(globalconfig ,'ocrafterrangeselect')], [(("选取OCR范围后立即进行一次识别"),12),getsimpleswitch(globalconfig ,'ocrafterrangeselect')],
[(("选取OCR范围后显示范围框"),12),getsimpleswitch(globalconfig ,'showrangeafterrangeselect')], [(("选取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")], [(("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 return grids

View File

@ -206,63 +206,15 @@ def setTabThree_lazy(self) :
] ]
commonfsgrid=[ 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=[ 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)], [('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),''], [('Hook LosslessScaling进程使其不会退出缩放',4),getsimpleswitch(globalconfig,'hooklossless')],
[('',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)],
] ]
tab=self.makesubtab_lazy(['文本设置', '界面设置','窗口缩放'],[ tab=self.makesubtab_lazy(['文本设置', '界面设置','窗口缩放'],[
lambda:self.makescroll(self.makegrid(textgrid ) ), lambda:self.makescroll(self.makegrid(textgrid ) ),
@ -270,7 +222,7 @@ def setTabThree_lazy(self) :
lambda:self.makevbox( lambda:self.makevbox(
[ [
self.makegrid(commonfsgrid ), self.makegrid(commonfsgrid ),
self.makesubtab_lazy(['Magpie10','LosslessScaling'],[ self.makesubtab_lazy(['Magpie','外部缩放软件'],[
lambda:self.makescroll(self.makegrid(innermagpie ) ), lambda:self.makescroll(self.makegrid(innermagpie ) ),
lambda:self.makescroll(self.makegrid(losslessgrid ) ) lambda:self.makescroll(self.makegrid(losslessgrid ) )

View File

@ -29,7 +29,7 @@ from gui.usefulwidget import resizableframeless
from gui.dialog_savedgame import browserdialog from gui.dialog_savedgame import browserdialog
class QUnFrameWindow(resizableframeless): class QUnFrameWindow(resizableframeless):
displayres = pyqtSignal(str,str,str ,bool) 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) displaystatus=pyqtSignal(str,str,bool,bool)
showhideuisignal=pyqtSignal() showhideuisignal=pyqtSignal()
hookfollowsignal=pyqtSignal(int,tuple) hookfollowsignal=pyqtSignal(int,tuple)
@ -92,7 +92,7 @@ class QUnFrameWindow(resizableframeless):
except: except:
print_exc() print_exc()
def showraw(self,hira,res,color ,onlyshowhist): def showraw(self,hira,res,color ,onlyshowhist,clear):
#print(res,onlyshowhist) #print(res,onlyshowhist)
gobject.baseobject.transhis.getnewsentencesignal.emit(res) gobject.baseobject.transhis.getnewsentencesignal.emit(res)
if onlyshowhist: if onlyshowhist:
@ -102,11 +102,11 @@ class QUnFrameWindow(resizableframeless):
else: else:
_res=res _res=res
if globalconfig['isshowhira'] and globalconfig['isshowrawtext']: if globalconfig['isshowhira'] and globalconfig['isshowrawtext']:
self.showline(True,[hira,_res],color , 2 ) self.showline(clear,[hira,_res],color , 2 )
elif globalconfig['isshowrawtext']: elif globalconfig['isshowrawtext']:
self.showline(True,[hira,_res],color,1) self.showline(clear,[hira,_res],color,1)
else: else:
self.showline(True,None,None,1) self.showline(clear,None,None,1)
gobject.baseobject.edittextui.getnewsentencesignal.emit(res) gobject.baseobject.edittextui.getnewsentencesignal.emit(res)
def showstatus(self,res,color,clear,origin): def showstatus(self,res,color,clear,origin):

View File

@ -1,11 +1,12 @@
import os,json,math import os,json,math
import windows import windows
from myutils.config import globalconfig ,magpie10_config 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 traceback import print_exc
from myutils.subproc import subproc_w from myutils.subproc import subproc_w
import time,threading import time,subprocess
from myutils.wrapper import threader from myutils.wrapper import threader
import re
class fullscreen(): class fullscreen():
def __init__(self,_externalfsend) -> None: def __init__(self,_externalfsend) -> None:
self.savewindowstatus=None self.savewindowstatus=None
@ -17,93 +18,160 @@ class fullscreen():
self.__call__(self.lasthwnd,not self.status) self.__call__(self.lasthwnd,not self.status)
@property @property
def fsmethod(self):return globalconfig['fullscreenmethod_3'] 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): def internal_stopped(self):
# 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'
# }
# 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)
def _waitenginestop(self):
def _waitexternalend():
#self.engine.wait()
while pid_running(self.engine.pid):
time.sleep(0.5)
self._externalfsend() self._externalfsend()
self.status=False self.status=False
threading.Thread(target=_waitexternalend ).start()
@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):
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('<Hotkey>(.*?)</Hotkey>',config)[0]
hotkHotkeyModifierKeysey=re.findall('<HotkeyModifierKeys>(.*?)</HotkeyModifierKeys>',config)[0]
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)
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 @threader
def _waitenginestop_magpie(self): def _waitenginestop_magpie(self):
self.engine.wait() self.engine.wait()
self._externalfsend() self.internal_stopped()
self.status=False def _magpie_builtin(self,hwnd,full):
def _0(self,hwnd,full):
if full: if full:
profiles_index=globalconfig['profiles_index'] profiles_index=globalconfig['profiles_index']
if profiles_index>len(magpie10_config['profiles']): if profiles_index>len(magpie10_config['profiles']):
@ -128,25 +196,27 @@ class fullscreen():
# return # return
# WM_DESTORYHOST=RegisterWindowMessage( "MAGPIE_WM_DESTORYHOST") # WM_DESTORYHOST=RegisterWindowMessage( "MAGPIE_WM_DESTORYHOST")
# SendMessage(hwnd, WM_DESTORYHOST) # SendMessage(hwnd, WM_DESTORYHOST)
def _2(self,hwnd,full): def _alt_enter(self,hwnd,full):
windows.SetForegroundWindow(hwnd ) windows.SetForegroundWindow(hwnd )
windows.keybd_event(18,0,0,0) # alt windows.keybd_event(18,0,0,0) # alt
windows.keybd_event(13,0,0,0) # enter windows.keybd_event(13,0,0,0) # enter
windows.keybd_event(13, 0, windows.KEYEVENTF_KEYUP, 0) windows.keybd_event(13, 0, windows.KEYEVENTF_KEYUP, 0)
windows.keybd_event(18, 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: if full:
self.savewindowstatus=letfullscreen(hwnd) self.savewindowstatus=letfullscreen(hwnd)
else: else:
recoverwindow(hwnd,self.savewindowstatus) recoverwindow(hwnd,self.savewindowstatus)
@threader
def __call__(self, hwnd=0,full=False): def __call__(self, hwnd=0,full=False):
try: try:
[ [
self._0, self._magpie_builtin,
self._2, self._alt_enter,
self._3, self._SW_SHOWMAXIMIZED,
self._4 self._external_lossless,
self._external_magpie10
][self.fsmethod](hwnd,full) ][self.fsmethod](hwnd,full)
self.status=full self.status=full
self.lasthwnd=hwnd self.lasthwnd=hwnd

View File

@ -3,7 +3,7 @@ import threading
from PyQt5.QtGui import QPixmap,QColor ,QIcon from PyQt5.QtGui import QPixmap,QColor ,QIcon
from PyQt5.QtWidgets import QApplication from PyQt5.QtWidgets import QApplication
import gobject import gobject
import os import os,subprocess
import time,winrtutils,winsharedutils,hashlib import time,winrtutils,winsharedutils,hashlib
from myutils.wrapper import threader from myutils.wrapper import threader
def pid_running(pid): def pid_running(pid):
@ -200,7 +200,14 @@ def getScreenRate() :
windows.ReleaseDC(None, hDC); windows.ReleaseDC(None, hDC);
__rate = round(dpiX, 2) __rate = round(dpiX, 2)
return __rate 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): def mouseselectwindow(callback):

View File

@ -2,8 +2,6 @@ import os
from myutils.config import globalconfig,_TR,static_data from myutils.config import globalconfig,_TR,static_data
import requests
import base64
from ocrengines.baseocrclass import baseocr from ocrengines.baseocrclass import baseocr
from ctypes import CDLL,c_char_p ,create_string_buffer,c_uint32,POINTER,c_int32 from ctypes import CDLL,c_char_p ,create_string_buffer,c_uint32,POINTER,c_int32
import os import os
@ -54,14 +52,27 @@ class OCR(baseocr):
def initocr(self): def initocr(self):
self._ocr=ocrwrapper() self._ocr=ocrwrapper()
self._savelang=None self._savelang=None
self.isusingjaasen=False
self.checkchange() self.checkchange()
def checkchange(self): def checkchange(self):
if self._savelang==self.srclang: if self._savelang==self.srclang:
return return
self.isusingjaasen=False
self._ocr.trydestroy() 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') ): 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路径后使用') ) raise Exception(_TR('未下载该语言的OCR模型,请从软件主页下载模型解压到files/ocr路径后使用') )
self._ocr.init(path+'/det.onnx',path+'/rec.onnx',path+'/dict.txt') self._ocr.init(path+'/det.onnx',path+'/rec.onnx',path+'/dict.txt')
self._savelang=self.srclang self._savelang=self.srclang
@ -78,4 +89,7 @@ class OCR(baseocr):
box.append([int(_) for _ in ls[i*2].split(',')]) box.append([int(_) for _ in ls[i*2].split(',')])
text.append(ls[i*2+1]) text.append(ls[i*2+1])
return self.common_solve_text_orientation(box,text) res=self.common_solve_text_orientation(box,text)
if self.isusingjaasen:
res='<msg_warning_with_text>'+_TR('找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳')+'</msg_warning_with_text>'+res
return res

View File

@ -8,7 +8,7 @@ import windows,subprocess
from myutils.config import globalconfig ,savehook_new_data ,_TR,static_data from myutils.config import globalconfig ,savehook_new_data ,_TR,static_data
from textsource.textsourcebase import basetext from textsource.textsourcebase import basetext
from myutils.utils import checkchaos from myutils.utils import checkchaos
from myutils.hwnd import testprivilege from myutils.hwnd import testprivilege,injectdll
from myutils.wrapper import threader 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 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 from ctypes.wintypes import DWORD,LPCWSTR,HANDLE
@ -158,13 +158,7 @@ class texthook(basetext ):
print(injecter,os.path.exists(injecter)) print(injecter,os.path.exists(injecter))
print(dll,os.path.exists(dll)) print(dll,os.path.exists(dll))
#subprocess.Popen('"{}" dllinject {} "{}"'.format(injecter,pid,dll)) #subprocess.Popen('"{}" dllinject {} "{}"'.format(injecter,pid,dll))
pid=' '.join([str(_) for _ in injectpids]) injectdll(injectpids,injecter,dll)
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)
@threader @threader
def onprocconnect(self,pid): def onprocconnect(self,pid):
self.connectedpids.append(pid) self.connectedpids.append(pid)

View File

@ -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 from ctypes import Structure,c_int,POINTER,c_uint,WINFUNCTYPE,c_void_p,sizeof,byref
import ctypes import ctypes
from traceback import print_exc 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 WAIT_TIMEOUT = 258
SW_HIDE = 0 SW_HIDE = 0
@ -749,3 +749,11 @@ class AutoHandle(HANDLE):
_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)

View File

@ -12,6 +12,8 @@
"read_translator": 0, "read_translator": 0,
"disappear_delay": 5, "disappear_delay": 5,
"network":0, "network":0,
"hookmagpie":true,
"hooklossless":true,
"direct_filterrepeat":false, "direct_filterrepeat":false,
"allow_set_text_name":false, "allow_set_text_name":false,
"embedded": { "embedded": {
@ -94,7 +96,6 @@
500, 500,
500 500
], ],
"OCR_mask_Opacity":0.5,
"ocr_stable_sim": 0, "ocr_stable_sim": 0,
"ocr_diff_sim": 0.95, "ocr_diff_sim": 0.95,
"autorun": true, "autorun": true,

View File

@ -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_show":["简体中文","日本語","English","Русский язык","Español","한국어","Français","繁體中文","Tiếng Việt","Türkçe","Polski","Українська Мова","Italiano","اللغة العربية","ภาษาไทย"] ,
"language_list_translator":["简体中文","日文","英文","俄语","西班牙语","韩语","法语","繁体中文","越南语","土耳其语","波兰语","乌克兰语","意大利语","阿拉伯语","泰语"], "language_list_translator":["简体中文","日文","英文","俄语","西班牙语","韩语","法语","繁体中文","越南语","土耳其语","波兰语","乌克兰语","意大利语","阿拉伯语","泰语"],
"language_list_translator_inner":["zh", "ja", "en","ru","es","ko","fr","cht","vi","tr","pl","uk","it","ar","th"], "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/LunaHook32.dll",
"./files/plugins/LunaHook/LunaHook64.dll", "./files/plugins/LunaHook/LunaHook64.dll",
"./files/plugins/LoaderDll.dll", "./files/plugins/LoaderDll.dll",
"./files/plugins/LocaleEmulator.dll" "./files/plugins/LocaleEmulator.dll",
"./files/plugins/hookmagpie.dll"
], ],
"64":[ "64":[
"./files/plugins/DLL64/winsharedutils64.dll", "./files/plugins/DLL64/winsharedutils64.dll",

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "ساكورا نشر البرنامج التعليمي", "Sakura部署教程": "ساكورا نشر البرنامج التعليمي",
"Github仓库": "مستودع جيتوب", "Github仓库": "مستودع جيتوب",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "استخدام المعلومات الواردة أعلاه في الترجمة ( عادة ما يكون هناك بعض التحسن ، ولكن يمكن أن يؤدي إلى إبطاء )", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "استخدام المعلومات الواردة أعلاه في الترجمة ( عادة ما يكون هناك بعض التحسن ، ولكن يمكن أن يؤدي إلى إبطاء )",
"范围选取遮罩透明度": "مجموعة اختيار قناع الشفافية",
"文本缓冲区长度": "نص طول المخزن المؤقت", "文本缓冲区长度": "نص طول المخزن المؤقت",
"显示/隐藏历史翻译和调试输出": "عرض / إخفاء تاريخ الترجمة وتصحيح الأخطاء الناتج", "显示/隐藏历史翻译和调试输出": "عرض / إخفاء تاريخ الترجمة وتصحيح الأخطاء الناتج",
"历史翻译和调试输出": "تاريخ الترجمة وتصحيح الأخطاء الناتج", "历史翻译和调试输出": "تاريخ الترجمة وتصحيح الأخطاء الناتج",
@ -701,5 +700,10 @@
"语言自适应": "التكيف اللغوي", "语言自适应": "التكيف اللغوي",
"去除重复字符": "إزالة الأحرف المكررة", "去除重复字符": "إزالة الأحرف المكررة",
"游戏内叠加层": "لعبة التراص الداخلي", "游戏内叠加层": "لعبة التراص الداخلي",
"内联效果参数": "مضمنة تأثير المعلمة" "内联效果参数": "مضمنة تأثير المعلمة",
"获取最新提取器核心&错误反馈&游戏支持": "الحصول على أحدث المستخلص الأساسية و ردود فعل خاطئة و دعم اللعبة",
"外部缩放软件": "برامج التكبير الخارجي",
"Hook Magpie进程使其不会退出缩放": "هوك ماجي العملية بحيث لا تخرج من التكبير",
"Hook LosslessScaling进程使其不会退出缩放": "هوك looslessscaling العملية بحيث لا تخرج من التكبير",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "لا يمكن العثور على نموذج التعرف على اللغة الإنجليزية ، واستخدام نموذج اليابانية بدلا من ذلك ، قد لا تعمل بشكل جيد"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Sakura部署教程", "Sakura部署教程": "Sakura部署教程",
"Github仓库": "Github倉庫", "Github仓库": "Github倉庫",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "利用上文資訊翻譯(通常會有一定的效果提升,但會導致變慢)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "利用上文資訊翻譯(通常會有一定的效果提升,但會導致變慢)",
"范围选取遮罩透明度": "範圍選取遮罩透明度",
"文本缓冲区长度": "文字緩衝區長度", "文本缓冲区长度": "文字緩衝區長度",
"显示/隐藏历史翻译和调试输出": "顯示/隱藏歷史翻譯和調試輸出", "显示/隐藏历史翻译和调试输出": "顯示/隱藏歷史翻譯和調試輸出",
"历史翻译和调试输出": "歷史翻譯和調試輸出", "历史翻译和调试输出": "歷史翻譯和調試輸出",
@ -701,5 +700,10 @@
"语言自适应": "語言自我調整", "语言自适应": "語言自我調整",
"去除重复字符": "去除重複字元", "去除重复字符": "去除重複字元",
"游戏内叠加层": "遊戲內疊加層", "游戏内叠加层": "遊戲內疊加層",
"内联效果参数": "內聯效果參數" "内联效果参数": "內聯效果參數",
"获取最新提取器核心&错误反馈&游戏支持": "獲取最新提取器覈心&錯誤迴響&遊戲支持",
"外部缩放软件": "外部縮放軟件",
"Hook Magpie进程使其不会退出缩放": "Hook Magpie行程使其不會退出縮放",
"Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling行程使其不會退出縮放",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "找不到英語識別模型,正在使用日語模型作為代替,可能效果不佳"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Sakura Deployment Tutorial", "Sakura部署教程": "Sakura Deployment Tutorial",
"Github仓库": "Github warehouse", "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)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "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", "文本缓冲区长度": "Text buffer length",
"显示/隐藏历史翻译和调试输出": "Show/hide historical translation and debugging output", "显示/隐藏历史翻译和调试输出": "Show/hide historical translation and debugging output",
"历史翻译和调试输出": "Historical translation and debugging output", "历史翻译和调试输出": "Historical translation and debugging output",
@ -701,5 +700,10 @@
"语言自适应": "Language Adaptation", "语言自适应": "Language Adaptation",
"去除重复字符": "Remove duplicate characters", "去除重复字符": "Remove duplicate characters",
"游戏内叠加层": "In-game overlay layer", "游戏内叠加层": "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"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Guía de despliegue Sakura", "Sakura部署教程": "Guía de despliegue Sakura",
"Github仓库": "Almacén github", "Github仓库": "Almacén github",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Traducción utilizando la información anterior (generalmente tiene un cierto efecto de mejora, pero puede causar lentitud)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "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", "文本缓冲区长度": "Longitud del colchón de texto",
"显示/隐藏历史翻译和调试输出": "Mostrar / ocultar la traducción histórica y depurar la salida", "显示/隐藏历史翻译和调试输出": "Mostrar / ocultar la traducción histórica y depurar la salida",
"历史翻译和调试输出": "Traducción histórica y salida de depuración", "历史翻译和调试输出": "Traducción histórica y salida de depuración",
@ -701,5 +700,10 @@
"语言自适应": "Adaptación lingüística", "语言自适应": "Adaptación lingüística",
"去除重复字符": "Eliminar caracteres duplicados", "去除重复字符": "Eliminar caracteres duplicados",
"游戏内叠加层": "Capa superpuesta en el juego", "游戏内叠加层": "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."
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Tutoriel de déploiement Sakura", "Sakura部署教程": "Tutoriel de déploiement Sakura",
"Github仓库": "Entrepôt github", "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)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "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", "文本缓冲区长度": "Longueur du tampon de texte",
"显示/隐藏历史翻译和调试输出": "Afficher / masquer la traduction historique et la sortie de débogage", "显示/隐藏历史翻译和调试输出": "Afficher / masquer la traduction historique et la sortie de débogage",
"历史翻译和调试输出": "Traduction historique et sortie de débogage", "历史翻译和调试输出": "Traduction historique et sortie de débogage",
@ -701,5 +700,10 @@
"语言自适应": "Adaptation linguistique", "语言自适应": "Adaptation linguistique",
"去除重复字符": "Supprimer les caractères dupliqués", "去除重复字符": "Supprimer les caractères dupliqués",
"游戏内叠加层": "Couches superposées dans le jeu", "游戏内叠加层": "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"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Tutorial sull'implementazione di Sakura", "Sakura部署教程": "Tutorial sull'implementazione di Sakura",
"Github仓库": "Magazzino Github", "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)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "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", "文本缓冲区长度": "Lunghezza buffer di testo",
"显示/隐藏历史翻译和调试输出": "Mostra/nasconde l'output storico di traduzione e debug", "显示/隐藏历史翻译和调试输出": "Mostra/nasconde l'output storico di traduzione e debug",
"历史翻译和调试输出": "Risultato storico di traduzione e debug", "历史翻译和调试输出": "Risultato storico di traduzione e debug",
@ -701,5 +700,10 @@
"语言自适应": "Adattamento linguistico", "语言自适应": "Adattamento linguistico",
"去除重复字符": "Rimuovi caratteri duplicati", "去除重复字符": "Rimuovi caratteri duplicati",
"游戏内叠加层": "Livello di sovrapposizione in gioco", "游戏内叠加层": "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"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Sakura導入チュートリアル", "Sakura部署教程": "Sakura導入チュートリアル",
"Github仓库": "Github倉庫", "Github仓库": "Github倉庫",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "上記の情報翻訳を利用する(通常は一定の効果が上がるが、遅くなる)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "上記の情報翻訳を利用する(通常は一定の効果が上がるが、遅くなる)",
"范围选取遮罩透明度": "範囲選択マスクの透明度",
"文本缓冲区长度": "テキストバッファ長", "文本缓冲区长度": "テキストバッファ長",
"显示/隐藏历史翻译和调试输出": "履歴翻訳とデバッグ出力の表示/非表示", "显示/隐藏历史翻译和调试输出": "履歴翻訳とデバッグ出力の表示/非表示",
"历史翻译和调试输出": "履歴翻訳とデバッグ出力", "历史翻译和调试输出": "履歴翻訳とデバッグ出力",
@ -701,5 +700,10 @@
"语言自适应": "げんごてきおう", "语言自适应": "げんごてきおう",
"去除重复字符": "繰り返し文字を削除", "去除重复字符": "繰り返し文字を削除",
"游戏内叠加层": "ゲーム内のオーバーレイレイヤ", "游戏内叠加层": "ゲーム内のオーバーレイレイヤ",
"内联效果参数": "インラインエフェクトパラメータ" "内联效果参数": "インラインエフェクトパラメータ",
"获取最新提取器核心&错误反馈&游戏支持": "最新の抽出コア&エラーフィードバック&ゲームサポートの取得",
"外部缩放软件": "外部ズームソフトウェア",
"Hook Magpie进程使其不会退出缩放": "Hook Magpieプロセスはスケールを終了しないようにする",
"Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScalingプロセスはスケーリングを終了しないようにする",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "英語認識モデルが見つからず、代わりに日本語モデルを使用しているため、効果がない可能性があります"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Sakura 배포 자습서", "Sakura部署教程": "Sakura 배포 자습서",
"Github仓库": "Github 창고", "Github仓库": "Github 창고",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "위의 정보를 사용하여 번역 (일반적으로 효과가 향상되지만 느려질 수 있음)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "위의 정보를 사용하여 번역 (일반적으로 효과가 향상되지만 느려질 수 있음)",
"范围选取遮罩透明度": "범위 선택 마스크 투명도",
"文本缓冲区长度": "텍스트 버퍼 길이", "文本缓冲区长度": "텍스트 버퍼 길이",
"显示/隐藏历史翻译和调试输出": "히스토리 번역 및 디버그 출력 표시 / 숨기기", "显示/隐藏历史翻译和调试输出": "히스토리 번역 및 디버그 출력 표시 / 숨기기",
"历史翻译和调试输出": "역사 번역 및 디버그 출력", "历史翻译和调试输出": "역사 번역 및 디버그 출력",
@ -701,5 +700,10 @@
"语言自适应": "언어 적응", "语言自适应": "언어 적응",
"去除重复字符": "중복 문자 제거", "去除重复字符": "중복 문자 제거",
"游戏内叠加层": "게임 내 중첩층", "游戏内叠加层": "게임 내 중첩층",
"内联效果参数": "인라인 효과 매개변수" "内联效果参数": "인라인 효과 매개변수",
"获取最新提取器核心&错误反馈&游戏支持": "최신 추출기 코어 & 오류 피드백 & 게임 지원 받기",
"外部缩放软件": "외부 확대 / 축소 소프트웨어",
"Hook Magpie进程使其不会退出缩放": "Hook Magpie 프로세스로 인해 줌이 종료되지 않습니다.",
"Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling 프로세스로 인해 줌이 종료되지 않습니다.",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "영어 인식 모델을 찾을 수 없습니다. 대신 일본어 모델을 사용하고 있습니다. 효과가 없을 수 있습니다"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Samouczek wdrażania Sakury", "Sakura部署教程": "Samouczek wdrażania Sakury",
"Github仓库": "Magazyn Github", "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)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "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", "文本缓冲区长度": "Długość bufora tekstu",
"显示/隐藏历史翻译和调试输出": "Pokaż/ukryj historyczne tłumaczenie i wyjście debugowania", "显示/隐藏历史翻译和调试输出": "Pokaż/ukryj historyczne tłumaczenie i wyjście debugowania",
"历史翻译和调试输出": "Historiczne tłumaczenie i debugowanie", "历史翻译和调试输出": "Historiczne tłumaczenie i debugowanie",
@ -701,5 +700,10 @@
"语言自适应": "Dostosowanie języka", "语言自适应": "Dostosowanie języka",
"去除重复字符": "Usuń duplikaty znaków", "去除重复字符": "Usuń duplikaty znaków",
"游戏内叠加层": "Warstwa nakładki w grze", "游戏内叠加层": "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"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Курс развертывания Sakura", "Sakura部署教程": "Курс развертывания Sakura",
"Github仓库": "Склад Github", "Github仓库": "Склад Github",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Использование вышеприведенного перевода информации (обычно имеет определенный эффект улучшения, но приводит к замедлению)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Использование вышеприведенного перевода информации (обычно имеет определенный эффект улучшения, но приводит к замедлению)",
"范围选取遮罩透明度": "Выберите прозрачность покрытия",
"文本缓冲区长度": "Длина буфера текста", "文本缓冲区长度": "Длина буфера текста",
"显示/隐藏历史翻译和调试输出": "Показать / скрыть исторический перевод и отладочный вывод", "显示/隐藏历史翻译和调试输出": "Показать / скрыть исторический перевод и отладочный вывод",
"历史翻译和调试输出": "Исторический перевод и отладка вывода", "历史翻译和调试输出": "Исторический перевод и отладка вывода",
@ -701,5 +700,10 @@
"语言自适应": "Язык адаптируется", "语言自适应": "Язык адаптируется",
"去除重复字符": "Удалить повторяющиеся символы", "去除重复字符": "Удалить повторяющиеся символы",
"游戏内叠加层": "Слой наложения внутри игры", "游戏内叠加层": "Слой наложения внутри игры",
"内联效果参数": "Параметры эффекта подключения" "内联效果参数": "Параметры эффекта подключения",
"获取最新提取器核心&错误反馈&游戏支持": "Получите последние ядра экстрактора и обратную связь с ошибками & Поддержка игры",
"外部缩放软件": "Программное обеспечение для внешнего масштабирования",
"Hook Magpie进程使其不会退出缩放": "Процесс Hook Magpie не выводит из масштабирования",
"Hook LosslessScaling进程使其不会退出缩放": "Процесс Hook LosslessScaling не выводит из масштабирования",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Не найдена модель распознавания на английском языке, вместо нее используется японская модель, которая может быть неэффективной"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Sakura Deployment กวดวิชา", "Sakura部署教程": "Sakura Deployment กวดวิชา",
"Github仓库": "คลังสินค้า Github", "Github仓库": "คลังสินค้า Github",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "ใช้ประโยชน์จากการแปลข้อมูลข้างต้น (มักจะมีผลบางอย่างเพิ่มขึ้น แต่ทำให้ช้าลง)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "ใช้ประโยชน์จากการแปลข้อมูลข้างต้น (มักจะมีผลบางอย่างเพิ่มขึ้น แต่ทำให้ช้าลง)",
"范围选取遮罩透明度": "ช่วงการเลือกหน้ากาก ความโปร่งใส",
"文本缓冲区长度": "ความยาวบัฟเฟอร์ข้อความ", "文本缓冲区长度": "ความยาวบัฟเฟอร์ข้อความ",
"显示/隐藏历史翻译和调试输出": "แสดง / ซ่อนการแปลประวัติและการแก้จุดบกพร่องเอาท์พุท", "显示/隐藏历史翻译和调试输出": "แสดง / ซ่อนการแปลประวัติและการแก้จุดบกพร่องเอาท์พุท",
"历史翻译和调试输出": "การแปลประวัติและการแก้จุดบกพร่องเอาท์พุท", "历史翻译和调试输出": "การแปลประวัติและการแก้จุดบกพร่องเอาท์พุท",
@ -701,5 +700,10 @@
"语言自适应": "การปรับภาษา", "语言自适应": "การปรับภาษา",
"去除重复字符": "ลบอักขระที่ซ้ำกัน", "去除重复字符": "ลบอักขระที่ซ้ำกัน",
"游戏内叠加层": "ซ้อนทับในเกม", "游戏内叠加层": "ซ้อนทับในเกม",
"内联效果参数": "พารามิเตอร์ผลกระทบแบบอินไลน์" "内联效果参数": "พารามิเตอร์ผลกระทบแบบอินไลน์",
"获取最新提取器核心&错误反馈&游戏支持": "รับแกนดูดล่าสุดและข้อเสนอแนะข้อผิดพลาดและการสนับสนุนเกม",
"外部缩放软件": "ซอฟต์แวร์ซูมภายนอก",
"Hook Magpie进程使其不会退出缩放": "กระบวนการ Hook Magpie ทำให้ไม่ออกจากการซูม",
"Hook LosslessScaling进程使其不会退出缩放": "Hook LosslessScaling กระบวนการทำให้มันไม่ออกจากซูม",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "ไม่พบแบบจำลองการจำแนกภาษาอังกฤษและใช้แบบจำลองภาษาญี่ปุ่นแทนอาจไม่ได้ผล"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Sakura Deployment Tutorial", "Sakura部署教程": "Sakura Deployment Tutorial",
"Github仓库": "Github deposu", "Github仓库": "Github deposu",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Önceki metinde verilen bilgileri kullanarak çevirin (genelde etkinliğinde bazı gelişmelerle, fakat daha yavaş çeviriye yol açabilir)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Ö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", "文本缓冲区长度": "Metin buffer uzunluğu",
"显示/隐藏历史翻译和调试输出": "Tarihi çevirimi ve arızasızlandırma çıkışını göster/gizle", "显示/隐藏历史翻译和调试输出": "Tarihi çevirimi ve arızasızlandırma çıkışını göster/gizle",
"历史翻译和调试输出": "Tarihi çeviri ve hata ayıklama çıkışı", "历史翻译和调试输出": "Tarihi çeviri ve hata ayıklama çıkışı",
@ -701,5 +700,10 @@
"语言自适应": "Dil Yönetimi", "语言自适应": "Dil Yönetimi",
"去除重复字符": "Çift karakterleri sil", "去除重复字符": "Çift karakterleri sil",
"游戏内叠加层": "Oyun üzerindeki katı", "游戏内叠加层": "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."
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Навчення розробки Sakura", "Sakura部署教程": "Навчення розробки Sakura",
"Github仓库": "Сховище Github", "Github仓库": "Сховище Github",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Переклад за допомогою інформації, наданої у попередньому тексті (зазвичай, з деяким покращенням ефективності, але це може призвести до повільнішого перекладу)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "Переклад за допомогою інформації, наданої у попередньому тексті (зазвичай, з деяким покращенням ефективності, але це може призвести до повільнішого перекладу)",
"范围选取遮罩透明度": "Прозорість маски вибору діапазону",
"文本缓冲区长度": "Довжина текстового буфера", "文本缓冲区长度": "Довжина текстового буфера",
"显示/隐藏历史翻译和调试输出": "Показувати/сховати історичний переклад і вивід зневаджування", "显示/隐藏历史翻译和调试输出": "Показувати/сховати історичний переклад і вивід зневаджування",
"历史翻译和调试输出": "Історічний переклад і вивід зневаджування", "历史翻译和调试输出": "Історічний переклад і вивід зневаджування",
@ -701,5 +700,10 @@
"语言自适应": "Адаптація мови", "语言自适应": "Адаптація мови",
"去除重复字符": "Вилучити дублікатні символи", "去除重复字符": "Вилучити дублікатні символи",
"游戏内叠加层": "Шир перекладу у грі", "游戏内叠加层": "Шир перекладу у грі",
"内联效果参数": "Параметри вхідних ефектів" "内联效果参数": "Параметри вхідних ефектів",
"获取最新提取器核心&错误反馈&游戏支持": "Отримати останню підтримку гри для відтворення & помилок ядра екстрактора",
"外部缩放软件": "Зовнішнє програмне забезпечення масштабу",
"Hook Magpie进程使其不会退出缩放": "Процес Hook Magpie забороняє їй вийти з масштабу",
"Hook LosslessScaling进程使其不会退出缩放": "Процес безвтратного розміруScaling забороняє їй вийти з розміру",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": "Не вдалося знайти англійську модель розпізнавання, використовуючи японську модель як заміну, може бути неефективною"
} }

View File

@ -662,7 +662,6 @@
"Sakura部署教程": "Hướng dẫn triển khai Sakura", "Sakura部署教程": "Hướng dẫn triển khai Sakura",
"Github仓库": "Kho Github", "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)", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "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", "文本缓冲区长度": "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", "显示/隐藏历史翻译和调试输出": "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", "历史翻译和调试输出": "Lịch sử dịch và gỡ lỗi đầu ra",
@ -701,5 +700,10 @@
"语言自适应": "Thích nghi ngôn ngữ", "语言自适应": "Thích nghi ngôn ngữ",
"去除重复字符": "Loại bỏ các ký tự trùng lặp", "去除重复字符": "Loại bỏ các ký tự trùng lặp",
"游戏内叠加层": "Lớp phủ trong trò chơi", "游戏内叠加层": "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"
} }

View File

@ -661,7 +661,6 @@
"Sakura部署教程": "", "Sakura部署教程": "",
"Github仓库": "", "Github仓库": "",
"利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "", "利用上文信息翻译(通常会有一定的效果提升,但会导致变慢)": "",
"范围选取遮罩透明度": "",
"文本缓冲区长度": "", "文本缓冲区长度": "",
"显示/隐藏历史翻译和调试输出": "", "显示/隐藏历史翻译和调试输出": "",
"历史翻译和调试输出": "", "历史翻译和调试输出": "",
@ -701,5 +700,10 @@
"API接口格式如下可根据自己的设置进行修改IP和端口。": "", "API接口格式如下可根据自己的设置进行修改IP和端口。": "",
"去除重复字符": "", "去除重复字符": "",
"游戏内叠加层": "", "游戏内叠加层": "",
"内联效果参数": "" "内联效果参数": "",
"获取最新提取器核心&错误反馈&游戏支持": "",
"外部缩放软件": "",
"Hook Magpie进程使其不会退出缩放": "",
"Hook LosslessScaling进程使其不会退出缩放": "",
"找不到英语识别模型,正在使用日语模型作为代替,可能效果不佳": ""
} }

View File

@ -6,7 +6,7 @@ if x86:
nuitkadist=r'..\build\x86\LunaTranslator_main.dist' nuitkadist=r'..\build\x86\LunaTranslator_main.dist'
targetdir=r'..\build\LunaTranslator_x86' targetdir=r'..\build\LunaTranslator_x86'
launch=r'..\plugins\builds\_x86' launch=r'..\plugins\builds\_x86'
downlevel=f'C:\Windows\SysWOW64\downlevel' downlevel=r'C:\Windows\SysWOW64\downlevel'
target='LunaTranslator_x86.zip' target='LunaTranslator_x86.zip'
baddll='DLL64' baddll='DLL64'
else: else:
@ -15,7 +15,7 @@ else:
launch=r'..\plugins\builds\_x64' launch=r'..\plugins\builds\_x64'
nuitkadist=r'..\build\x64\LunaTranslator_main.dist' nuitkadist=r'..\build\x64\LunaTranslator_main.dist'
targetdir=r'..\build\LunaTranslator' targetdir=r'..\build\LunaTranslator'
downlevel=f'C:\Windows\system32\downlevel' downlevel=r'C:\Windows\system32\downlevel'
targetdir_in=rf'{targetdir}\LunaTranslator' targetdir_in=rf'{targetdir}\LunaTranslator'
def get_import_table(file_path): def get_import_table(file_path):
pe = pefile.PE(file_path) pe = pefile.PE(file_path)

View File

@ -28,4 +28,4 @@ add_subdirectory(exec)
add_subdirectory(shareddllproxy) add_subdirectory(shareddllproxy)
add_subdirectory(winrtutils) add_subdirectory(winrtutils)
add_subdirectory(winsharedutils) add_subdirectory(winsharedutils)
add_subdirectory(hookmagpie)

1
plugins/hookmagpie/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
minhook

View File

@ -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()

View File

@ -0,0 +1,295 @@
#include <iostream>
#include<windows.h>
#include<thread>
#include<detours.h>
#include<string>
#include<assert.h>
#include<MinHook.h>
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<std::remove_pointer<HANDLE>::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<typename CHAR_T>
static void ToLowerCase(std::basic_string<CHAR_T>& 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;
}