Skip to content

Instantly share code, notes, and snippets.

@odie5533
Last active August 14, 2017 05:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odie5533/f638611e6fda0d846b0969b4dfcb11b7 to your computer and use it in GitHub Desktop.
Save odie5533/f638611e6fda0d846b0969b4dfcb11b7 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.9
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setEnabled(True)
MainWindow.resize(380, 110)
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.frame = QtWidgets.QFrame(self.centralWidget)
self.frame.setGeometry(QtCore.QRect(0, 0, 380, 110))
palette = QtGui.QPalette()
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
brush.setStyle(QtCore.Qt.SolidPattern)
palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
self.frame.setPalette(palette)
self.frame.setAutoFillBackground(True)
self.frame.setObjectName("frame")
self.labelAchievement = QtWidgets.QLabel(self.frame)
self.labelAchievement.setGeometry(QtCore.QRect(110, 20, 261, 51))
font = QtGui.QFont()
font.setPointSize(12)
font.setBold(True)
font.setWeight(75)
self.labelAchievement.setFont(font)
self.labelAchievement.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.labelAchievement.setWordWrap(True)
self.labelAchievement.setObjectName("labelAchievement")
self.labelDescription = QtWidgets.QLabel(self.frame)
self.labelDescription.setGeometry(QtCore.QRect(110, 58, 261, 41))
font = QtGui.QFont()
font.setPointSize(10)
self.labelDescription.setFont(font)
self.labelDescription.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.labelDescription.setWordWrap(True)
self.labelDescription.setObjectName("labelDescription")
self.label = QtWidgets.QLabel(self.frame)
self.label.setGeometry(QtCore.QRect(10, 10, 90, 90))
self.label.setText("")
self.label.setPixmap(QtGui.QPixmap("Youngling.png"))
self.label.setScaledContents(True)
self.label.setObjectName("label")
MainWindow.setCentralWidget(self.centralWidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "RetroAchievements"))
self.labelAchievement.setText(_translate("MainWindow", "Achievement"))
self.labelDescription.setText(_translate("MainWindow", "Description"))
import ctypes, win32ui, win32process, win32api, win32event, win32gui, win32con
from ctypes import wintypes
import datetime, sys, signal
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QDesktopWidget
from mainwindow import Ui_MainWindow
PROCESS_ALL_ACCESS = 0x1F0FFF
ReadProcessMemory = ctypes.WinDLL('kernel32',use_last_error=True).ReadProcessMemory
ReadProcessMemory.argtypes = [wintypes.HANDLE, wintypes.LPCVOID, wintypes.LPVOID,
ctypes.c_size_t,ctypes.POINTER(ctypes.c_size_t)]
ReadProcessMemory.restype = wintypes.BOOL
SwEp1RacerAchievements = {
"DETECTION": {
"windowName": "Episode I Racer"
},
"FINISHED_A_RACE": {"achieved":False,
"name":"Youngling",
"desc":"You finished your first race!",
"requirements":{
"core": {},
"alt1": {1:{
"size": "string7",
"memory": 0xE2C805, # ADDRESS_TALLY_STRING
"cmp": "=",
"value": b"Total: "
}},
"alt2": {1:{
"size": "string7",
"memory": 0xE2C384, # ADDRESS_RESULTS_STRING,
"cmp": "=",
"value": b"Results"
}}
}},
"FIRSTPLACE_RACE1": {"achieved":False, "name":"Boonta Training Course Veteran", "desc":"First place in Boonta Training Course!",
"requirements":{
"core": {1:{
"size": "byte",
"memory": 0xEA02B0, # ADDRESS_RACE_SELECT,
"cmp": "=",
"value": 0
},
2:{
"size": "byte",
"memory": 0xE29C1C, # ADDRESS_PLACE,
"cmp": "=",
"value": 1
}
},
"alt1": {1:{
"size": "string7",
"memory": 0xE2C805, # ADDRESS_TALLY_STRING
"cmp": "=",
"value": b"Total: "
}},
"alt2": {1:{
"size": "string7",
"memory": 0xE2C384, # ADDRESS_RESULTS_STRING,
"cmp": "=",
"value": b"Results"
}}
}},
"FIRSTPLACE_RACE2": {"achieved":False, "name":"Mon Gazza Speedway Veteran", "desc":"First place in Mon Gazza Speedway!",
"requirements":{
"core": {1:{
"size": "byte",
"memory": 0xEA02B0, # ADDRESS_RACE_SELECT,
"cmp": "=",
"value": 16
},
2:{
"size": "byte",
"memory": 0xE29C1C, # ADDRESS_PLACE,
"cmp": "=",
"value": 1
}
},
"alt1": {1:{
"size": "string7",
"memory": 0xE2C805, # ADDRESS_TALLY_STRING
"cmp": "=",
"value": b"Total: "
}},
"alt2": {1:{
"size": "string7",
"memory": 0xE2C384, # ADDRESS_RESULTS_STRING,
"cmp": "=",
"value": b"Results"
}}
}},
}
def readByte(process, address):
buffer = ctypes.create_string_buffer(1)
bytes_read = ctypes.c_size_t()
ReadProcessMemory(process.handle, address, buffer, 1, ctypes.byref(bytes_read))
last_err = ctypes.get_last_error()
if last_err:
print("Error readByte:", last_err)
return None
return buffer.raw[0]
def readString(process, address, length):
buffer = ctypes.create_string_buffer(length)
bytes_read = ctypes.c_size_t()
ReadProcessMemory(process.handle, address, buffer, length, ctypes.byref(bytes_read))
last_err = ctypes.get_last_error()
if last_err:
print("Error readString:", last_err)
return None
i = buffer.raw.find(b'\x00')
if i == -1:
return buffer.raw
return buffer.raw[:i]
class PCRAApp(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(PCRAApp, self).__init__(parent)
self.setupUi(self)
signal.signal(signal.SIGINT, self.sigint_handler)
self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowTransparentForInput)
self.check_timer = None
self.swep1timer = None
self.should_close = False
ag = QDesktopWidget().availableGeometry()
x = ag.width() - self.width() - 20
y = ag.height() - self.height() - 20
self.move(x, y)
#self.unlockAchievement("FINISHED_A_RACE", SwEp1RacerAchievements["FINISHED_A_RACE"])
self.check_games()
def sigint_handler(self, *args):
self.should_close = True
self.close()
QtCore.QCoreApplication.instance().quit()
def printWindowStyles(self):
print("WindowStyle 0x%X" % self.getWindowStyle())
print("WindowStyleEx 0x%X" % self.getWindowStyleEx())
def hwnd(self):
#win32ui.FindWindow(None, self.windowTitle()).GetSafeHwnd()
return self.winId()
def getWindowStyleEx(self):
return win32gui.GetWindowLong(self.hwnd(), win32con.GWL_EXSTYLE )
def getWindowStyle(self):
return win32gui.GetWindowLong(self.hwnd(), win32con.GWL_STYLE )
"""def make_transparent(self):
lExStyle = self.getWindowStyleEx()
lExStyle = lExStyle | win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
lExStyle = lExStyle & ~(win32con.WS_EX_DLGMODALFRAME | win32con.WS_EX_CLIENTEDGE | win32con.WS_EX_STATICEDGE)
print("lExStyle", lExStyle)
win32gui.SetWindowLong(self.hwnd(), win32con.GWL_EXSTYLE, lExStyle )
lStyle = self.getWindowStyle()
lStyle = lStyle & ~(win32con.WS_CAPTION | win32con.WS_THICKFRAME | win32con.WS_MINIMIZE | win32con.WS_MAXIMIZE | win32con.WS_SYSMENU)
print("lstyle", lStyle)
win32gui.SetWindowLong(self.hwnd(), win32con.GWL_STYLE, lStyle )
#self.setFixedSize(self.width()-16, self.height()-38)
win32gui.SetWindowPos(self.hwnd(), win32con.HWND_TOP, 0, 0, self.width(), self.height(), win32con.SWP_NOMOVE)
#SetLayeredWindowAttributes(self.hwnd(), win32api.RGB(255, 255, 255), 0, win32con.LWA_COLORKEY)"""
def unlockAchievement(self, ach_name, ach):
if ach['achieved'] == False:
ach['achieved'] = True
msg = "Unlocking achievement: " + ach['name'] + " - " + ach['desc']
print(msg)
self.labelAchievement.setText(ach['name'])
self.labelDescription.setText(ach['desc'])
self.printWindowStyles()
self.show()
self.printWindowStyles()
#self.plainTextEdit.appendPlainText(msg)
#vsb = self.plainTextEdit.verticalScrollBar()
#vsb.setValue(vsb.maximum())
def swep1racer_parsetime(self, string):
if string.count(":") == 2:
x = datetime.datetime.strptime(string,'%H:%M:%S.%f')
if string.count(":") == 1:
x = datetime.datetime.strptime(string,'%M:%S.%f')
if string.count(":") == 0:
x = datetime.datetime.strptime(string,'%S.%f')
return datetime.timedelta(hours=x.hour,
minutes=x.minute,
seconds=x.second,
microseconds=x.microsecond).total_seconds()
def testRequirement(self, proc, req):
if req["size"].startswith("string"):
s_len = int(req["size"][6:])
return readString(proc, req["memory"], s_len) == req["value"]
if req["size"] == "byte":
return readByte(proc, req["memory"]) == req["value"]
def testReqGroup(self, proc, group):
if len(group) == 0:
return True
reqResults = [self.testRequirement(proc, group[i]) for i in group]
return all(reqResults)
def checkAchievement(self, proc, ach_name, ach):
if "requirements" not in ach:
return
reqs = ach["requirements"]
altRes = [self.testReqGroup(proc, reqs[grp]) for grp in reqs if grp.startswith("alt")]
if self.testReqGroup(proc, reqs["core"]):
if len(altRes) == 0 or any(altRes):
self.unlockAchievement(ach_name, ach)
def checkAchievements(self, proc, achievements):
for ach_name, ach in achievements.items():
self.checkAchievement(proc, ach_name, ach)
def check_swep1racer(self):
if self.should_close:
return
if win32event.WaitForSingleObject(self.swep1process, 0) == 0:
self.swep1timer = None
return
self.checkAchievements(self.swep1process, SwEp1RacerAchievements)
self.swep1timer = QtCore.QTimer()
self.swep1timer.timeout.connect(self.check_swep1racer)
self.swep1timer.start(200)
def is_swep1racer_running(self):
try:
HWND = win32ui.FindWindow(None, "Episode I Racer").GetSafeHwnd()
PID = win32process.GetWindowThreadProcessId(HWND)[1]
return win32api.OpenProcess(PROCESS_ALL_ACCESS, 0, PID)
except win32ui.error:
return False
def check_games(self):
if self.should_close:
return
if self.swep1timer is None:
self.swep1process = self.is_swep1racer_running()
if self.swep1process != False:
self.check_swep1racer()
self.check_timer = QtCore.QTimer()
self.check_timer.timeout.connect(self.check_games)
self.check_timer.start(500)
def closeEvent(self, event):
self.should_close = True
def main():
app = QtWidgets.QApplication(sys.argv)
form = PCRAApp()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment