Advertisement
djvj

Untitled

Jan 17th, 2016
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 158.74 KB | None | 0 0
  1. MCRC=50647777
  2. MVersion=1.3.8
  3.  
  4. StartModule(){
  5. Global gameSectionStartTime,gameSectionStartHour,skipChecks,dbName,romPath,romName,romExtension,systemName,MEmu,MEmuV,MURL,MAuthor,MVersion,MCRC,iCRC,MSystem,romMapTable,romMappingLaunchMenuEnabled,romMenuRomName,sevenZEnabled,hideCursor,toggleCursorKey,servoStikEnabled,ledblinkyEnabled,winVer,setResolution,zz
  6. Global mgEnabled,mgOnLaunch,mgCandidate,mgLaunchMenuActive,MultiGame_Running,keyboardEncoder,keyboardEncoderEnabled,ultraMapFullPath,winIPACFullPath
  7. Global rIniIndex,globalPluginsFile,sysPluginsFile
  8. Log("StartModule - Started")
  9. Log("StartModule - MEmu: " . MEmu . "`r`n`t`t`t`t`tMEmuV: " . MEmuV . "`r`n`t`t`t`t`tMURL: " . MURL . "`r`n`t`t`t`t`tMAuthor: " . MAuthor . "`r`n`t`t`t`t`tMVersion: " . MVersion . "`r`n`t`t`t`t`tMCRC: " . MCRC . "`r`n`t`t`t`t`tiCRC: " . iCRC . "`r`n`t`t`t`t`tMID: " . MID . "`r`n`t`t`t`t`tMSystem: " . MSystem)
  10. If InStr(MSystem,systemName)
  11. Log("StartModule - You have a supported System Name for this module: """ . systemName . """")
  12. Else
  13. Log("StartModule - You have an unsupported System Name for this module: """ . systemName . """. Only the following System Names are suppported: """ . MSystem . """",2)
  14.  
  15. winVer := If A_Is64bitOS ? "64" : "32" ; get windows version
  16.  
  17. ;-----------------------------------------------------------------------------------------------------------------------------------------
  18. ; Plugin Specific Settings from Settings \ Global Plugins.ini and Settings \ %systemName% \ Plugins.ini
  19. ;-----------------------------------------------------------------------------------------------------------------------------------------
  20. rIniIndex := {} ; initialize the RIni array
  21. globalPluginsFile := A_ScriptDir . "\Settings\Global Plugins.ini"
  22. If !FileExist(globalPluginsFile)
  23. FileAppend,, %globalPluginsFile% ; create blank ini
  24. RIni_Read(8,globalPluginsFile)
  25. rIniIndex[8] := globalPluginsFile ; assign to array
  26.  
  27. sysPluginsFile := A_ScriptDir . "\Settings\" . systemName . "\Plugins.ini"
  28. If !FileExist(sysPluginsFile)
  29. FileAppend,, %sysPluginsFile% ; create blank ini
  30. RIni_Read(9,sysPluginsFile)
  31. rIniIndex[9] := sysPluginsFile ; assign to array
  32.  
  33. Gosub, PluginInit ; initialize plugin vars
  34. ; Gosub, ReadFEGameInfo ; read plugin data
  35. ;-----------------------------------------------------------------------------------------------------------------------------------------
  36.  
  37. If (mgEnabled = "true" && mgOnLaunch = "true" && mgCandidate) { ; only if user has mgOnLaunch enabled
  38. mgLaunchMenuActive := true
  39. Log("StartModule - MultiGame_On_Launch execution started.",4)
  40. Gosub, StartMulti
  41. Sleep, 200
  42. Loop {
  43. If !MultiGame_Running
  44. Break
  45. }
  46. mgLaunchMenuActive := false
  47. Log("StartModule - MultiGame_On_Launch execution ended.",4)
  48. }
  49. If (romMappingLaunchMenuEnabled = "true" && romMapTable.MaxIndex()) ; && romMapMultiRomsFound)
  50. CreateRomMappingLaunchMenu%zz%(romMapTable)
  51. ; msgbox dbName: %dbName%`nromName: %romName%`nromMenuRomName: %romMenuRomName%`nsevenZEnabled: %sevenZEnabled%`nskipChecks: %skipChecks%
  52. If (skipChecks != "false" && romMenuRomName && sevenZEnabled = "false") ; this is to support the scenario where Rom Map Launch Menu can send a rom that does not exist on disk or in the archive (mame clones)
  53. { Log("StartModule - Setting romName to the game picked from the Launch Menu: " . romMenuRomName,4)
  54. romName := romMenuRomName
  55. } Else If romName && romMapTable.MaxIndex()
  56. { Log("StartModule - Leaving romName as is because Rom Mapping filled it with an Alternate_Rom_Name: " . romName,4)
  57. romName := romName ; When Rom Mapping is used but no Alternate_Archive_Name key exists yet Alternate_Rom_Name key(s) were used.
  58. } Else If romMapTable.MaxIndex()
  59. { Log("StartModule - Not setting romName because Launch Menu was used and 7z will take care of it.",4)
  60. romName := "" ; If a romMapTable exists with roms, do not fill romName yet as 7z will take care of that.
  61. } Else
  62. { Log("StartModule - Setting romName to the dbName sent to RocketLauncher: " . dbName,4)
  63. romName := dbName ; Use dbName if previous checks are false
  64. }
  65.  
  66. If (setResolution != "")
  67. SetDisplaySettings(setResolution)
  68.  
  69. If RegExMatch(hideCursor,"i)true|do_not_restore")
  70. SystemCursor("Off")
  71. Else If RegExMatch(hideCursor,"i)custom|custom_do_not_restore") {
  72. cursor := GetRLMediaFiles("Cursors","cur|ani") ;load cursor file for the system if they exist
  73. If cursor
  74. SetSystemCursor(Cursor) ; replace system cursors
  75. }
  76. If toggleCursorKey
  77. XHotKeywrapper(toggleCursorKey,"ToggleCursor")
  78. If (ledblinkyEnabled = "All")
  79. LEDBlinky("START")
  80. KeymapperProfileSelect("START", keyboardEncoder, %keyboardEncoder%FullPath, "ipc", "keyboard")
  81. KeymapperProfileSelect("START", "UltraMap", ultraMapFullPath, "ugc")
  82. If (servoStikEnabled = 4 || servoStikEnabled = 8)
  83. ServoStik(servoStikEnabled) ; handle servostiks on start
  84.  
  85. ; romName := If romName ? romName : If romMapTable.MaxIndex() ? "" : dbName ; OLD METHOD, keeping this here until the split apart conditionals have been tested enough. ; if romName was filled at some point, use it, Else If a romMapTable exists with roms, do not fill romName yet as 7z will take care of that. Use dbName if previous checks are false
  86. Gui, show,Hide,RocketLauncherMessageReceiver ; creating hidden GUI to receive RocketLauncher messages
  87. OnMessage(0x4a, "ReceiveMessage")
  88. BroadcastMessage("RocketLauncher Message: Welcome! :)")
  89. gameSectionStartTime := A_TickCount
  90. gameSectionStartHour := A_Now
  91. ; msgbox % "romPath: " . romPath . "`nromName: " . romName . "`nromExtension: " . romExtension . "`nromMenuRomName: " . romMenuRomName . "`nromMapTable.MaxIndex(): " . romMapTable.MaxIndex()
  92. Log("StartModule - Ended")
  93. }
  94.  
  95. ; ExitModule function in case we need to call anything on the module's exit routine, like UpdateStatistics for Pause or UnloadKeymapper
  96. ExitModule(){
  97. Global statisticsEnabled,keymapperEnabled,keymapper,keymapperAHKMethod,keymapperLoaded,logShowCommandWindow,pToken,cmdWindowObj,mouseCursorHidden,cursor,hideCursor,rocketLauncherIsExiting,servoStikExitMode,ledblinkyEnabled,zz
  98. Global JoyIDsEnabled,JoyIDsPreferredControllersOnExit,keyboardEncoder,keyboardEncoderEnabled,ultraMapFullPath,winIPACFullPath
  99. Log("ExitModule - Started")
  100. rocketLauncherIsExiting := 1 ; notifies rest of the thread that the exit routine was triggered
  101. If (statisticsEnabled = "true")
  102. Gosub, UpdateStatistics
  103. If (keymapperEnabled = "true" && keymapperLoaded)
  104. RunKeyMapper%zz%("unload",keymapper)
  105. If keymapperAHKMethod = External
  106. RunAHKKeymapper%zz%("unload")
  107. If (JoyIDsEnabled = "true" && JoyIDsPreferredControllersOnExit)
  108. LoadPreferredControllers%zz%(JoyIDsPreferredControllersOnExit)
  109. If (hideCursor = "custom" and cursor)
  110. RestoreCursors() ; retore default system cursors
  111. If mouseCursorHidden ; just in case
  112. SystemCursor("On")
  113. If (ledblinkyEnabled = "All")
  114. LEDBlinky("END")
  115. KeymapperProfileSelect("END", keyboardEncoder, %keyboardEncoder%FullPath, "ipc", "keyboard")
  116. KeymapperProfileSelect("END", "UltraMap", ultraMapFullPath, "ugc")
  117. If (servoStikExitMode = 4 || servoStikExitMode = 8)
  118. ServoStik(servoStikExitMode) ; handle servostiks on exit
  119. If logShowCommandWindow = true
  120. Loop {
  121. If !cmdWindowObj[A_Index,"Name"]
  122. Break
  123. Else {
  124. Log("ExitModule - Closing command window: " . cmdWindowObj[A_Index,"Name"] . " PID: " . cmdWindowObj[A_Index,"PID"],4)
  125. Process("Close", cmdWindowObj[A_Index,"Name"]) ; close each opened cmd.exe
  126. }
  127. }
  128. BroadcastMessage("RocketLauncher Message: Goodbye! :(")
  129. Gdip_Shutdown(pToken) ; gdi+ may now be shutdown on exiting the thread
  130. Log("ExitModule - Ended")
  131. Log("End of Module Logs",,,1)
  132. ExitApp
  133. }
  134.  
  135. WinWait(winTitle,winText="",secondsToWait=30,excludeTitle="",excludeText=""){
  136. Global detectFadeErrorEnabled, logLevel
  137. If logLevel > 3
  138. GetActiveWindowStatus()
  139. Log("WinWait - Waiting for """ . winTitle . """")
  140. WinWait, %winTitle% ,%winText% , %secondsToWait% , %excludeTitle% ,%excludeText%
  141. curErr := ErrorLevel ; have to store this because GetActiveWindowStatus will reset it
  142. If logLevel > 3
  143. GetActiveWindowStatus()
  144. If (curErr and detectFadeErrorEnabled = "true")
  145. ScriptError("There was an error waiting for the window """ . winTitle . """. Please check you have the correct version emulator installed for this module, followed any notes in the module, and have this emulator working outside your Frontend first. Also turn off Fade to see if you are hiding your problem.",10)
  146. Else If (curErr and detectFadeErrorEnabled != "true")
  147. Log("There was an error waiting for the window """ . winTitle . """. Please check you have the correct version emulator installed for this module, followed any notes in the module, and have this emulator working outside your Frontend first. Also turn off Fade to see if you are hiding your problem.",3)
  148. Return curErr
  149. }
  150.  
  151. WinWaitActive(winTitle,winText="",secondsToWait=30,excludeTitle="",excludeText=""){
  152. Global detectFadeErrorEnabled, logLevel, emulatorProcessID, emulatorVolumeObject, emulatorInitialMuteState, fadeMuteEmulator, fadeIn
  153. If (logLevel > 3)
  154. GetActiveWindowStatus()
  155. Log("WinWaitActive - Waiting for """ . winTitle . """")
  156. WinWaitActive, %winTitle% ,%winText% , %secondsToWait% , %excludeTitle% ,%excludeText%
  157. curErr := ErrorLevel ; have to store this because GetActiveWindowStatus will reset it
  158. If (logLevel > 3)
  159. GetActiveWindowStatus()
  160. If (curErr and detectFadeErrorEnabled = "true")
  161. ScriptError("There was an error waiting for the window """ . winTitle . """ to become active. Please check you have the correct version emulator installed for this module, followed any notes in the module, and have this emulator working outside your Frontend first. Also turn off Fade to see if you are hiding your problem.",10)
  162. Else If (curErr and detectFadeErrorEnabled != "true")
  163. Log("There was an error waiting for the window """ . winTitle . """ to become active. Please check you have the correct version emulator installed for this module, followed any notes in the module, and have this emulator working outside your Frontend first. Also turn off Fade to see if you are hiding your problem.",3)
  164. If !curErr
  165. {
  166. WinGet emulatorProcessID, PID, %winTitle%
  167. emulatorVolumeObject := GetVolumeObject(emulatorProcessID)
  168. If ((fadeMuteEmulator = "true") and (fadeIn = "true")){
  169. getMute(emulatorInitialMuteState, emulatorVolumeObject)
  170. setMute(1, emulatorVolumeObject)
  171. }
  172. }
  173. Return curErr
  174. }
  175.  
  176. WinWaitClose(winTitle,winText="",secondsToWait="",excludeTitle="",excludeText=""){
  177. Log("WinWaitClose - Waiting for """ . winTitle . """ to close")
  178. WinWaitClose, %winTitle% ,%winText% , %secondsToWait% , %excludeTitle% ,%excludeText%
  179. Return ErrorLevel
  180. }
  181.  
  182. WinClose(winTitle,winText="",secondsToWait="",excludeTitle="",excludeText=""){
  183. Log("WinClose - Closing: " . winTitle)
  184. WinClose, %winTitle%, %winText% , %secondsToWait%, %excludeTitle%, %excludeText%
  185. If (secondsToWait = "" || !secondsToWait)
  186. secondsToWait := 2 ; need to always have some timeout for this command otherwise it will wait forever
  187. WinWaitClose, %winTitle%, %winText% , %secondsToWait%, %excludeTitle%, %excludeText% ; only WinWaitClose reports an ErrorLevel
  188. Return ErrorLevel
  189. }
  190.  
  191. RunWait(target,workingDir="",options=0,ByRef outputVarPID=""){
  192. Global errorLevelReporting
  193. options := If options = 1 ? "useErrorLevel" : options ; enable or disable error level
  194. Log("RunWait - Started - running: " . workingDir . "\" . target)
  195. RunWait, %target%, %workingDir%, %options%, outputVarPID
  196. curErr := ErrorLevel ; store error level immediately
  197. Log("RunWait - """ . target . """ Process ID: " . outputVarPID . " and ErrorLevel reported as: " . curErr, 4)
  198. Return curErr
  199. }
  200.  
  201. ; To disable inputBlocker on a specific Run call, set inputBlocker to 0, or to force it a specified amount of seconds (upto 30), set it to that amount.
  202. ; By default, options will enable all calls of Run() to return errorlevel within the function. However, it will only be returned if errorLevelReporting is true
  203. ; bypassCmdWindow - some apps will never work with the command window, like xpadder. enable this argument on these Run calls so it doesn't get caught here
  204. Run(target,workingDir="",options=0,ByRef outputVarPID="",inputBlocker=1,bypassCmdWindow=0,disableLogging=0){
  205. Static cmdWindowCount
  206. Global logShowCommandWindow,logCommandWindow,cmdWindowObj,blockInputTime,blockInputFile,errorLevelReporting
  207. options := If options = 1 ? "useErrorLevel" : options ; enable or disable error level
  208. If disableLogging
  209. Log("Run - Running hidden executable in " . workingDir)
  210. Else
  211. Log("Run - Running: " . workingDir . "\" . target)
  212. If (blockInputTime && inputBlocker = 1) ; if user set a block time, use the user set length
  213. blockTime := blockInputTime
  214. Else If (inputBlocker > 1) ; if module called for a block, use that amount
  215. blockTime := inputBlocker
  216. Else ; do not block input
  217. blockTime := ""
  218. If blockTime
  219. { Log("Run - Blocking Input for: " . blockTime . " seconds")
  220. Run, %blockInputFile% %blockTime%
  221. }
  222. If !cmdWindowObj
  223. cmdWindowObj := Object() ; initialize object, this is used so all the command windows can be properly closed on exit
  224. If (logShowCommandWindow = "true" && !bypassCmdWindow) {
  225. Run, %ComSpec% /k, %workingDir%, %options%, outputVarPID ; open a command window (cmd.exe), starting in the directory of the target executable
  226. curErr := ErrorLevel ; store error level immediately
  227. If errorLevelReporting = true
  228. { Log("Run - Error Level for " . ComSpec . " reported as: " . curErr, 4)
  229. errLvl := curErr ; allows the module to handle the error level
  230. }
  231. Log("Run - Showing Command Window to troubleshoot launching. ProcessID: " . outputVarPID)
  232. WinWait, ahk_pid %outputVarPID%
  233. WinActivate, ahk_pid %outputVarPID%
  234. WinWaitActive, ahk_pid %outputVarPID%,,2
  235. If ErrorLevel {
  236. WinSet, AlwaysOnTop, On, ahk_pid %outputVarPID%
  237. WinActivate, ahk_pid %outputVarPID%
  238. WinWaitActive, ahk_pid %outputVarPID%,,2
  239. If ErrorLevel
  240. ScriptError("Could not put focus onto the command window. Please try turning off Fade In if you have it enabled in order to see it")
  241. }
  242. WinGet, procName, ProcessName, ahk_pid %outputVarPID% ; get the name of the process (which should usually be cmd.exe)
  243. mapObjects[currentObj,"type"] := "database"
  244. cmdWindowCount++
  245. cmdWindowObj[cmdWindowCount,"Name"] := procName ; store the ProcessName being ran
  246. cmdWindowObj[cmdWindowCount,"PID"] := outputVarPID ; store the PID of the application being ran
  247. foundPos := RegExMatch(target,".*\.(exe|bat)",targetExeOnly) ; grab only the exe or bat file from the supplied target
  248. exeLen := StrLen(targetExeOnly) ; get length of exe name
  249. params := SubStr(target, exeLen+1) ; grab optional params out of supplied target
  250. If InStr(targetExeOnly, A_Space)
  251. target := """" . targetExeOnly . """" . params
  252. If (logCommandWindow = "true")
  253. SendInput, {Raw}%target% 1>"%A_ScriptDir%\command_%cmdWindowCount%_output.log" 2>"%A_ScriptDir%\command_%cmdWindowCount%_error.log" ; send the text to the command window and log the output to file
  254. Else
  255. SendInput, {Raw}%target% ; send the text to the command window and run it
  256. Send, {Enter}
  257. } Else {
  258. Run, %target%, %workingDir%, %options%, outputVarPID
  259. curErr := ErrorLevel ; store error level immediately
  260. If errorLevelReporting = true
  261. { Log("Run - Error Level for " . target . " reported as: " . curErr, 4)
  262. errLvl := curErr ; allows the module to handle the error level
  263. }
  264. }
  265. If disableLogging
  266. Log("Run - ""Hidden executable"" Process ID: " . outputVarPID, 4)
  267. Else
  268. Log("Run - """ . target . """ Process ID: " . outputVarPID, 4)
  269. Return errLvl
  270. }
  271.  
  272. Process(cmd,name,param=""){
  273. Log("Process - " . cmd . A_Space . name . A_Space . param)
  274. Process, %cmd%, %name%, %param%
  275. Return ErrorLevel
  276. }
  277.  
  278. SetKeyDelay(delay="",pressDur="",play="") {
  279. Global pressDuration
  280. If (delay = "") ; -1 is the default delay for play mode and 10 for event mode when none is supplied
  281. delay := (If play = "" ? 10 : -1)
  282. If (pressDur = "") ; -1 is the default pressDur when none is supplied
  283. pressDur := -1
  284.  
  285. Log("SetKeyDelay - Current delay is " . A_KeyDelay . ". Current press duration is " . pressDuration . ". Delay will now be set to """ . delay . """ms for a press duration of """ . pressDur . """", 4)
  286. SetKeyDelay, %delay%, %pressDur%, %play%
  287. pressDuration := pressDur ; this is so the current pressDuration can be monitored outside the function
  288. }
  289.  
  290. ; Replaces standard ahk IniRead calls
  291. ; Will not let ERROR be returned, returns no value instead
  292. ; If errormsg is set, will trigger ScriptError instead of returning no or default value
  293. IniRead(file,section,key,defaultvalue="",errorMsg="") {
  294. Log("IniRead - SECTION: [" . section . "] - KEY: " . key . " - VALUE: " . value . " - FILE: " . file,4)
  295. IniRead, v, %file%, %section%, %key%, %defaultvalue%
  296. If (v = "ERROR" || v = A_Space) { ; if key does not exist or is a space, delete ERROR as the value
  297. If errorMsg
  298. ScriptError(errorMsg)
  299. Else {
  300. If defaultValue = %A_Space% ; this prevents the var from existing when it's actually blank
  301. defaultValue := ""
  302. Return defaultValue
  303. }
  304. }
  305. Return v
  306. }
  307.  
  308. ; Replaces standard ahk IniWrite calls
  309. ; compare = if used, only writes new value if existing value differs
  310. IniWrite(value,file,section,key,compare="") {
  311. If compare {
  312. IniRead, v, %file%, %section%, %key%
  313. If (v != value) {
  314. IniWrite, %value%, %file%, %section%, %key%
  315. err := ErrorLevel
  316. Log("IniWrite - ini updated due to differed value. SECTION: [" . section . "] - KEY: " . key . " - Old: " . v . " | New: " . value)
  317. } Else
  318. Log("IniWrite - ini value already correct. SECTION: [" . section . "] - KEY: " . key . " - Value: " . value,4)
  319. } Else {
  320. IniWrite, %value%, %file%, %section%, %key%
  321. err := ErrorLevel
  322. Log("IniWrite - SECTION: [" . section . "] - KEY: " . key . " - VALUE: " . value . " - FILE: " . file)
  323. }
  324. If err
  325. Log("IniWrite - There was an error writing to the ini",3)
  326. Return err ; returns 1 if there was an error
  327. }
  328.  
  329. ; Mainly used in modules to read module.ini settings so multiple sections of an ini can be read of the same key name
  330. ; section: Allows | separated values so multiple sections can be checked.
  331. IniReadCheck(file,section,key,defaultvalue="",errorMsg="",logType="") {
  332. Loop, Parse, section, |
  333. { section%A_Index% := A_LoopField ; keep each parsed section in its own var
  334. If iniVar != "" ; if last loop's iniVar has a value, update this loop's default value with it
  335. defaultValue := If A_Index = 1 ? defaultValue : iniVar ; on first loop, default value will be the one sent to the function, on following loops it gets the value from the previous loop
  336. IniRead, iniVar, %file%, % section%A_Index%, %key%, %defaultvalue%
  337. If (IniVar = "ERROR" || iniVar = A_Space) ; if key does not exist or is a space, delete ERROR as the value
  338. iniVar := ""
  339. If (A_Index = 1 && iniVar = "" and !logType) {
  340. If errorMsg
  341. ScriptError(errorMsg)
  342. Else
  343. IniWrite, %defaultValue%, %file%, % section%A_Index%, %key%
  344. Return defaultValue
  345. }
  346. If logType ; only log if logType set
  347. { logAr := ["Module","Bezel"]
  348. Log(logAr[logType] . " Setting - [" . section%A_Index% . "] - " . key . ": " . iniVar)
  349. }
  350. If (iniVar != "") ; if IniVar contains a value, update the lastIniVar
  351. lastIniVar := iniVar
  352. }
  353. If defaultValue = %A_Space% ; this prevents the var from existing when it's actually blank
  354. defaultValue := ""
  355. Return If A_Index = 1 ? iniVar : If lastIniVar != "" ? lastIniVar : defaultValue ; if this is the first loop, always return the iniVar. If any other loop, return the lastinivar if it was filled, otherwise send the last updated defaultvalue
  356. }
  357.  
  358. MaximizeWindow(WinTitle, keepAspectRatio="true", removeTitle="true", removeBorder="true", removeToggleMenu="true") {
  359. If (removeTitle = "true")
  360. WinSet, Style, -0xC00000, %WinTitle% ;Removes the titlebar of the game window
  361. If (removeBorder = "true")
  362. WinSet, Style, -0x40000, %WinTitle% ;Removes the border of the game window
  363. If (removeToggleMenu = "true") {
  364. WinGet, WinID, ID, %WinTitle%
  365. ToggleMenu(WinID)
  366. }
  367.  
  368. If (keepAspectRatio = "true") {
  369. WinGetPos, appX, appY, appWidth, appHeight, %WinTitle%
  370. widthMaxPercenty := ( A_ScreenWidth / appWidth )
  371. heightMaxPercenty := ( A_ScreenHeight / appHeight )
  372.  
  373. If ( widthMaxPercenty < heightMaxPercenty )
  374. percentToEnlarge := widthMaxPercenty
  375. Else
  376. percentToEnlarge := heightMaxPercenty
  377.  
  378. appWidthNew := appWidth * percentToEnlarge
  379. appHeightNew := appHeight * percentToEnlarge
  380.  
  381. Transform, appY, Round, %appY%
  382. Transform, appWidthNew, Round, %appWidthNew%, 2
  383. Transform, appHeightNew, Round, %appHeightNew%, 2
  384. appXPos := ( A_ScreenWidth / 2 ) - ( appWidthNew / 2 )
  385. appYPos := ( A_ScreenHeight / 2 ) - ( appHeightNew / 2 )
  386. }
  387. Else {
  388. appXPos := 0
  389. appYPos := 0
  390. appWidthNew := A_ScreenWidth
  391. appHeightNew := A_ScreenHeight
  392. }
  393. MoveWindow(WinTitle,appXPos,appYPos,appWidthNew,appHeightNew)
  394. }
  395.  
  396. MoveWindow(winTitle,X,Y,W,H,timeLimit=2000,ignoreWin=""){ ; assures that a window is moved to the desired position within a timeout
  397. Log("MoveWindow - Moving window " . winTitle . " to X=" . X . ", Y=" . Y . ", W=" . W . " H=" . H, 4)
  398. WinMove, % winTitle, , %X%, %Y%, %W%, %H%, %ignoreWin%
  399. ;check If window moved
  400. timeout := A_TickCount
  401. Loop
  402. { WinGetPos, Xgot, Ygot, Wgot, Hgot, %winTitle%,, %ignoreWin%
  403. If ((Xgot=X) and (Ygot=Y) and (Wgot=W) and (Hgot=H)){
  404. Log("MoveWindow - Successful: Window " . winTitle . " moved to X=" . X . ", Y=" . Y . ", W=" . W . " H=" . H, 4)
  405. error := 0
  406. Break
  407. }
  408. If (timeout<A_TickCount-timeLimit){
  409. Log("MoveWindow - Failed: Window " . winTitle . " at X=" . Xgot . ", Y=" . Ygot . ", W=" . Wgot . " H=" . Hgot, 4)
  410. error := 1
  411. Break
  412. }
  413. Sleep, 200
  414. WinMove, %winTitle%,, %X%, %Y%, %W%, %H%, %ignoreWin%
  415. }
  416. Return error
  417. }
  418.  
  419. ; Purpose: Handle an emulators Open Rom window when CLI is not an option
  420. ; Returns 1 when successful
  421. OpenROM(windowName,selectedRomName) {
  422. Log("OpenROM - Started")
  423. Global MEmu,moduleName
  424. WinWait(windowName)
  425. WinWaitActive(windowName)
  426. state := 0
  427. Loop, 150 ; 15 seconds
  428. { ControlSetText, Edit1, %selectedRomName%, %windowName%
  429. ControlGetText, edit1Text, Edit1, %windowName%
  430. If (edit1Text = selectedRomName) {
  431. state := 1
  432. Log("OpenROM - Successfully set romName into """ . windowName . """ in " . A_Index . " " . (If A_Index = 1 ? "try." : "tries."),4)
  433. Break
  434. }
  435. Sleep, 100
  436. }
  437. If (state != 1)
  438. ScriptError("Tried for 15 seconds to send the romName to " . MEmu . " but was unsuccessful. Please try again with Fade and Bezel disabled and put the " . moduleName . " in windowed mode to see if the problem persists.", 10)
  439. PostMessage, 0x111, 1,,, %windowName% ; Select Open
  440. Log("OpenROM - Ended")
  441. Return %state%
  442. }
  443.  
  444. GetActiveWindowStatus(){
  445. dWin := A_DetectHiddenWindows ; store current value to return later
  446. DetectHiddenWindows, On
  447. activeWinHWND := WinExist("A")
  448. WinGet, procPath, ProcessPath, ahk_id %activeWinHWND%
  449. WinGet, procID, PID, ahk_id %activeWinHWND%
  450. WinGet, winState, MinMax, ahk_id %activeWinHWND%
  451. WinGetClass, winClass, ahk_id %activeWinHWND%
  452. WinGetTitle, winTitle, ahk_id %activeWinHWND%
  453. WinGetPos, X, Y, W, H, ahk_id %activeWinHWND%
  454. Log("GetActiveWindowStatus - Title: " . winTitle . " | Class: " . winClass . " | State: " . winState . " | X: " . X . " | Y: " . Y . " | Width: " . W . " | Height: " . H . " | Window HWND: " . activeWinHWND . " | Process ID: " . procID . " | Process Path: " . procPath, 4)
  455. DetectHiddenWindows, %dWin% ; restore prior state
  456. }
  457.  
  458. ; CheckFile Usage:
  459. ; file = file to be checked if it exists
  460. ; msg = the error msg you want displayed on screen if you don't want the default "file not found"
  461. ; timeout = gets passed to ScriptError(), the amount of time you want the error to show on screen
  462. ; crc = If this is a an AHK library only, provide a crc so it can be validated
  463. ; crctype = default empty and crc is not checked. Use 0 for AHK libraries and RocketLauncher extension files. Use 1 for module crc checks..
  464. ; logerror = default empty will give a log error instead of stopping with a scripterror
  465. ; allowFolder = allows folders or files w/o an extension to be checked. By default a file must have an extension.
  466. CheckFile(file,msg="",timeout=6,crc="",crctype="",logerror="",allowFolder=0){
  467. Global RLObject,logIncludeFileProperties
  468. exeFileInfo := "
  469. ( LTrim
  470. FileDescription
  471. FileVersion
  472. InternalName
  473. LegalCopyright
  474. OriginalFilename
  475. ProductName
  476. ProductVersion
  477. CompanyName
  478. PrivateBuild
  479. SpecialBuild
  480. LegalTrademarks
  481. )"
  482.  
  483. Log("CheckFile - Checking if " . file . " exists")
  484. SplitPath, file, fileName, filePath, fileExt, fileNameNoExt
  485. If !FileExist(filePath . "\" . fileName)
  486. If FileExist(filePath . "\" . fileNameNoExt . " (Example)." . fileExt) {
  487. FileCopy, %filePath%\%fileNameNoExt% (Example).%fileExt%, %filePath%\%fileName%
  488. If ErrorLevel
  489. Log("CheckFile - Found an example for this file, but did not have permissions to retore it: " . filePath . "\" . fileNameNoExt . " (Example)." . fileExt,3)
  490. Else
  491. Log("CheckFile - Restored this file from its example: " . filePath . "\" . fileNameNoExt . " (Example)." . fileExt,2)
  492. } Else {
  493. If msg
  494. ScriptError(msg, timeout)
  495. Else
  496. ScriptError("Cannot find " . file, timeout)
  497. }
  498. If (!fileExt && !allowFolder)
  499. ScriptError("This is a folder and must point to a file instead: " . file, timeout)
  500.  
  501. If (crctype = 0 Or crctype = 1) {
  502. CRCResult := RL_checkModuleCRC("" . file . "",crc,crctype)
  503. If (CRCResult = -1)
  504. Log("CRC Check - " . (If crctype=1 ? "Module" : If (crctype=0 && crc) ? "Library" : "Extension") . " file not found.",3)
  505. Else If (CRCResult = 0)
  506. If (crctype = 1)
  507. Log("CRC Check - CRC does not match official module and will not be supported. Continue using at your own risk.",2)
  508. Else If logerror
  509. Log("CRC Check - CRC does not match for this " . (If (crctype=0 && crc) ? "Library" : "Extension") . ". Please re-download this file to continue using RocketLauncher: " . file,3)
  510. Else
  511. ScriptError("CRC Check - CRC does not match for this " . (If (crctype=0 && crc) ? "Library" : "Extension") . ". Please re-download this file to continue using RocketLauncher: " . file)
  512. Else If (CRCResult = 1)
  513. Log("CRC Check - CRC matches, this is an official unedited " . (If crctype=1 ? "Module" : If (crctype=0 && crc) ? "Library" : "Extension") . ".",4)
  514. Else If (CRCResult = 2)
  515. Log("CRC Check - No CRC defined on the header for: " . file,3)
  516. }
  517.  
  518. If (logIncludeFileProperties = "true")
  519. { If exeAtrib := FileGetVersionInfo_AW(file, exeFileInfo, "`n")
  520. Loop, Parse, exeAtrib, `n
  521. logTxt .= (If A_Index=1 ? "":"`n") . "`t`t`t`t`t" . A_LoopField
  522. FileGetSize, fileSize, %file%
  523. FileGetTime, fileTimeC, %file%, C
  524. FormatTime, fileTimeC, %fileTimeC%, M/d/yyyy - h:mm:ss tt
  525. FileGetTime, fileTimeM, %file%, M
  526. FormatTime, fileTimeM, %fileTimeM%, M/d/yyyy - h:mm:ss tt
  527. logTxt .= (If logTxt ? "`r`n":"") . "`t`t`t`t`tFile Size:`t`t`t" . fileSize . " bytes"
  528. logTxt .= "`r`n`t`t`t`t`tCreated:`t`t`t" . fileTimeC
  529. logTxt .= "`r`n`t`t`t`t`tModified:`t`t`t" . fileTimeM
  530. Log("CheckFile - Attributes:`r`n" . logTxt,4)
  531. }
  532. Return %file%
  533. }
  534.  
  535. CheckFolder(folder,msg="",timeout=6,crc="",crctype="",logerror="") {
  536. Return CheckFile(folder,msg,timeout,crc,crctype,logerror,1)
  537. }
  538.  
  539. ; ScriptError usage:
  540. ; error = error text
  541. ; timeout = duration in seconds error will show
  542. ; w = width of error box
  543. ; h = height of error box
  544. ; txt = font size
  545. ScriptError(error,timeout=6,w=800,h=225,txt=20,noexit=""){
  546. Global RLMediaPath,exitEmulatorKey,RLFile,RLErrSoundPath,logShowCommandWindow,cmdWindowObj,scriptErrorTriggered
  547. Global screenRotationAngle,baseScreenWidth,baseScreenHeight,xTranslation,yTranslation,XBaseRes,YBaseRes
  548.  
  549. XHotKeywrapper(exitEmulatorKey,"CloseProcess","OFF")
  550. XHotKeywrapper(exitEmulatorKey,"CloseError","ON")
  551. Hotkey, Esc, CloseError
  552. Hotkey, Enter, CloseError
  553.  
  554. If !pToken := Gdip_Startup(){ ; Start gdi+
  555. MsgBox % "Gdiplus failed to start. Please ensure you have gdiplus on your system"
  556. ExitApp
  557. }
  558.  
  559. timeout *= 1000 ; converting to seconds
  560. ;Acquiring screen info for dealing with rotated menu drawings
  561. Gdip_Alt_GetRotatedDimensions(A_ScreenWidth, A_ScreenHeight, screenRotationAngle, baseScreenWidth, baseScreenHeight)
  562. Gdip_GetRotatedTranslation(baseScreenWidth, baseScreenHeight, screenRotationAngle, xTranslation, yTranslation)
  563. xTranslation:=round(xTranslation), yTranslation:=round(yTranslation)
  564. XBaseRes := 1920, YBaseRes := 1080
  565. If (((A_screenWidth < A_screenHeight) and ((screenRotationAngle=0) or (screenRotationAngle=180))) or ((A_screenWidth > A_screenHeight) and ((screenRotationAngle=90) or (screenRotationAngle=270))))
  566. XBaseRes := 1080, YBaseRes := 1920
  567. If !errorXScale
  568. errorXScale := baseScreenWidth/XBaseRes
  569. If !errorYScale
  570. errorYScale := baseScreenHeight/YBaseRes
  571. Error_Warning_Width := w
  572. Error_Warning_Height := h
  573. Error_Warning_Pen_Width := 7
  574. Error_Warning_Rounded_Corner := 30
  575. Error_Warning_Margin := 30
  576. Error_Warning_Bitmap_Size := 125
  577. Error_Warning_Text_Size := txt
  578. OptionScale(Error_Warning_Width, errorXScale)
  579. OptionScale(Error_Warning_Height, errorYScale)
  580. OptionScale(Error_Warning_Pen_Width, errorXScale)
  581. OptionScale(Error_Warning_Rounded_Corner, errorXScale)
  582. OptionScale(Error_Warning_Margin, errorXScale)
  583. OptionScale(Error_Warning_Bitmap_Size, errorXScale)
  584. OptionScale(Error_Warning_Text_Size, errorYScale)
  585.  
  586. ;Create error GUI
  587. Gui, Error_GUI: +Disabled -Caption +E0x80000 +OwnDialogs +LastFound +ToolWindow +AlwaysOnTop
  588. Gui, Error_GUI: Margin,0,0
  589. Gui, Error_GUI: Show,, ErrorLayer
  590. Error_hwnd := WinExist()
  591. Error_hbm := CreateDIBSection(A_ScreenWidth, A_ScreenHeight)
  592. Error_hdc := CreateCompatibleDC()
  593. Error_obm := SelectObject(Error_hdc, Error_hbm)
  594. Error_G := Gdip_GraphicsFromhdc(Error_hdc)
  595. Gdip_SetSmoothingMode(Error_G, 4)
  596. Gdip_TranslateWorldTransform(Error_G, xTranslation, yTranslation)
  597. Gdip_RotateWorldTransform(Error_G, screenRotationAngle)
  598. pGraphUpd(Error_G,baseScreenWidth, baseScreenHeight)
  599.  
  600. ;Create GUI elements
  601. pBrush := Gdip_BrushCreateSolid("0xFF000000") ; Painting the background color
  602. Gdip_Alt_FillRectangle(Error_G, pBrush, -1, -1, baseScreenWidth+1, baseScreenHeight+1) ; draw the background first on layer 1 first, layer order matters!!
  603. brushWarningBackground := Gdip_CreateLineBrushFromRect(0, 0, Error_Warning_Width, Error_Warning_Height, 0xff555555, 0xff050505)
  604. penWarningBackground := Gdip_CreatePen(0xffffffff, Error_Warning_Pen_Width)
  605. Gdip_Alt_FillRoundedRectangle(Error_G, brushWarningBackground, (baseScreenWidth - Error_Warning_Width)//2, (baseScreenHeight - Error_Warning_Height)//2, Error_Warning_Width, Error_Warning_Height, Error_Warning_Rounded_Corner)
  606. Gdip_Alt_DrawRoundedRectangle(Error_G, penWarningBackground, (baseScreenWidth - Error_Warning_Width)//2, (baseScreenHeight - Error_Warning_Height)//2, Error_Warning_Width, Error_Warning_Height, Error_Warning_Rounded_Corner)
  607. WarningBitmap := Gdip_CreateBitmapFromFile(RLMediaPath . "\Menu Images\RocketLauncher\Warning.png")
  608. Gdip_Alt_DrawImage(Error_G,WarningBitmap, round((baseScreenWidth - Error_Warning_Width)//2 + Error_Warning_Margin),round(baseScreenHeight/2 - Error_Warning_Bitmap_Size/2),Error_Warning_Bitmap_Size,Error_Warning_Bitmap_Size)
  609. Gdip_Alt_TextToGraphics(Error_G, error, "x" round((baseScreenWidth-Error_Warning_Width)//2+Error_Warning_Bitmap_Size+Error_Warning_Margin) " y" round((baseScreenHeight-Error_Warning_Height)//2+Error_Warning_Margin) " Left vCenter cffffffff r4 s" Error_Warning_Text_Size " Bold",, round((Error_Warning_Width - 2*Error_Warning_Margin - Error_Warning_Bitmap_Size)) , round((Error_Warning_Height - 2*Error_Warning_Margin)))
  610.  
  611. startTime := A_TickCount
  612. Loop{ ; fade in
  613. t := ((TimeElapsed := A_TickCount-startTime) < 300) ? (255*(timeElapsed/300)) : 255
  614. Alt_UpdateLayeredWindow(Error_hwnd,Error_hdc, 0, 0, baseScreenWidth, baseScreenHeight,t)
  615. If (t >= 255)
  616. Break
  617. }
  618.  
  619. ; Generate a random sound to play on a script error
  620. erSoundsAr:=[] ; initialize the array to store error sounds
  621. Loop, %RLErrSoundPath%\error*.mp3
  622. erSoundsAr.Insert(A_LoopFileName) ; insert each found error sound into an array
  623. Random, erRndmSound, 1, % erSoundsAr.MaxIndex() ; randomize what sound to play
  624. Log("ScriptError - Playing error sound: " . erSoundsAr[erRndmSound],4)
  625. setMute(0,emulatorVolumeObject)
  626. SoundPlay % If erSoundsAr.MaxIndex() ? (RLErrSoundPath . "\" . erSoundsAr[erRndmSound]):("*-64"), wait ; play the random sound if any exist, or default to the Asterisk windows sound
  627. If noexit { ; do not close thread, continue with script and let it handle the exiting
  628. scriptErrorTriggered := 1
  629. Return
  630. }
  631. 7zCleanUp() ; clean up 7z if necessary
  632. Sleep, %timeout%
  633.  
  634. CloseError:
  635. endTime := A_TickCount
  636. Loop { ; fade out
  637. t := ((TimeElapsed := A_TickCount-endTime) < 300) ? (255*(1-timeElapsed/300)) : 0
  638. Alt_UpdateLayeredWindow(Error_hwnd,Error_hdc, 0, 0, baseScreenWidth, baseScreenHeight,t)
  639. If (t <= 0)
  640. Break
  641. }
  642.  
  643. XHotKeywrapper(exitEmulatorKey,"CloseError","OFF")
  644. XHotKeywrapper(exitEmulatorKey,"CloseProcess","ON")
  645. Gdip_DeleteBrush(pBrush)
  646. Gdip_DisposeImage(WarningBitmap), SelectObject(Error_hdc, Error_obm), DeleteObject(Error_hbm), DeleteDC(Error_hdc), Gdip_DeleteGraphics(Error_G)
  647. Gui, ErrorGUI_10: Destroy
  648. Log("ScriptError - " . error,3)
  649.  
  650. ExitModule() ; attempting to use this method which has the small chance to cause an infinite ScriptError loop, but no need to duplicate code to clean up on errors
  651. ; Below cleanup exists because we can't call other functions that may cause additional scripterrors and put the thread in an infinite loop
  652. ; If logShowCommandWindow = true
  653. ; { for index, element in cmdWindowObj
  654. ; Process, Close, % cmdWindowObj[A_Index,1] ; close each opened cmd.exe
  655. ; }
  656. ; ExitApp
  657. }
  658.  
  659. ; Log usage:
  660. ; text = text I want to log
  661. ; lvl = the lvl to log the text at
  662. ; notime = only used for 1st and last lines of the log so a time is not inserted when I inset the BBCode [code] tags. Do not use this param
  663. ; dump = tells the function to write the log file at the end. Do not use this param
  664. ; firstLog = tells the function to not insert a time when the first log is made, instead puts an N/A. Do not use this param
  665. ; Log() in the module thread requires `r`n at the end of each line, where it's not needed in the RocketLauncher thread
  666. Log(text,lvl=1,notime="",dump="",firstLog=""){
  667. Static log
  668. Static lastLog
  669. Global logFile,logLevel,logLabel,logShowDebugConsole
  670. ; Global executable
  671. If (logLevel > 0)
  672. {
  673. If (lvl<=logLevel || lvl=3){ ; ensures errors are always logged
  674. logDiff := A_TickCount - lastLog
  675. lastLog := A_TickCount
  676. log := log . (If notime?"" : A_Hour . ":" . A_Min ":" . A_Sec ":" . A_MSec . " | MD | " . logLabel[lvl] . A_Space . " | +" . AlignColumn(If firstLog ? "N/A" : logDiff) . "" . " | ") . text . "`r`n"
  677. }
  678. If (logShowDebugConsole = "true")
  679. DebugMessage(log)
  680. If (logLevel>=10 || dump){
  681. FileAppend,%log%,%logFile%
  682. log := ""
  683. }
  684. ; Process, Exist, %executable%
  685. ; If ErrorLevel
  686. ; Log .= "mame exists`r`n"
  687. Return log
  688. }
  689. }
  690.  
  691. ; Inserts extra characters/spaces into sections of the Log file to keep it aligned.
  692. ; Usage: inserts char x number of times on the end of txt until pad is reached.
  693. AlignColumn(txt,pad=9,char=" "){
  694. x := If char=" "?2:1 ; if char is a space, let's only insert half as many so it looks slightly more even in notepad++
  695. Loop {
  696. n := StrLen(txt)
  697. If (n*x >= pad)
  698. Break
  699. txt := txt . char
  700. }
  701. Return txt
  702. }
  703.  
  704. ; Rini returns -2 if section does not exist
  705. ; Rini returns -3 if key does not exist
  706. ; Rini returns -10 if an invalid reference var for the ini file was used
  707. ; Rini returns empty value if key exists with no value
  708. ; rIniIndex := Object(1,globalRLFile,2,sysRLFile,3,globalEmuFile,4,sysEmuFile,5,RLFile,6,gamesFile)
  709. ; preferDefault - On rare occasions we may want to set a default value w/o wanting rini to return an error value of -2 or -3. Used for JoyIDs_Preferred_Controllers
  710. RIniLoadVar(gRIniVar,sRIniVar,section,key,gdefaultvalue="",sdefaultvalue="use_global",preferDefault="") {
  711. Global rIniIndex
  712. If (gRIniVar != 6) ; do not create missing sections or keys for games.ini
  713. { gValue := RIni_GetKeyValue(gRIniVar,section,key,If preferDefault ? gdefaultvalue : "")
  714. gValue := gValue ; trims whitespace
  715. If RegExMatch(gValue,"-2|-3") ; if global ini key does not exist, create the key
  716. { RIni_SetKeyValue(gRIniVar,section,key,gdefaultvalue)
  717. RIni_Write(gRIniVar,rIniIndex[gRIniVar],"`r`n",1,1,1)
  718. gValue := gdefaultvalue ; set to default value because it did not exist
  719. Log("RIniLoadVar - Created missing Global ini key: """ . key . """ in section: """ . section . """ in """ . rIniIndex[gRIniVar] . """",2)
  720. }
  721. If sRIniVar ; != "" ; only create system sections or keys for inis that use them
  722. { sValue := RIni_GetKeyValue(sRIniVar,section,key,If preferDefault ? sdefaultvalue : "")
  723. sValue := sValue ; trims whitespace
  724. If RegExMatch(sValue,"-2|-3") ; if system ini key does not exist, create the key
  725. { RIni_SetKeyValue(sRIniVar,section,key,sdefaultvalue)
  726. RIni_Write(sRIniVar,rIniIndex[sRIniVar],"`r`n",1,1,1)
  727. sValue := sdefaultvalue ; set to default value because it did not exist
  728. Log("RIniLoadVar - Created missing System ini key: """ . key . """ in section: """ . section . """ in """ . rIniIndex[sRIniVar] . """",2)
  729. }
  730. Return If sValue = "use_global" ? gValue : sValue ; now compare global & system keys to get final value
  731. }
  732. Return gValue ; return gValue when not using globa/system inis, like RLFile (rIniIndex 5)
  733. }
  734. iniVar := RIni_GetKeyValue(gRIniVar,section,key,gdefaultvalue) ; lookup key from ini and return it
  735. iniVar := iniVar ; trims whitespace
  736. Return iniVar
  737. }
  738.  
  739. RIniReadCheck(rIniVar,section,key,defaultvalue="",errorMsg="") {
  740. Global rIniIndex
  741. iniVar := RIni_GetKeyValue(rIniVar,section,key) ; lookup key from ini and return it
  742. iniVar := iniVar ; trims whitespace
  743. If (iniVar = -2 or iniVar = -3 or iniVar = "") {
  744. If (iniVar != "") { ; with rini, no need write to ini file if value is returned empty, we already know the section\key exists with no value
  745. Log("RIniReadCheck - Created missing RocketLauncher ini key: """ . key . """ in section: """ . section . """ in """ . rIniIndex[rIniVar] . """",2)
  746. RIni_SetKeyValue(rIniVar,section,key,defaultvalue)
  747. RIni_Write(rIniVar,rIniIndex[rIniVar],"`r`n",1,1,1) ; write blank section, blank key, and space between sections
  748. }
  749. If errorMsg
  750. ScriptError(errorMsg)
  751. Return defaultValue
  752. }
  753. Return iniVar
  754. }
  755.  
  756. CheckFont(font) {
  757. If !(Gdip_FontFamilyCreate(font))
  758. ScriptError("The Font """ . font . """ is not installed on your system. Please install the font or change it in RocketLauncherUI.")
  759. }
  760.  
  761. ; Toggles hiding/showing a MenuBar
  762. ; Usage: Provide the window's PID of the window you want to toggle the MenuBar
  763. ; used in nulldc module and bezel
  764. ToggleMenu(hWin){
  765. Static hMenu, visible
  766. If (hMenu = "")
  767. hMenu := DllCall("GetMenu", "uint", hWin) ; store the menubar ID so it can be restored later
  768. hMenuCur := DllCall("GetMenu", "uint", hWin)
  769. timeout := A_TickCount
  770. If !hMenuCur
  771. Loop {
  772. ;ToolTip, menubar is hidden`, bringing it back`nhMenuCur: %hMenuCur%`n%A_Index%
  773. hMenuCur := DllCall("GetMenu", "uint", hWin)
  774. If hMenuCur {
  775. Log("ToggleMenu - MenuBar is now visible for " . hWin,4)
  776. Break ; menubar is now visible, break out
  777. }
  778. DllCall("SetMenu", "uint", hWin, "uint", hMenu)
  779. If (timeout < A_TickCount - 500) ; prevents an infinite loop and breaks after 2 seconds
  780. Break
  781. }
  782. Else Loop { ; menubar is visible
  783. ;ToolTip, menubar is visible`, hiding it`nhMenuCur: %hMenuCur%`n%A_Index%
  784. hMenuCur := DllCall("GetMenu", "uint", hWin)
  785. If !hMenuCur {
  786. Log("ToggleMenu - MenuBar is now hidden for " . hWin,4)
  787. Break ; menubar is now hidden, break out
  788. }
  789. DllCall("SetMenu", "uint", hWin, "uint", 0)
  790. If (timeout < A_TickCount - 500) ; prevents an infinite loop and breaks after 2 seconds
  791. Break
  792. }
  793. }
  794. ; Original function but somestimes does not work, which is why the new function loops above
  795. ToggleMenuOld(hWin){
  796. Static hMenu, visible
  797. If (hMenu = "")
  798. hMenu := DllCall("GetMenu", "uint", hWin)
  799. If !visible
  800. DllCall("SetMenu", "uint", hWin, "uint", hMenu)
  801. Else
  802. DllCall("SetMenu", "uint", hWin, "uint", 0)
  803. visible := !visible
  804. }
  805.  
  806. ; Function to pause and wait for a user to press any key to continue.
  807. ; IdleCheck usage:
  808. ; t = timeout in ms to break out of function
  809. ; m = the method - can be "P" (physical) or "L" (logical)
  810. ; s = sleep or how fast the function checks for idle state
  811. ; Exits when state is no longer idle or times out
  812. IdleCheck(t="",m="L",s=200){
  813. timeIdlePrev := 0
  814. startTime := A_TickCount
  815. While timeIdlePrev < (If m = "L" ? A_TimeIdle : A_TimeIdlePhysical){
  816. timeIdlePrev := If m = "L" ? A_TimeIdle : A_TimeIdlePhysical
  817. If (t && A_TickCount-startTime >= t)
  818. Return "Timed Out"
  819. Sleep s
  820. }
  821. Return A_PriorKey
  822. }
  823.  
  824. ; This function looks through all defined romPaths and romExtensions for the provided rom file
  825. ; Returns a path to the rom where it was found
  826. ; Returns nothing if not found
  827. RomNameExistCheck(file,archivesOnly="") {
  828. Global romPathFromIni,romExtensions,sevenZFormats
  829. Loop, Parse, romPathFromIni, | ; for each rom path defined
  830. { tempRomPath := A_LoopField ; assigning this to a var so it can be accessed in the next loop
  831. Loop, Parse, romExtensions, | ; for each extension defined
  832. { If (archivesOnly != "")
  833. If !InStr(sevenZFormats,A_LoopField) ; if rom extension is not an archive type, skip this rom
  834. Continue
  835. ; msgbox % tempRomPath . "\" . file . "." . tempRomExtension
  836. Log("RomNameExistCheck - Looking for rom: " . tempRomPath . "\" . file . "." . A_LoopField,4)
  837. If FileExist( tempRomPath . "\" . file . "." . A_LoopField ) {
  838. Log("RomNameExistCheck - Found rom: " . tempRomPath . "\" . file . "." . A_LoopField)
  839. Return tempRomPath . "\" . file . "." . A_LoopField ; return path if file exists
  840. }
  841. Log("RomNameExistCheck - Looking for rom: " . tempRomPath . "\" . file . "\" . file . "." . A_LoopField,4)
  842. If FileExist( tempRomPath . "\" . file . "\" . file . "." . A_LoopField ) { ; check one folder deep of the rom's name in case user keeps each rom in a folder
  843. Log("RomNameExistCheck - Found rom: " . tempRomPath . "\" . file . "\" . file . "." . A_LoopField)
  844. Return tempRomPath . "\" . file . "\" . file . "." . A_LoopField ; return path if file exists
  845. }
  846. }
  847. }
  848. Log("RomNameExistCheck - Could not find """ . file . """ in any of your Rom Paths with any defined Rom Extensions",2)
  849. Return
  850. }
  851.  
  852. ; Shared romTable function and label for Pause and MG which calculates what roms have multiple discs. Now available on every launch to support some custom uses for loading multiple disks on some older computer systems
  853. CreateMGRomTable:
  854. Log("CreateMGRomTable - Started")
  855. If !mgCandidate {
  856. Log("CreateMGRomTable - Ended - This rom does not qualify for MultiGame")
  857. Return
  858. }
  859. If !IsObject(romTable)
  860. { Log("CreateMGRomTable - romTable does not exist, creating one for """ . dbName . """",4)
  861. romTable := CreateRomTable(dbName)
  862. } Else
  863. Log("CreateMGRomTable - romTable already exists, skipping table creation.",4)
  864. Log("CreateMGRomTable - Ended")
  865. Return
  866.  
  867. CreateRomTable(table) {
  868. Global romPathFromIni,dbName,romExtensionOrig,sevenZEnabled,romTableStarted,romTableComplete,romTableCanceled,rocketLauncherIsExiting,mgCandidate
  869. romTableStarted := 1
  870. romTableCanceled := ""
  871. romTableComplete := ""
  872. If rocketLauncherIsExiting {
  873. romTableCanceled := 1 ; set this so the RomTableCheck is canceled and doesn't get stuck in an infinite loop
  874. Log("CreateRomTable - RocketLauncher is currently exiting, skipping romTable creation")
  875. Return
  876. }
  877. If !mgCandidate {
  878. romTableCanceled := 1 ; set this so the RomTableCheck is canceled and doesn't get stuck in an infinite loop
  879. Log("CreateRomTable - This rom does not qualify for MultiGame")
  880. Return
  881. }
  882. Log("CreateRomTable - Started")
  883.  
  884. romCount := 0 ; initialize the var and reset it, needed in case GUI is used more then once in a session
  885. table := [] ; initialize and empty the table
  886. typeArray := ["(Disc","(Disk","(Cart","(Tape","(Cassette","(Part","(Side"]
  887. regExCheck = i)\s\(Disc\s[^/]*|\s\(Disk\s[^/]*|\s\(Cart\s[^/]*|\s\(Tape\s[^/]*|\s\(Cassette\s[^/]*|\s\(Part\s[^/]*|\s\(Side\s[^/]*
  888. dbNamePre := RegExReplace(dbName, regExCheck) ; removes the last set of parentheses if Disc,Tape, etc is in them. A Space must exist before the "(" and after the word Disc or Tape, followed by the number. This is the HS2 standard
  889. Loop % typeArray.MaxIndex() ; loop each item in our array
  890. { If matchedRom ; Once we matched our game to the typeArray, no need to search for another. This allows the loop to break out.
  891. Break
  892. indexTotal ++
  893. Log("CreateRomTable - Checking for match: """ . dbName . """ and """ . typeArray[A_Index] . """",4)
  894. If dbName contains % typeArray[A_Index] ; find the item in our array that matches our rom
  895. { Log("CreateRomTable - """ . dbName . """ contains """ . typeArray[A_Index] . """",4)
  896. typeArrayIndex := A_Index
  897. Loop, Parse, romPathFromIni, |
  898. { indexTotal ++
  899. currentPath := A_LoopField
  900. Log("CreateRomTable - Checking New Rom path: " . currentPath,4)
  901. Log("CreateRomTable - Now looping in: " . currentPath . "\" . dbNamePre . A_Space . typeArray[typeArrayIndex] . "*",4)
  902. Loop, % currentPath . "\" . dbNamePre . A_Space . typeArray[typeArrayIndex] . "*", 1,1 ; we now know to only look for files & folders that have our rom & media type in them.
  903. { indexTotal ++
  904. Log(A_LoopFileFullPath,4)
  905. Log("CreateRomTable - Looking for: " . currentPath . "\" . dbNamePre . A_Space . typeArray[typeArrayIndex] . "*." . A_LoopFileExt,4)
  906. If romExtensionOrig contains % A_LoopFileExt ; Now we narrow down to all matching files using our original extension. Next we use this data to build an array of our files to populate the GUI.
  907. { romCount += 1
  908. matchedRom := 1 ; Allows to break out of the loops once we matched our rom
  909. table[romCount,1] := A_LoopFileFullPath ; Store A_LoopFileFullPath (full file path and file) in column 1
  910. table[romCount,2] := A_LoopFileName ; Store A_LoopFileName (the full filename and extension) in column 2
  911. table[romCount,3] := RegExReplace(table[romCount, 2], "\..*") ; Store the filename with media type # but w/o an extension in column 3
  912. pos := RegExMatch(table[romCount,2], regExCheck) ; finds position of our multi media type so we can trim away and generate the imageText and check if rom is part of a set. This pulls only the filenames out of the table in column 2.
  913. uncleanTxt:= SubStr(table[romCount,2], pos + 1) ; remove everything but the media type and # and ext from our file name
  914. table[romCount,4] := dbNamePre ; store dbName w/o the media type and #, used for Pause and updating statistics in column 4
  915. table[romCount,5] := RegExReplace(uncleanTxt, "\(|\)|\..*") ; clean the remainder, removing () and ext, then store it as column 5 in our table to be used for our imageText, this is the media type and #
  916. table[romCount,6] := SubStr(table[romCount,5],1,4) ; copies just the media type to column 6
  917. Log("CreateRomTable - Adding found game to Rom Table: " . A_LoopFileFullPath,4)
  918. }
  919. }
  920. }
  921. }
  922. }
  923. romTableComplete := 1 ; flag to tell the RomTableCheck the function is complete in case no romTable was created for non-MG games
  924. romTableStarted := ""
  925. Log("CreateRomTable - Ended`, " . IndexTotal . " Loops to create table.")
  926. Return table
  927. }
  928.  
  929. ; Function that gets called in some modules to wait for romTable creation if the module bases some conditionals off whether this table exists or not
  930. RomTableCheck() {
  931. Global systemName,mgEnabled,pauseEnabled,romTable,romTableStarted,romTableComplete,romTableCanceled,mgCandidate,dbName
  932. If mgCandidate { ; && (pauseEnabled = "true" || mgEnabled = "true")) {
  933. ; If (!romTableStarted && !IsObject(romTable))
  934. ; romTable := CreateRomTable(dbName)
  935.  
  936. Log("RomTableCheck - Started")
  937. ; PauseGlobalIni := A_ScriptDir . "\Settings\Global Pause.ini" ; Pause keys have not been read into memory yet, so they must be read here so RocketLauncher knows whether to run the below loop or not
  938. ; PauseSystemIni := A_ScriptDir . "\Settings\" . systemName . "\Pause.ini"
  939. ; IniRead, changeDiscMenuG, %PauseGlobalIni%, General Options, ChangeDisc_Menu_Enabled
  940. ; IniRead, changeDiscMenuS, %PauseSystemIni%, General Options, ChangeDisc_Menu_Enabled
  941. ; changeDiscMenu := If changeDiscMenuS = "use_global" ? changeDiscMenuG : changeDiscMenuS ; calculate to use system or global setting
  942.  
  943. ; If (mgEnabled = "true" || changeDiscMenu = "true") {
  944. ; Log("RomTableCheck - MultiGame and/or Pause's Change Disc Menu is enabled so checking if romTable exists yet.",4)
  945. If !romTable.MaxIndex()
  946. Log("RomTableCheck - romTable does not exist yet, waiting until it does to continue loading the module.",4)
  947. Loop {
  948. If romTableComplete { ; this var gets created when CreateRomTable is complete in case this is not an MG game
  949. Log("RomTableCheck - Detected CreateRomTable is finished processing. Continuing with module thread.",4)
  950. Break
  951. } Else If romTableCanceled { ; this var gets created when CreateRomTable is cancelled in cases it is no longer needed
  952. Log("RomTableCheck - Detected CreateRomTable is no longer needed. Continuing with module thread.",4)
  953. Break
  954. } Else If (A_Index > 200) { ; if 20 seconds pass by, log there was an issue and continue w/o romTable
  955. Log("RomTableCheck - Creating the romTable took longer than 20 seconds. Continuing with module thread without waiting for the table's creation.",3)
  956. Break
  957. } Else
  958. Sleep, 100
  959. }
  960. ; }
  961. Log("RomTableCheck - Ended")
  962. } Else
  963. Log("RomTableCheck - This game is not a candidate for MG or Change DIsc menu.")
  964. }
  965.  
  966. ; Allows changing LEDBlinky's active profile
  967. ; mode can be RL or Rom which tells LEDBlinky what profile to load
  968. ; Ledblinky's ini gets loaded on start, so this function will never touch it
  969. LEDBlinky(mode) {
  970. Global ledblinkyEnabled,ledblinkySystemName,ledblinkyFullPath,ledblinkyProfilePath,ledblinkyRLProfile,dbName,systemName,romName
  971. Static ledblinkyExists,ledblinkyExe,ledblinkyPath
  972. If (ledblinkyEnabled != "false")
  973. {
  974. If !ledblinkyExists { ; Make sure LEDBlinky exists first before trying to use it
  975. If FileExist(ledblinkyFullPath) {
  976. ledblinkyExists := 1
  977. SplitPath,ledblinkyFullPath,ledblinkyExe,ledblinkyPath
  978.  
  979. } Else
  980. ScriptError("You are trying to use LEDBlinky support but could not locate it here: " . ledblinkyFullPath)
  981. }
  982. Log("LEDBlinky - Started, sending mode " . mode)
  983.  
  984. If (mode = "START")
  985. Run(ledblinkyExe . " """ . (If romName ? romName : dbName) . """ """ . (If ledblinkySystemName ? ledblinkySystemName : systemName) . """", ledblinkyPath) ; Game Start Event
  986. Else If (mode = "END")
  987. Run(ledblinkyExe . " 4" , ledblinkyPath) ; Game Stop Event
  988. Else If (mode = "RL")
  989. Run(ledblinkyExe . " 15 RocketLauncher RocketLauncher", ledblinkyPath) ; Load RocketLauncher profile. "15" Tells ledblinky to skip all game start options and only light the controls.
  990. Else If (mode = "ROM")
  991. Run(ledblinkyExe . " 15 """ . (If romName ? romName : dbName) . """ """ . (If ledblinkySystemName ? ledblinkySystemName : systemName) . """", ledblinkyPath) ; return to rom profile. If within the module, romName can be used, otherwise default to dbName.
  992. Else
  993. Log("LEDBlinky - Unsupported use of LEDBlinky - UNKNOWN MODE SUPPLIED: """ . mode . """",3)
  994. Log("LEDBlinky - Ended")
  995. }
  996. }
  997.  
  998. ; Allows changing WinIPAC's and UltraMap's active profile, among any other tools thrown at it that would utilize similar profile structure
  999. ; mode = can be START, END, RL or RESUME which represents what part of RL is called the function and what profiles will be loaded
  1000. ; tool = the name of the tool or folder that will be searched in and checked if that setting is enabled. Ex: WinIPAC or UltraMap
  1001. ; path = because of how the function supports multiple scenarios, the fullpath to the exe must be provided. Not through making it Global as variables like %prefix%FullPath cannot be made global
  1002. ; ext = extension of the profiles to look for
  1003. ; type = used to basically force special modes (only keyboard for now) so the function can support multiple scenarios that all use the same folder structures for profiles
  1004. KeymapperProfileSelect(mode,tool,path,ext,type="") {
  1005. Global keyboardEncoderEnabled,ultraMapEnabled,profilePath,keymapperFrontEndProfileName,systemName,emuName,dbName
  1006. Global keymapperProfiles
  1007.  
  1008. If !keymapperProfiles
  1009. keymapperProfiles := {} ; create initial object
  1010.  
  1011. If (type = "keyboard")
  1012. prefix := "keyboardEncoder"
  1013. Else
  1014. prefix := tool
  1015.  
  1016. If (%prefix%Enabled = "true") {
  1017. keymapperProfiles[tool,"Enabled"] := "true"
  1018. Log(tool . " - Started with mode: " . mode)
  1019. If !keymapperProfiles[tool,"Exist"] { ; Make sure the tool exists first before trying to use it
  1020. If FileExist(path) {
  1021. keymapperProfiles[tool,"Exist"] := 1
  1022. keymapperProfiles[tool,"FullPath"] := path
  1023. SplitPath,path,exe,path
  1024. keymapperProfiles[tool,"Exe"] := exe
  1025. keymapperProfiles[tool,"Path"] := path
  1026. keymapperProfiles[tool,"Ext"] := "." . ext
  1027. keymapperProfiles[tool,"ProfilePath"] := profilePath . "\" . tool
  1028. keymapperProfiles[tool,"RLProfile"] := keymapperProfiles[tool,"ProfilePath"] . "\RocketLauncher"
  1029. keymapperProfiles[tool,"FEProfile"] := keymapperProfiles[tool,"ProfilePath"] . "\" . keymapperFrontEndProfileName
  1030. keymapperProfiles[tool,"DefaultProfile"] := keymapperProfiles[tool,"ProfilePath"] . "\_Default"
  1031. keymapperProfiles[tool,"SystemProfile"] := keymapperProfiles[tool,"ProfilePath"] . "\" . systemName
  1032. keymapperProfiles[tool,"EmuProfile"] := keymapperProfiles[tool,"ProfilePath"] . "\" . emuName
  1033. keymapperProfiles[tool,"RomProfile"] := keymapperProfiles[tool,"ProfilePath"] . "\" . systemName . "\" . dbName
  1034. ; msgbox % "fullPath: " . keymapperProfiles[tool,"FullPath"] . "`nexe: " . keymapperProfiles[tool,"Exe"] . "`npath: " . keymapperProfiles[tool,"Path"] . "`nExt: " . keymapperProfiles[tool,"Ext"] . "`nProfilePath: " . keymapperProfiles[tool,"ProfilePath"] . "`nRLProfile: " . keymapperProfiles[tool,"RLProfile"] . "`nFEProfile: " . keymapperProfiles[tool,"FEProfile"] . "`nDefaultProfile: " . keymapperProfiles[tool,"DefaultProfile"] . "`nSystemProfile: " . keymapperProfiles[tool,"SystemProfile"] . "`nEmuProfile: " . keymapperProfiles[tool,"EmuProfile"] . "`nRomProfile: " . keymapperProfiles[tool,"RomProfile"]
  1035. } Else {
  1036. Log(tool . " - You have your path set to " . %prefix% . " defined, but it could not be found here: " . path,2)
  1037. keymapperProfiles[tool,"Enabled"] := "false"
  1038. }
  1039. }
  1040.  
  1041. If (mode = "START")
  1042. { Log(tool . " - Searching for profiles",4)
  1043. If FileExist(keymapperProfiles[tool,"RomProfile"] . keymapperProfiles[tool,"Ext"]) {
  1044. profile := keymapperProfiles[tool,"RomProfile"] . keymapperProfiles[tool,"Ext"]
  1045. } Else If FileExist(keymapperProfiles[tool,"EmuProfile"] . keymapperProfiles[tool,"Ext"]) {
  1046. profile := keymapperProfiles[tool,"EmuProfile"] . keymapperProfiles[tool,"Ext"]
  1047. } Else If FileExist(keymapperProfiles[tool,"SystemProfile"] . keymapperProfiles[tool,"Ext"]) {
  1048. profile := keymapperProfiles[tool,"SystemProfile"] . keymapperProfiles[tool,"Ext"]
  1049. } Else If FileExist(keymapperProfiles[tool,"DefaultProfile"] . keymapperProfiles[tool,"Ext"]) {
  1050. profile := keymapperProfiles[tool,"DefaultProfile"] . keymapperProfiles[tool,"Ext"]
  1051. } Else {
  1052. Log(tool . " - No profiles found",4)
  1053. Return
  1054. }
  1055. keymapperProfiles[tool,"LastProfile"] := profile
  1056. } Else If (mode = "END")
  1057. { Log(tool . " - Searching for your Front End profile",4)
  1058. If FileExist(keymapperProfiles[tool,"FEProfile"] . keymapperProfiles[tool,"Ext"]) {
  1059. profile := keymapperProfiles[tool,"FEProfile"] . keymapperProfiles[tool,"Ext"]
  1060. } Else {
  1061. Log(tool . " - Profile not found",4)
  1062. Return
  1063. }
  1064. } Else If (mode = "RL")
  1065. { Log(tool . " - Searching for your RocketLauncher profile",4)
  1066. If FileExist(keymapperProfiles[tool,"RLProfile"] . keymapperProfiles[tool,"Ext"]) {
  1067. profile := keymapperProfiles[tool,"RLProfile"] . keymapperProfiles[tool,"Ext"]
  1068. } Else {
  1069. Log(tool . " - Profile not found",4)
  1070. Return
  1071. }
  1072. } Else If (mode = "RESUME")
  1073. { Log(tool . " - Restoring to your last profile",4)
  1074. If keymapperProfiles[tool,"LastProfile"] ; only restore to a previous profile if one was found on start
  1075. profile := keymapperProfiles[tool,"LastProfile"]
  1076. Else {
  1077. Log(tool . " - A profile was not loaded on start, skipping any profile loading",4)
  1078. Return
  1079. }
  1080. } Else
  1081. Log(tool . " - Unsupported mode: " . mode,2)
  1082.  
  1083. Log(tool . " - Loading found profile: " . profile,4)
  1084. Run, % keymapperProfiles[tool,"Exe"] . " " . profile . (If tool = "UltraMap" ? "/logerrors " . keymapperProfiles[tool,"Path"] . "\UltraMapLog.log" : ""), % keymapperProfiles[tool,"Path"] ; If there was a problem loading a profile, WinIPAC will pop up with a box saying so with this title/class: "WinIPAC - Downloading ahk_class ThunderRT6FormDC". It does not return any error codes unfortunately. UltraMap requires errors to be logged otherwise it pops up with an error dialog.
  1085. Log(tool . " - Ended")
  1086. }
  1087. }
  1088.  
  1089. ; Function to measure the size of an text
  1090. MeasureText(Text,Options,Font="Arial",Width="", Height="", ReturnMode="W", ByRef H="", ByRef W="", ByRef X="", ByRef Y="", ByRef Chars="", ByRef Lines=""){
  1091. hdc_MeasureText := GetDC("MeasureText_hwnd")
  1092. G_MeasureText := Gdip_GraphicsFromHDC(hdc_MeasureText)
  1093. RECTF_STR := Gdip_TextToGraphics(G_MeasureText, Text, Options, Font, Width, Height, 1)
  1094. StringSplit,RCI,RECTF_STR, |
  1095. W := Ceil(RCI3)
  1096. H := Ceil(RCI4)
  1097. X := Ceil(RCI1)
  1098. Y := Ceil(RCI2)
  1099. Chars := Ceil(RCI5)
  1100. Lines := Ceil(RCI6)
  1101. DeleteDC(hdc_MeasureText), Gdip_DeleteGraphics(G_MeasureText)
  1102. Return (ReturnMode="X") ? X : (ReturnMode="Y") ? Y :(ReturnMode="W") ? W :(ReturnMode="H") ? H : (ReturnMode="Chars") ? Chars : Lines
  1103. }
  1104.  
  1105.  
  1106. ; Function that allows making applications transparent so they can be hidden completely w/o moving them
  1107. FadeApp(title,direction,time=0){
  1108. startTime := A_TickCount
  1109. Loop{
  1110. t := ((TimeElapsed := A_TickCount-startTime) < time) ? (If direction="in" ? 255*(timeElapsed/time) : 255*(1-(timeElapsed/time))) : (If direction="in" ? 255 : 0)
  1111. WinSet, Transparent, %t%, %title%
  1112. If (direction = "in" && t >= 255) or (direction = "out" && t <= 0) {
  1113. If (direction = "in")
  1114. WinSet, Transparent, Off, %title%
  1115. Break
  1116. }
  1117. }
  1118. Log("HideFE - " . (If direction = "out" ? "Hiding Frontend by making it transparent" : "Showing Frontend and removing transparency"))
  1119. }
  1120.  
  1121. ; SplitPath function with support for roms that contain multiple periods in their name. AHK SplitPath does not support this.
  1122. SplitPath(in,Byref outFileName,Byref outPath,Byref outExt,Byref outNameNoExt) {
  1123. regx := "(\\{2}|(^[\w]:\\))([\w].+\w\\)" ; return path on regexmath and file on regexreplace
  1124. regext := "((\.[^.\s]+)+)$" ; return extension with period (match literal period, match one or more at beginning any character and white space, one or more of all previous, and entire match must appear at end)
  1125. in := RegExReplace(in,"/","\") ; replace all occurences of / with \
  1126. RegExMatch(in, regx, outPathBSlash) ; path with backslash
  1127. pathLen := StrLen(outPathBSlash) ; get length of path with slash
  1128. outPath := SubStr(outPathBSlash, 1, pathLen - 1) ; grab path w/o slash
  1129. RegExMatch(in, regext, outExtP) ; get ext with period
  1130. outExt := SubStr(outExtP, 2) ; get ext and remove period
  1131. outFileName := RegExReplace(in, regx) ; get name with ext
  1132. nameLen := StrLen(outFileName) ; get length of name
  1133. extLen := StrLen(outExt) ; get length of ext
  1134. outNameNoExt := SubStr(outFileName, 1, nameLen - extLen - 1) ; get name w/o ext
  1135. }
  1136.  
  1137. ; This function converts a relative path to absolute
  1138. GetFullName( fn ) {
  1139. ; http://msdn.microsoft.com/en-us/library/Aa364963
  1140. Static buf ;, i ; removing i from static because it needs to be reset from one call to the next
  1141. ; If !i
  1142. i := VarSetCapacity(buf, 512)
  1143. DllCall("GetFullPathNameA", "str", fn, "uint", 512, "str", buf, "str*", 0)
  1144. Return buf
  1145. }
  1146.  
  1147. ; Converts a relative path to an absolute one after providing the base path
  1148. AbsoluteFromRelative(MasterPath, RelativePath)
  1149. {
  1150. VarSetCapacity(AbsP,260,0)
  1151. DllCall( "shlwapi\PathCombineA", Str,AbsP, Str,MasterPath, Str,RelativePath )
  1152. Return AbsP
  1153. }
  1154.  
  1155. ; FileGetVersionInfo_AW which gets file attributes
  1156. FileGetVersionInfo_AW( peFile="", StringFileInfo="", Delimiter="|") {
  1157. Static CS, HexVal, Sps=" ", DLL="Version\"
  1158. If ( CS = "" )
  1159. CS := A_IsUnicode ? "W" : "A", HexVal := "msvcrt\s" (A_IsUnicode ? "w": "" ) "printf"
  1160. If ! FSz := DllCall( DLL "GetFileVersionInfoSize" CS , Str,peFile, UInt,0 )
  1161. Return "", DllCall( "SetLastError", UInt,1 )
  1162. VarSetCapacity( FVI, FSz, 0 ), VarSetCapacity( Trans,8 * ( A_IsUnicode ? 2 : 1 ) )
  1163. DllCall( DLL "GetFileVersionInfo" CS, Str,peFile, Int,0, UInt,FSz, UInt,&FVI )
  1164. If ! DllCall( DLL "VerQueryValue" CS, UInt,&FVI, Str,"\VarFileInfo\Translation", UIntP,Translation, UInt,0 )
  1165. Return "", DllCall( "SetLastError", UInt,2 )
  1166. If ! DllCall( HexVal, Str,Trans, Str,"%08X", UInt,NumGet(Translation+0) )
  1167. Return "", DllCall( "SetLastError", UInt,3 )
  1168. Loop, Parse, StringFileInfo, %Delimiter%
  1169. { subBlock := "\StringFileInfo\" SubStr(Trans,-3) SubStr(Trans,1,4) "\" A_LoopField
  1170. If ! DllCall( DLL "VerQueryValue" CS, UInt,&FVI, Str,SubBlock, UIntP,InfoPtr, UInt,0 )
  1171. Continue
  1172. Value := DllCall( "MulDiv", UInt,InfoPtr, Int,1, Int,1, "Str" )
  1173. Info .= Value ? ( ( InStr( StringFileInfo,Delimiter ) ? SubStr( A_LoopField Sps,1,24 ) . A_Tab : "" ) . Value . Delimiter ) : ""
  1174. } StringTrimRight, Info, Info, 1
  1175. Return Info
  1176. }
  1177.  
  1178. GetOSVersion() {
  1179. VarSetCapacity(v,148), NumPut(148,v)
  1180. DllCall("GetVersionEx", "uint", &v)
  1181. ; Return formatted version string similar to A_AhkVersion.
  1182. ; Assume build number will never be more than 4 characters.
  1183. return NumGet(v,4) ; major
  1184. . "." NumGet(v,8) ; minor
  1185. . "." SubStr("0000" NumGet(v,12), -3) ; build
  1186. }
  1187.  
  1188. ; Returns system paths
  1189. ; For example, GetCommonPath("LOCAL_APPDATA") will return the full path to yout local appdata folder: C:\Users\NAME\AppData\Local
  1190. GetCommonPath(csidl) {
  1191. Static init
  1192. If !init
  1193. {
  1194. CSIDL_APPDATA := 0x001A ; Application Data, new for NT4
  1195. CSIDL_COMMON_APPDATA := 0x0023 ; All Users\Application Data
  1196. CSIDL_COMMON_DOCUMENTS := 0x002e ; All Users\Documents
  1197. CSIDL_DESKTOP := 0x0010 ; C:\Documents and Settings\username\Desktop
  1198. CSIDL_FONTS := 0x0014 ; C:\Windows\Fonts
  1199. CSIDL_LOCAL_APPDATA := 0x001C ; non roaming, user\Local Settings\Application Data
  1200. CSIDL_MYMUSIC := 0x000d ; "My Music" folder
  1201. CSIDL_MYPICTURES := 0x0027 ; My Pictures, new for Win2K
  1202. CSIDL_PERSONAL := 0x0005 ; My Documents
  1203. CSIDL_PROGRAM_FILES_COMMON := 0x002b ; C:\Program Files\Common
  1204. CSIDL_PROGRAM_FILES := 0x0026 ; C:\Program Files
  1205. CSIDL_PROGRAMS := 0x0002 ; C:\Documents and Settings\username\Start Menu\Programs
  1206. CSIDL_RESOURCES := 0x0038 ; %windir%\Resources\, For theme and other windows resources.
  1207. CSIDL_STARTMENU := 0x000b ; C:\Documents and Settings\username\Start Menu
  1208. CSIDL_STARTUP := 0x0007 ; C:\Documents and Settings\username\Start Menu\Programs\Startup.
  1209. CSIDL_SYSTEM := 0x0025 ; GetSystemDirectory()
  1210. CSIDL_WINDOWS := 0x0024 ; GetWindowsDirectory()
  1211. }
  1212. val := CSIDL_%csidl%
  1213. VarSetCapacity(fpath, 256)
  1214. DllCall("shell32\SHGetFolderPathA", "uint", 0, "int", val, "uint", 0, "int", 0, "str", fpath)
  1215. Return %fpath%
  1216. }
  1217.  
  1218. ; StrX function because some modules use it and Pause needs it for XML reading
  1219. StrX( H, BS="",BO=0,BT=1, ES="",EO=0,ET=1, ByRef N="" ) {
  1220. Return SubStr(H,P:=(((Z:=StrLen(ES))+(X:=StrLen(H))+StrLen(BS)-Z-X)?((T:=InStr(H,BS,0,((BO
  1221. <0)?(1):(BO))))?(T+BT):(X+1)):(1)),(N:=P+((Z)?((T:=InStr(H,ES,0,((EO)?(P+1):(0))))?(T-P+Z
  1222. +(0-ET)):(X+P)):(X)))-P)
  1223. }
  1224.  
  1225. HexCompareWrite(file,Pos,Value){
  1226. If (value = "") {
  1227. Log("HexCompareWrite - NULL value supplied",2)
  1228. Return
  1229. }
  1230. curBin := BinRead(file,nvramData,1,Pos) ; read binary
  1231. Bin2Hex(curHex,nvramData,curBin) ; convert to hex
  1232. If (curHex != value) {
  1233. Log("HexCompareWrite - Changing " . curHex . " to " . value . " in: " . file,4)
  1234. Hex2Bin(binData,value)
  1235. BinWrite(file,binData,1,Pos)
  1236. }
  1237. }
  1238.  
  1239. i18n(key, defaultLocale = "English_United_States", p0 = "-0", p1 = "-0", p2 = "-0", p3 = "-0", p4 = "-0", p5 = "-0", p6 = "-0", p7 = "-0", p8 = "-0", p9 = "-0") {
  1240. Global sysLang,langFile
  1241. Log("i18n - Started",4)
  1242. IniRead, phrase, %langFile%, %sysLang%, %key%
  1243. If (phrase = "ERROR" || phrase = "")
  1244. {
  1245. ; Nothing found, test with generic language
  1246. StringSplit, keyArray, sysLang, _
  1247. Log("i18n - Section """ . sysLang . """ & key """ . key . """ not found, trying section """ . keyArray1 . """",4)
  1248. IniRead, phrase, %langFile% , %keyArray1%, %key%
  1249. If (phrase = "ERROR" || phrase = "")
  1250. {
  1251. Log("i18n - Section """ . keyArray1 . """ & key """ . key . """ not found, trying section """ . defaultLocale . """",4)
  1252. ; Nothing found, test with default locale if one is provided
  1253. If (defaultLocale != "")
  1254. {
  1255. IniRead, phrase, %langFile% , %defaultLocale%, %key%
  1256. If (phrase = "ERROR" || phrase = "")
  1257. {
  1258. ; Nothing found, test with generic language for default locale as well
  1259. StringSplit, keyArray, defaultLocale, _
  1260. Log("i18n - Section """ . defaultLocale . """ & key """ . key . """ not found, trying section """ . keyArray1 . """",4)
  1261. IniRead, phrase, %langFile% , %keyArray1%, %key%
  1262. }
  1263. }
  1264. ; Nothing found return original value
  1265. If (defaultLocale = "" || phrase = "ERROR" || phrase = "") {
  1266. Log("i18n - Ended, no phrase found for """ . key . """ in language """ . sysLang . """. Using default """ . key . """",2)
  1267. Return % key
  1268. }
  1269. }
  1270. }
  1271.  
  1272. StringReplace, phrase, phrase, `\n, `r`n, ALL
  1273. StringReplace, phrase, phrase, `\t, % A_Tab, ALL
  1274. Loop 10
  1275. {
  1276. idx := A_Index - 1
  1277. IfNotEqual, p%idx%, -0
  1278. phrase := RegExReplace(phrase, "\{" . idx . "\}", p%idx%)
  1279. }
  1280. Log("i18n - Ended, using """ . phrase . """ for """ . key . """",4)
  1281. Return % phrase
  1282. }
  1283.  
  1284. ; Debug console handler
  1285. DebugMessage(str) {
  1286. Global rlTitle,rlVersion,rlDebugConsoleStdout
  1287. If !rlDebugConsoleStdout
  1288. DebugConsoleInitialize(rlDebugConsoleStdout, rlTitle . " v" . rlVersion . " Debug Console") ; start console window if not yet started
  1289. str .= "`n" ; add line feed
  1290. FileAppend %str%, CONOUT$
  1291. ; FileAppend %str%`n, * ; Works with SciTE and similar editors.
  1292. ; OutputDebug %str%`n ; Works with Visual Studio and DbgView.
  1293. WinSet, Bottom,, ahk_id %rlDebugConsoleStdout% ; keep console on bottom
  1294. }
  1295.  
  1296. DebugConsoleInitialize(ByRef handle, title="") {
  1297. ; two calls to open, no error check (it's debug, so you know what you are doing)
  1298. DllCall("AttachConsole", int, -1, int)
  1299. DllCall("AllocConsole", int)
  1300.  
  1301. DllCall("SetConsoleTitle", "str", (If title ? title : a_scriptname)) ; Set the title
  1302. handle := DllCall("GetStdHandle", "int", -11) ; get the handle
  1303. WinSet, Bottom,, ahk_id %handle% ; make sure it's on the bottom
  1304. Return
  1305. }
  1306.  
  1307. ;Sends a command to the active window using AHK key names. It will always send down/up keypresses for better compatibility
  1308. ;A special command {Wait} can be used to force a sleep of the time defined by WaitTime
  1309. ;WaitCommandOffset will affect all Wait events passed in the Command string by this amount
  1310. SendCommand(Command, SendCommandDelay=2000, WaitTime=500, WaitBetweenSends=0, Delay=50, PressDuration=-1, WaitCommandOffset=0) {
  1311. Log("SendCommand - Started")
  1312. Log("SendCommand - Command: " . Command . "`r`n`t`t`t`t`tSendCommandDelay: " . SendCommandDelay . "`r`n`t`t`t`t`tWaitTime: " . WaitTime . "`r`n`t`t`t`t`tWaitBetweenSends: " . WaitBetweenSends . "`r`n`t`t`t`t`tDelay: " . Delay . "`r`n`t`t`t`t`tPressDuration: " . PressDuration . "`r`n`t`t`t`t`tWaitCommandOffset: " . WaitCommandOffset,4)
  1313. ArrayCount := 0 ;Keeps track of how many items are in the array.
  1314. InsideBrackets := 0 ;If 1 it means the current array item starts with {
  1315. SavedKeyDelay := A_KeyDelay ;Saving previous key delay and setting the new one
  1316. SetKeyDelay, %Delay%, %PressDuration%
  1317. Sleep, %SendCommandDelay% ;Wait before starting to send any command
  1318.  
  1319. ;Create an array with each command as an array element
  1320. Loop, % StrLen(Command)
  1321. { StrValue := SubStr(Command,A_Index,1)
  1322. ; { StringMid, StrValue, Command, A_Index, 1
  1323. If (StrValue != A_Space || InsideBrackets = 1) ; Spaces must be allowed when inside brackets so we can issue {Shift Down} for instance
  1324. { If (InsideBrackets = 0)
  1325. ArrayCount += 1
  1326. If (StrValue = "{")
  1327. { If (InsideBrackets = 1)
  1328. ScriptError("Non-Matching brackets detected in the SendCommand parameter, please correct it")
  1329. Else
  1330. InsideBrackets := 1
  1331. } Else If (StrValue = "}")
  1332. { If (InsideBrackets = 0)
  1333. ScriptError("Non-Matching brackets detected in the SendCommand parameter, please correct it")
  1334. Else
  1335. InsideBrackets := 0
  1336. }
  1337. Array%ArrayCount% := Array%ArrayCount% . StrValue ;Update the array data
  1338. }
  1339. }
  1340.  
  1341. ;Loop through the array and send the commands
  1342. Loop %ArrayCount%
  1343. { element := Array%A_Index%
  1344.  
  1345. If (WaitBetweenSends = 1)
  1346. Sleep, %WaitTime%
  1347.  
  1348. ;Particular cases check if the commands already come with down or up suffixes on them and if so send the commands directly without appending Up/Down
  1349. If RegExMatch(element,"i)Down}")
  1350. { If (element != "{Down}")
  1351. { Send, %element%
  1352. continue
  1353. }
  1354. }
  1355. Else If RegExMatch(element,"i)Up}")
  1356. { If (element != "{Up}")
  1357. { Send, %element%
  1358. Continue
  1359. }
  1360. }
  1361. Else If (element = "{Wait}") ;Special non-ahk tag to issue a sleep
  1362. { NewWaitTime := WaitTime + WaitCommandOffset
  1363. Sleep, %NewWaitTime%
  1364. Continue
  1365. }
  1366. Else If RegExMatch(element,"i)\{Wait:")
  1367. { ;Wait for a specified amount of time {Wait:xxx}
  1368. ; StringMid, NewWaitTime, element, 7, StrLen(element) - 7
  1369. NewWaitTime := SubStr(element,7,StrLen(element) - 7)
  1370. NewWaitTime := NewWaitTime + WaitCommandOffset
  1371. Sleep, %NewWaitTime%
  1372. Continue
  1373. }
  1374.  
  1375. ;the rest of the commands, send a keypress with down and up suffixes
  1376. If RegExMatch(element,"}")
  1377. { StrElement := SubStr(element,1,StrLen(element) - 1)
  1378. ; { StringLeft, StrElement, element, StrLen(element) - 1
  1379. Send, %StrElement% down}%StrElement% up}
  1380. } Else
  1381. Send, {%element% down}{%element% up}
  1382. }
  1383. ;Restore key delay values
  1384. SetKeyDelay(SavedKeyDelay, -1)
  1385. Log("SendCommand - Ended")
  1386. }
  1387.  
  1388. ; Purpose: Tell a ServoStik to transition to 4 or 8-way mode
  1389. ; Parameters:
  1390. ; direction = Can be 4 or 8, self-explanatory
  1391. ServoStik(direction) {
  1392. Log("ServoStik - Started")
  1393. Global PacDriveDllFile,servoStikEnabled
  1394. Static dllExists
  1395. If !RegExMatch(direction,"4|8")
  1396. {
  1397. Log("ServoStik - """ . direction . """ is not a supported direction for ServoSticks. Only 4 and 8 are supported. Leaving your ServoStik as is.",2)
  1398. Return
  1399. }
  1400. If !dllExists {
  1401. CheckFile(pacDrivedllFile, "Following file is required for RocketLauncher ServoStik support, but could not be found:`n" . pacDrivedllFile)
  1402. dllExists := 1 ; do not run this check again
  1403. }
  1404. pacDriveLoadModule := DllCall("LoadLibrary", "Str", PacDriveDllFile) ; Avoids the need for ahk to load and free the dll's library multiple times
  1405. pacInitialize := DllCall(PacDriveDllFile . "\PacInitialize") ; Initialize all PacDrive, PacLED64 and U-HID Devices and return the amount connected to system
  1406. If !pacInitialize {
  1407. Log("ServoStik - No devices found on system",2)
  1408. Log("ServoStik - Ended")
  1409. Return
  1410. } Else
  1411. Log("ServoStik - " . pacInitialize . " devices found on system. If you have multiple devices, this should list more than one and may not specifically mean a ServoStik was found")
  1412.  
  1413. result := DllCall(PacDriveDllFile . "\PacSetServoStik" . direction . "Way") ; Tell ServoStiks to change to desired direction
  1414. If !result
  1415. Log("ServoStik - There was a problem telling your ServoStik(s) to go " . direction . "-Way",3)
  1416. Else
  1417. Log("ServoStik - ServoStik(s) were told to go " . direction . "-Way")
  1418. ; pacDriveUnloadModule := DllCall("FreeLibrary", "UInt", pacDriveLoadModule) ; To conserve memory, the DLL is unloaded after using it.
  1419. Log("ServoStik - Ended")
  1420. }
  1421.  
  1422. GetTimeString(time) {
  1423. If (time<0)
  1424. Return time
  1425. If time is not number
  1426. Return time
  1427. Days := time // 86400
  1428. Hours := Mod(time, 86400) // 3600
  1429. Minutes := Mod(time, 3600) // 60
  1430. Seconds := Mod(time, 60)
  1431. If (Days<>0) {
  1432. If Strlen(Hours) = 1
  1433. Hours = 0%Hours%
  1434. If Strlen(Minutes) = 1
  1435. Minutes = 0%Minutes%
  1436. If Strlen(Seconds) = 1
  1437. Seconds = 0%Seconds%
  1438. TimeString = %Days%d %Hours%h %Minutes%m %Seconds%s
  1439. } Else If (Hours<>0) {
  1440. If Strlen(Minutes) = 1
  1441. Minutes = 0%Minutes%
  1442. If Strlen(Seconds) = 1
  1443. Seconds = 0%Seconds%
  1444. TimeString = %Hours%h %Minutes%m %Seconds%s
  1445. } Else If (Minutes<>0) {
  1446. If Strlen(Seconds) = 1
  1447. Seconds = 0%Seconds%
  1448. TimeString = %Minutes%m %Seconds%s
  1449. } Else If (Seconds<>0)
  1450. TimeString = %Seconds%s
  1451. Else
  1452. TimeString := ""
  1453. Return TimeString
  1454. }
  1455.  
  1456. ReplaceFileNameInvalidChar(ByRef hastack,list,replaceChar){
  1457. Loop, Parse, list, `,
  1458. StringReplace, hastack, hastack, %a_loopfield%, %replaceChar%, All
  1459. Return hastack
  1460. }
  1461.  
  1462.  
  1463. ;-------------------------------------------------------------------------------------------------------------
  1464. ;-------------------------------------------- RL Media Functions ---------------------------------------------
  1465. ;-------------------------------------------------------------------------------------------------------------
  1466. rndRLMediaLogoPath(assetType){
  1467. Global RLMedia, feMedia, gameInfo
  1468. If !(RLMedia)
  1469. RLMedia := loadRLMediaLogos(gameInfo)
  1470. LogoImageList := []
  1471. for index, element in RLMedia["Logos"]
  1472. If (element.Label)
  1473. If (element.AssetType=assetType)
  1474. Loop, % element.TotalItems
  1475. LogoImageList.Insert(element["Path" . a_index])
  1476. If !(LogoImageList[1])
  1477. for index, element in feMedia["Logos"]
  1478. If (element.Label)
  1479. If (element.AssetType=assetType)
  1480. Loop, % element.TotalItems
  1481. LogoImageList.Insert(element["Path" . a_index])
  1482. If (LogoImageList[1]) {
  1483. Random, RndmLogoImage, 1, % LogoImageList.MaxIndex()
  1484. Return LogoImageList[RndmLogoImage]
  1485. }
  1486. }
  1487.  
  1488. LoadRLMediaLogos(gameInfoObj){
  1489. Global RLMediaPath, RLMedia, systemname, dbname, romTable, mgCandidate
  1490. RLMedia := {}
  1491. LogoList := "Genre|Rating|Developer|Publisher|Year"
  1492. Loop, Parse, LogoList, |
  1493. { If (gameInfoObj[A_LoopField].Value){
  1494. %A_LoopField% := gameInfoObj[A_LoopField].Value
  1495. If (A_LoopField = "Genre"){
  1496. ReplaceFileNameInvalidChar(%A_LoopField%,"/,|","\") ;Replacing invalid file name characters by folder separator ("\")
  1497. ReplaceFileNameInvalidChar(%A_LoopField%,"*","-") ;Replacing invalid file name characters by hippens ("-")
  1498. } Else
  1499. ReplaceFileNameInvalidChar(%A_LoopField%,"/,*,|","-") ;Replacing invalid file name characters by hippens ("-")
  1500. ReplaceFileNameInvalidChar(%A_LoopField%,":"," - ") ;Replacing invalid file name characters by hippens ("-")
  1501. ReplaceFileNameInvalidChar(%A_LoopField%,"?," . """" . ",<,>","") ;Replacing invalid file name characters by hippens ("-")
  1502. %A_LoopField% :=RegExReplace(%A_LoopField%,"^\s+|\s+(?=\s)|\s$") ;remove double white spaces
  1503. If (FileExist(RLMediaPath . "\" . A_LoopField . "\" . systemname . "\" . dbname . "\" . %A_LoopField% . ".*"))
  1504. %A_LoopField%Path := RLMediaPath . "\" . A_LoopField . "\" . systemname . "\" . dbname . "\" . %A_LoopField% . ".*"
  1505. Else If (FileExist(RLMediaPath . "\" . A_LoopField . "\" . systemname . "\_Default\" . %A_LoopField% . ".*"))
  1506. %A_LoopField%Path := RLMediaPath . "\" . A_LoopField . "\" . systemname . "\_Default\" . %A_LoopField% . ".*"
  1507. Else
  1508. %A_LoopField%Path := RLMediaPath . "\" . A_LoopField . "\_Default\" . %A_LoopField% . ".*"
  1509. }
  1510. }
  1511. RLMedia.Logos := BuildAssetsTable(GenrePath . "|" . RatingPath . "|" . DeveloperPath . "|" . PublisherPath . "|" . YearPath,"Genre Logo|Rating Logo|Developer Logo|Publisher Logo|Year Logo","genre|rating|developer|publisher|year","png|bmp|gif|jpg|tif")
  1512. systemLogoPath := RLMediaPath . "\Logos\" . systemname . "\_Default\"
  1513. gameLogoPath1 := RLMediaPath . "\Logos\" . systemname . "\" . dbname . "\"
  1514. ;Description name without (Disc X)
  1515. If (!romTable && mgCandidate)
  1516. romTable := CreateRomTable(dbName)
  1517. Totaldiscsofcurrentgame := romTable.MaxIndex()
  1518. If (Totaldiscsofcurrentgame > 1) {
  1519. DescriptionNameWithoutDisc := romTable[1,4]
  1520. gameLogoPath2 := RLMediaPath . "\Logos\" . systemname . "\" . DescriptionNameWithoutDisc . "\"
  1521. }
  1522. RLMedia.Logos := BuildAssetsTable(systemLogoPath . "|" . gameLogoPath1 . "|" . gameLogoPath2,"System Logo|Game Logo|Game Logo","system|game|game","png|bmp|gif|jpg|tif",RLMedia.Logos)
  1523. Return RLMedia
  1524. }
  1525.  
  1526. ; Inject a shared function for Pause and Fade which adjusts the background image positioning
  1527. ; Usage, params 1-4 are byref so supply the var you want to be filled with the calculated positions and size. Next 2 are the original pics width and height. Last is the position the user wants.
  1528. GetBGPicPosition(ByRef retX,ByRef retY,ByRef retW,ByRef retH,w,h,pos){
  1529. Global baseScreenWidth, baseScreenHeight
  1530. widthMaxPercent := ( baseScreenWidth / w ) ; get the percentage needed to maximumise the image so it reaches the screen's width
  1531. heightMaxPercent := ( baseScreenHeight / h )
  1532. If (pos = "Stretch and Lose Aspect") { ; image is stretched to screen, loosing aspect
  1533. retW := baseScreenWidth
  1534. retH := baseScreenHeight
  1535. retX := 0
  1536. retY := 0
  1537. } Else If (pos = "Stretch and Keep Aspect") { ; image is stretched to Center screen, keeping aspect
  1538. percentToEnlarge := If (widthMaxPercent < heightMaxPercent) ? widthMaxPercent : heightMaxPercent ; this basicallys says if the width's max reaches the screen's width first, use the width's percentage instead of the height's
  1539. retW := Round(w * percentToEnlarge) ; multiply width by the percentage from above to reach as close to the edge as possible
  1540. retH := Round(h * percentToEnlarge) ; multiply height by the percentage from above to reach as close to the edge as possible
  1541. retX := ( baseScreenWidth / 2 ) - ( retW / 2 ) ; find where to place the X of the image
  1542. retY := ( baseScreenHeight / 2 ) - ( retH / 2 ) ; find where to place the Y of the image
  1543. } Else If (pos = "Center Width") { ; image is stretched to Center screen's width, keeping aspect
  1544. percentToEnlarge := widthMaxPercent ; increase the image size by the percentage it takes to reaches the screen's width, cropping may occur on top and bottom
  1545. retW := Round(w * percentToEnlarge) ; multiply width by the percentage from above to reach as close to the edge as possible
  1546. retH := Round(h * percentToEnlarge) ; multiply height by the percentage from above to reach as close to the edge as possible
  1547. retX := ( baseScreenWidth / 2 ) - ( retW / 2 ) ; find where to place the X of the image
  1548. retY := ( baseScreenHeight / 2 ) - ( retH / 2 ) ; find where to place the Y of the image
  1549. } Else If (pos = "Center Height") { ; image is stretched to Center screen's height, keeping aspect
  1550. percentToEnlarge := heightMaxPercent ; increase the image size by the percentage it takes to reaches the screen's height, cropping may occur on left and right
  1551. retW := Round(w * percentToEnlarge) ; multiply width by the percentage from above to reach as close to the edge as possible
  1552. retH := Round(h * percentToEnlarge) ; multiply height by the percentage from above to reach as close to the edge as possible
  1553. retX := ( baseScreenWidth / 2 ) - ( retW / 2 ) ; find where to place the X of the image
  1554. retY := ( baseScreenHeight / 2 ) - ( retH / 2 ) ; find where to place the Y of the image
  1555. } Else If (pos = "Center") { ; original image size and aspect
  1556. retX := ( baseScreenWidth / 2 ) - ( w / 2 ) ; find where to place the X of the image
  1557. retY := ( baseScreenHeight / 2 ) - ( h / 2 ) ; find where to place the Y of the image
  1558. } Else If (pos = "Align to Bottom Left") { ; place the pic so the bottom left corner matches the screen's bottom left corner
  1559. retH := baseScreenHeight
  1560. retW := Round( w / ( h / baseScreenHeight ))
  1561. If ( retW < baseScreenWidth ){
  1562. retW := baseScreenWidth
  1563. retH := Round( h / ( w / retW ))
  1564. }
  1565. retY := baseScreenHeight - retH
  1566. } Else If (pos = "Align to Bottom Right") { ; place the pic so the bottom right corner matches the screen's bottom right corner
  1567. retH := baseScreenHeight
  1568. retW := Round( w / ( h / baseScreenHeight ))
  1569. If ( retW < baseScreenWidth ){
  1570. retW := baseScreenWidth
  1571. retH := Round( h / ( w / retW ))
  1572. }
  1573. retX := baseScreenWidth - retW
  1574. retY := baseScreenHeight - retH
  1575. } Else If (pos = "Align to Top Right") { ; place the pic so the top right corner matches the screen's top right corner
  1576. retH := baseScreenHeight
  1577. retW := Round( w / ( h / baseScreenHeight ))
  1578. If ( retW < baseScreenWidth ){
  1579. retW := baseScreenWidth
  1580. retH := Round( h / ( w / retW ))
  1581. }
  1582. retX := baseScreenWidth - retW
  1583. } Else { ; place the pic so the top left corner matches the screen's top left corner, also the default
  1584. retH := baseScreenHeight
  1585. retW := Round( w / ( h / baseScreenHeight ))
  1586. If ( retW < baseScreenWidth ){
  1587. retW := baseScreenWidth
  1588. retH := Round( h / ( w / retW ))
  1589. }
  1590. }
  1591. }
  1592.  
  1593. ; Usage, params 1&2 are byref so supply the var you want to be filled with the calculated positions. Next 4 are the original pics xy,w,h. Last is the position the user wants.
  1594. GetFadePicPosition(ByRef retX, ByRef retY,x,y,w,h,pos){
  1595. Global baseScreenWidth, baseScreenHeight
  1596. If (pos = "Stretch and Lose Aspect"){ ; image is stretched to screen, loosing aspect
  1597. retX := 0
  1598. retY := 0
  1599. } Else If (pos = "Stretch and Keep Aspect") { ; image is stretched to screen, keeping aspect
  1600. retX := round(( baseScreenWidth / 2 ) - ( w / 2 ))
  1601. retY := round(( baseScreenHeight / 2 ) - ( h / 2 ))
  1602. } Else If (pos = "Center") {
  1603. retX := round(( baseScreenWidth / 2 ) - ( w / 2 ))
  1604. retY := round(( baseScreenHeight / 2 ) - ( h / 2 ))
  1605. } Else If (pos = "Top Left Corner") {
  1606. retX := 0
  1607. retY := 0
  1608. } Else If (pos = "Top Right Corner") {
  1609. retX := baseScreenWidth - w
  1610. retY := 0
  1611. } Else If (pos = "Bottom Left Corner") {
  1612. retX := 0
  1613. retY := baseScreenHeight - h
  1614. } Else If (pos = "Bottom Right Corner") {
  1615. retX := baseScreenWidth - w
  1616. retY := baseScreenHeight - h
  1617. } Else If (pos = "Top Center") {
  1618. retX := round(( baseScreenWidth / 2 ) - ( w / 2 ))
  1619. retY := 0
  1620. } Else If (pos = "Bottom Center") {
  1621. retX := round(( baseScreenWidth / 2 ) - ( w / 2 ))
  1622. retY := baseScreenHeight - h
  1623. } Else If (pos = "Left Center") {
  1624. retX := 0
  1625. retY := round(( baseScreenHeight / 2 ) - ( h / 2 ))
  1626. } Else If (pos = "Right Center") {
  1627. retX := baseScreenWidth - w
  1628. retY := round(( baseScreenHeight / 2 ) - ( h / 2 ))
  1629. } Else {
  1630. retX := x
  1631. retY := y
  1632. }
  1633. }
  1634.  
  1635. GetRLMediaFiles(mediaType,supportedFileTypes,returnArray=0) {
  1636. Log("GetRLMediaFiles - Started",4)
  1637. Global RLMediaPath,dbName,systemName,romTable,mgCandidate
  1638. If (!romTable && mgCandidate)
  1639. romTable:=CreateRomTable(dbName)
  1640. DescriptionNameWithoutDisc := romTable[1,4]
  1641. romFolder := RLMediaPath . "\" . mediaType . "\" . systemName . "\" . dbName . "\"
  1642. romDisckLessFolder := RLMediaPath . "\" . mediaType . "\" . systemName . "\" . DescriptionNameWithoutDisc . "\"
  1643. systemFolder := RLMediaPath . "\" . mediaType . "\" . systemName . "\_Default\"
  1644. globalFolder := RLMediaPath . "\" . mediaType . "\_Default\"
  1645. imagesArray := []
  1646. Loop, Parse, supportedFileTypes, |
  1647. If FileExist(romFolder . "*." . A_LoopField) {
  1648. Loop % romFolder . "*." . A_LoopField
  1649. imagesArray[A_Index] := A_LoopFileFullPath
  1650. }
  1651. If imagesArray.MaxIndex() <= 0
  1652. Loop, Parse, supportedFileTypes, |
  1653. If FileExist(romDisckLessFolder . "*." . A_LoopField) {
  1654. Loop % romDisckLessFolder . "*." . A_LoopField
  1655. imagesArray[A_Index] := A_LoopFileFullPath
  1656. }
  1657. If imagesArray.MaxIndex() <= 0
  1658. Loop, Parse, supportedFileTypes, |
  1659. If FileExist(systemFolder . "*." . A_LoopField) {
  1660. Loop % systemFolder . "*." . A_LoopField
  1661. imagesArray[A_Index] := A_LoopFileFullPath
  1662. }
  1663. If imagesArray.MaxIndex() <= 0
  1664. Loop, Parse, supportedFileTypes, |
  1665. If FileExist(globalFolder . "*." . A_LoopField) {
  1666. Loop % globalFolder . "*." . A_LoopField
  1667. imagesArray[A_Index] := A_LoopFileFullPath
  1668. }
  1669. If returnArray {
  1670. Log("GetRLMediaFiles - Ended, returning array",4)
  1671. Return imagesArray
  1672. }
  1673. Else {
  1674. Random, RndmImagePic, 1, % imagesArray.MaxIndex()
  1675. file := imagesArray[RndmImagePic]
  1676. Log("GetRLMediaFiles - Ended, randomized RocketLauncher " . mediaType . " file selected: " . file)
  1677. Return file
  1678. }
  1679. }
  1680.  
  1681.  
  1682. ;-------------------------------------------------------------------------------------------------------------
  1683. ;----------------------------------------- DXWnd Functions -----------------------------------------
  1684. ;-------------------------------------------------------------------------------------------------------------
  1685.  
  1686. ; If you provide a value, DxwndIniRW assumes you want to write to the ini
  1687. ; If no value is provided, DxwndIniRW assumes you want to read from the ini and returns the value
  1688. ; DxwndIniRW is only used to read and write settings to dxwnd.ini
  1689. ; DxwndRun is for launching dxwnd
  1690. ; DxwndClose is for closing dxwnd
  1691. ; DxwndUpdateIniPath is for updating the dxwndIni variable
  1692. DxwndIniRW(sec="",key="",val="", default="", cTarget="") {
  1693. Log("DxwndIniRW - Started")
  1694. Global dxwndIni,romName
  1695. Static pos,iniExists
  1696. If !iniExists {
  1697. CheckFile(dxwndIni)
  1698. iniExists := 1 ; do not run this check again
  1699. }
  1700. If !pos { ; the current romName or cTarget position has not been found, loop through the ini to find it first
  1701. targetGame := If cTarget ? cTarget : romName
  1702. Loop {
  1703. pos := a_index-1
  1704. IniRead, dxwndName, %dxwndIni%, target, title%pos%
  1705. If (dxwndName = targetGame)
  1706. Break
  1707. If (dxwndName = "ERROR")
  1708. ScriptError("There was a problem finding """ . targetGame . """ in the DXWnd Ini. Please make sure you have added this game to DXWnd before attempting to launch DXWnd through it.")
  1709. }
  1710. }
  1711. errLvl := Process("Exist", "dxwnd.exe") ; Make sure dxwnd is not running first so settings don't get reverted
  1712. If errLvl {
  1713. DxwndClose()
  1714. Process("WaitClose", "dxwnd.exe")
  1715. }
  1716. If val {
  1717. IniWrite, %val%, %dxwndIni%, %sec%, %key%%pos%
  1718. Log("DxwndIniRW - Wrote """ . val . """ to game #" . pos,4)
  1719. } Else {
  1720. IniRead, val, %dxwndIni%, %sec%, %key%%pos%
  1721. Log("DxwndIniRW - Read """ . val . """",4)
  1722. Log("DxwndIniRW - Ended")
  1723. Return val
  1724. }
  1725. Log("DxwndIniRW - Ended")
  1726. }
  1727.  
  1728. DxwndRun(ByRef outPID="") {
  1729. Log("DxwndRun - Started")
  1730. Global dxwndFullPath,dxwndExe,dxwndPath,dxwndIni
  1731. Static exeExists
  1732. If !exeExists {
  1733. CheckFile(dxwndFullPath, "Following file is required for DXWnd support, but its file could not be found:`n" . dxwndFullPath)
  1734. exeExists := 1 ; do not run this check again
  1735. }
  1736. If !dxwndExe
  1737. SplitPath, dxwndFullPath, dxwndExe, dxwndPath
  1738. SplitPath, dxwndIni, dxwndIniFile
  1739.  
  1740. Run(dxwndExe . " /T /C:""" . dxwndIniFile . """", dxwndPath, "Min", outPID)
  1741. errLvl := Process("Wait", dxwndExe, 10) ; waiting 10 seconds for dxwnd to start
  1742. If (errLvl = "")
  1743. ScriptError("DXWnd did not start after waiting for 10 seconds. Please check you can run it manually and try again.")
  1744. Else
  1745. Log("DxwndRun - DxwndRun is now running")
  1746. Log("DxwndRun - Ended")
  1747. }
  1748.  
  1749. DxwndClose() {
  1750. Log("DxwndClose - Started")
  1751. Global dxwndFullPath,dxwndExe,dxwndPath
  1752. If !dxwndExe
  1753. SplitPath, dxwndFullPath, dxwndExe, dxwndPath
  1754. PostMessage, 0x111, 32810,,,ahk_exe %dxwndExe% ; this tells dxwnd to close itself
  1755. Process("WaitClose", dxwndExe, 1) ; waits 1 second for dxwnd to close
  1756. errLvl := Process("Exist", dxwndExe) ; checks if dxwnd is still running
  1757. If errLvl
  1758. Process("Close", dxwndExe) ; only needed when RocketLauncher is not ran as admin or RocketLauncher cannot close dxwnd for some reason
  1759. Log("DxwndClose - Ended")
  1760. }
  1761.  
  1762. DxwndUpdateIniPath() {
  1763. Global dxwndFullPath,dxwndPath,dxwndIni,systemName
  1764. SplitPath,dxwndFullPath,,dxwndPath
  1765.  
  1766. If FileExist( dxwndPath . "\" . systemName . ".ini" )
  1767. dxwndIni := dxwndPath . "\" . systemName . ".ini"
  1768. Else
  1769. dxwndIni := dxwndPath . "\dxwnd.ini"
  1770.  
  1771. Log("DxwndUpdateIniPath - DxwndIni set to " . dxwndIni)
  1772. }
  1773.  
  1774. ;-------------------------------------------------------------------------------------------------------------
  1775. ;----------------------------------- Cursor Control Functions ------------------------------------
  1776. ;-------------------------------------------------------------------------------------------------------------
  1777.  
  1778. ToggleCursor:
  1779. Log("ToggleCursor - Hotkey """ . toggleCursorKey . """ pressed, toggling cursor visibility")
  1780. SystemCursor("Toggle")
  1781. Return
  1782.  
  1783. ; Function to hide/unhide the mouse cursor
  1784. SystemCursor(OnOff=1) ; INIT = "I","Init"; OFF = 0,"Off"; TOGGLE = -1,"T","Toggle"; ON = others
  1785. { Global mouseCursorHidden
  1786. Static AndMask, XorMask, cursor, h_cursor
  1787. ,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13 ; system cursors
  1788. , b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13 ; blank cursors
  1789. , h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11,h12,h13 ; handles of default cursors
  1790. If (OnOff = "Init" or OnOff = "I" or cursor = "") ; init when requested or at first call
  1791. {
  1792. cursor := "h" ; active default cursors
  1793. VarSetCapacity( h_cursor,4444, 1 )
  1794. VarSetCapacity( AndMask, 32*4, 0xFF )
  1795. VarSetCapacity( XorMask, 32*4, 0 )
  1796. system_cursors = 32512,32513,32514,32515,32516,32642,32643,32644,32645,32646,32648,32649,32650
  1797. StringSplit c, system_cursors, `,
  1798. Loop %c0%
  1799. {
  1800. h_cursor := DllCall( "LoadCursor", "uint",0, "uint",c%A_Index% )
  1801. h%A_Index% := DllCall( "CopyImage", "uint",h_cursor, "uint",2, "int",0, "int",0, "uint",0 )
  1802. b%A_Index% := DllCall("CreateCursor","uint",0, "int",0, "int",0
  1803. , "int",32, "int",32, "uint",&AndMask, "uint",&XorMask )
  1804. }
  1805. }
  1806. If (OnOff = 0 or OnOff = "Off" or $ = "h" and (OnOff < 0 or OnOff = "Toggle" or OnOff = "T")){
  1807. cursor := "b" ; use blank cursors
  1808. Log("SystemCursor - Hiding mouse cursor")
  1809. CoordMode, Mouse ; Also lets move it to the side since some emu's flash a cursor real quick even if we hide it.
  1810. MouseMove, 0, 0, 0
  1811. } Else {
  1812. cursor := "h" ; use the saved cursors
  1813. SPI_SETCURSORS := 0x57 ; Emergency restore cursor, just in case something goes wrong
  1814. DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
  1815. mouseCursorHidden := ""
  1816. Log("SystemCursor - Restoring mouse cursor")
  1817. }
  1818.  
  1819. Loop %c0%
  1820. {
  1821. h_cursor := DllCall( "CopyImage", "uint",%cursor%%A_Index%, "uint",2, "int",0, "int",0, "uint",0 )
  1822. DllCall( "SetSystemCursor", "uint",h_cursor, "uint",c%A_Index% )
  1823. }
  1824. }
  1825.  
  1826. SetSystemCursor( Cursor = "", cx = 0, cy = 0 ) {
  1827. BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init
  1828.  
  1829. SystemCursors = 32512IDC_ARROW,32513IDC_IBEAM,32514IDC_WAIT,32515IDC_CROSS
  1830. ,32516IDC_UPARROW,32640IDC_SIZE,32641IDC_ICON,32642IDC_SIZENWSE
  1831. ,32643IDC_SIZENESW,32644IDC_SIZEWE,32645IDC_SIZENS,32646IDC_SIZEALL
  1832. ,32648IDC_NO,32649IDC_HAND,32650IDC_APPSTARTING,32651IDC_HELP
  1833.  
  1834. If (Cursor = "") ; empty, so create blank cursor
  1835. {
  1836. Log("SetSystemCursor - Creating blank cursor",4)
  1837. VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )
  1838. BlankCursor := 1 ; flag for later
  1839. }
  1840. Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor
  1841. {
  1842. Log("SetSystemCursor - Loading system cursor",4)
  1843. Loop, Parse, SystemCursors, `,
  1844. {
  1845. CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr
  1846. CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id
  1847. SystemCursor := 1
  1848. If ( CursorName = Cursor ) {
  1849. CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )
  1850. Break
  1851. }
  1852. }
  1853. If (CursorHandle = "") ; invalid cursor name given
  1854. {
  1855. Log("SetSystemCursor - Invalid cursor name supplied: """ . CursorHandle . """",2)
  1856. ; Msgbox,, SetCursor, Error: Invalid cursor name
  1857. CursorHandle := "Error"
  1858. }
  1859. }
  1860. Else If FileExist( Cursor )
  1861. {
  1862. Log("SetSystemCursor - Found this cursor: """ . Cursor . """",4)
  1863. SplitPath, Cursor,,, Ext ; auto-detect type
  1864. If (Ext = "ico")
  1865. uType := 0x1
  1866. Else If RegExMatch("cur|ani","i)" . Ext)
  1867. uType := 0x2
  1868. Else ; invalid file ext
  1869. {
  1870. Log("SetSystemCursor - Invalid cursor extension: """ . Ext . """",2)
  1871. ; Msgbox,, SetCursor, Error: Invalid file type
  1872. CursorHandle := "Error"
  1873. }
  1874. FileCursor := 1
  1875. }
  1876. Else
  1877. {
  1878. Log("SetSystemCursor - Invalid cursor name or path: """ . Cursor . """",2)
  1879. ; Msgbox,, SetCursor, Error: Invalid file path or cursor name
  1880. CursorHandle := "Error" ; raise for later
  1881. }
  1882. If (CursorHandle != "Error")
  1883. {
  1884. Loop, Parse, SystemCursors, `,
  1885. {
  1886. If (BlankCursor = 1)
  1887. {
  1888. Type := "BlankCursor"
  1889. %Type%%A_Index% := DllCall( "CreateCursor", Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )
  1890. CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
  1891. DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
  1892. }
  1893. Else If (SystemCursor = 1)
  1894. {
  1895. Type := "SystemCursor"
  1896. CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )
  1897. %Type%%A_Index% := DllCall( "CopyImage", Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )
  1898. CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
  1899. DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
  1900. }
  1901. Else If (FileCursor = 1)
  1902. {
  1903. Type := "FileCursor"
  1904. %Type%%A_Index% := DllCall( "LoadImage", UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 )
  1905. DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )
  1906. }
  1907. }
  1908. }
  1909. }
  1910.  
  1911. RestoreCursors() {
  1912. SPI_SETCURSORS := 0x57
  1913. DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
  1914. }
  1915.  
  1916. ;-------------------------------------------------------------------------------------------------------------
  1917. ;------------------ Read and Write Wrapper Functions for IniFileEdit ------------------
  1918. ;-------------------------------------------------------------------------------------------------------------
  1919.  
  1920. ; Usage - Read and Write to config files that are not valid inis with [sections], like RetroArch's cfg
  1921.  
  1922. ; cfgFile - path to the file to read, only need to send this once, it stays in memory until SavePropertiesCfg is used
  1923. ; Returns a reference number to the array where the cfg is stored in memory so multiple files can be edited at once
  1924. LoadProperties(cfgFile) {
  1925. Log("LoadProperties - Started and loading this cfg into memory: " . cfgFile,4)
  1926. cfgtable := Object()
  1927. Loop, Read, %cfgFile% ; This loop retrieves each line from the file, one at a time.
  1928. cfgtable.Insert(A_LoopReadLine) ; Append this line to the array.
  1929. Log("LoadProperties - Ended",4)
  1930. Return cfgtable
  1931. }
  1932.  
  1933. ; cfgFile - path to the file to read, only need to send this once, it stays in memory until SavePropertiesCfg is used
  1934. ; cfgArray - reference number of array in memory that should be saved to the cfgFile
  1935. SaveProperties(cfgFile,cfgArray) {
  1936. Log("SaveProperties - Started and saving this cfg to disk: " . cfgFile,4)
  1937. FileDelete, %cfgFile%
  1938. Loop % cfgArray.MaxIndex()
  1939. { element := cfgArray[A_Index]
  1940. trimmedElement := LTrim(element)
  1941. finalCfg .= trimmedElement . "`n"
  1942. }
  1943. FileAppend, %finalCfg%, %cfgFile%
  1944. Log("SaveProperties - Ended",4)
  1945. }
  1946.  
  1947. ; cfgArray - reference number of array in memory that you want to read
  1948. ; keyName = key whose value you want to read
  1949. ; Separator = the separator to use, defaults to =
  1950. ReadProperty(cfgArray,keyName,Separator="=") {
  1951. Log("ReadProperty - Started",4)
  1952. Loop % cfgArray.MaxIndex()
  1953. { element := cfgArray[A_Index]
  1954. trimmedElement := Trim(element)
  1955. ;MsgBox % "Element number " . A_Index . " is " . element
  1956.  
  1957. StringGetPos, pos, trimmedElement, [
  1958. If (pos = 0)
  1959. Break ; Section was found, do not search anymore, global section has ended
  1960.  
  1961. If element contains %Separator%
  1962. { StringSplit, keyValues, element, %Separator%
  1963. CfgValue := Trim(keyValues1)
  1964. If (CfgValue = keyName)
  1965. Return Trim(keyValues2) ; Found it & trim any whitespace
  1966. }
  1967. }
  1968. Log("ReadProperty - Ended",4)
  1969. }
  1970.  
  1971. ; cfgArray - reference number of array in memory that you want to read
  1972. ; keyName = key whose value you want to write
  1973. ; Value = value that you want to write to the keyName
  1974. ; AddSpaces = If the seperator (=) has spaces on either side, set this parameter to 1 and it will wrap the seperator in spaces
  1975. ; AddQuotes = If the Value needs to be wrapped in double quotes (like in retroarch's config), set this parameter to 1
  1976. ; Separator = the separator to use, defaults to =
  1977. WriteProperty(cfgArray,keyName,Value,AddSpaces=0,AddQuotes=0,Separator="=") {
  1978. Log("WriteProperty - Started",4)
  1979. added := 0
  1980. Loop % cfgArray.MaxIndex()
  1981. { lastIndex := A_Index
  1982. element := cfgArray[A_Index]
  1983. trimmedElement := Trim(element)
  1984.  
  1985. StringGetPos, pos, trimmedElement, [
  1986. If (pos = 0)
  1987. { lastIndex := lastIndex - 1 ; Section was found, do not search anymore
  1988. Break
  1989. }
  1990.  
  1991. If element contains %Separator%
  1992. { StringSplit, keyValues, element, %Separator%
  1993. CfgValue := Trim(keyValues1)
  1994. If (CfgValue = keyName)
  1995. { cfgArray[A_Index] := CfgValue . (If AddSpaces=1 ? (" " . Separator . " ") : Separator) . (If AddQuotes=1 ? ("""" . Value . """") : Value) ; Found it
  1996. added := 1
  1997. Break
  1998. }
  1999. }
  2000. }
  2001. If (added = 0)
  2002. cfgArray.Insert(lastIndex+1, keyName . (If AddSpaces=1 ? (" " . Separator . " ") : Separator) . (If AddQuotes=1 ? ("""" . Value . """") : Value)) ; Add the new entry to the file
  2003. Log("WriteProperty - Ended",4)
  2004. }
  2005.  
  2006. ;-------------------------------------------------------------------------------------------------------------
  2007. ;----------------------------------------- Player Select Menu --------------------------------------
  2008. ;-------------------------------------------------------------------------------------------------------------
  2009.  
  2010. ; function to create a small menu with the number of players option
  2011. NumberOfPlayersSelectionMenu(maxPlayers=4) {
  2012. Global screenRotationAngle,baseScreenWidth,baseScreenHeight,xTranslation,yTranslation
  2013. Global navSelectKey,navUpKey,navDownKey,navP2SelectKey,navP2UpKey,navP2DownKey,exitEmulatorKey,exitEmulatorKey
  2014. Global keymapper,keymapperEnabled,keymapperRocketLauncherProfileEnabled
  2015. If !pToken
  2016. pToken := Gdip_Startup()
  2017. Gdip_Alt_GetRotatedDimensions(A_ScreenWidth, A_ScreenHeight, screenRotationAngle, baseScreenWidth, baseScreenHeight)
  2018. Gdip_GetRotatedTranslation(baseScreenWidth, baseScreenHeight, screenRotationAngle, xTranslation, yTranslation)
  2019. xTranslation:=round(xTranslation), yTranslation:=round(yTranslation)
  2020. Loop, 2 {
  2021. Gui, playersMenu_GUI%A_Index%: +Disabled -Caption +E0x80000 +OwnDialogs +LastFound +ToolWindow +AlwaysOnTop
  2022. Gui, playersMenu_GUI%A_Index%: Margin,0,0
  2023. Gui, playersMenu_GUI%A_Index%: Show,, playersMenuLayer%A_Index%
  2024. playersMenu_hwnd%A_Index% := WinExist()
  2025. playersMenu_hbm%A_Index% := CreateDIBSection(A_ScreenWidth, A_ScreenHeight)
  2026. playersMenu_hdc%A_Index% := CreateCompatibleDC()
  2027. playersMenu_obm%A_Index% := SelectObject(playersMenu_hdc%A_Index%, playersMenu_hbm%A_Index%)
  2028. playersMenu_G%A_Index% := Gdip_GraphicsFromhdc(playersMenu_hdc%A_Index%)
  2029. Gdip_SetSmoothingMode(playersMenu_G%A_Index%, 4)
  2030. Gdip_TranslateWorldTransform(playersMenu_G%A_Index%, xTranslation, yTranslation)
  2031. Gdip_RotateWorldTransform(playersMenu_G%A_Index%, screenRotationAngle)
  2032. }
  2033. ;Initializing parameters
  2034. playersMenuTextFont := "Bebas Neue"
  2035. CheckFont(playersMenuTextFont)
  2036. playersMenuSelectedTextSize := 50
  2037. playersMenuSelectedTextColor := "FFFFFFFF"
  2038. playersMenuDisabledTextColor := "FFAAAAAA"
  2039. playersMenuDisabledTextSize := 30
  2040. playersMenuMargin := 50
  2041. playersMenuSpaceBtwText := 30
  2042. playersMenuCornerRadius := 10
  2043. ;menu scalling factor
  2044. XBaseRes := 1920, YBaseRes := 1080
  2045. If (((A_screenWidth < A_screenHeight) and ((screenRotationAngle=0) or (screenRotationAngle=180))) or ((A_screenWidth > A_screenHeight) and ((screenRotationAngle=90) or (screenRotationAngle=270))))
  2046. XBaseRes := 1080, YBaseRes := 1920
  2047. If !playersMenuXScale
  2048. playersMenuXScale := baseScreenWidth/XBaseRes
  2049. If !playersMenuYScale
  2050. playersMenuYScale := baseScreenHeight/YBaseRes
  2051. OptionScale(playersMenuSelectedTextSize, playersMenuYScale)
  2052. OptionScale(playersMenuDisabledTextSize, playersMenuYScale)
  2053. OptionScale(playersMenuMargin, playersMenuXScale)
  2054. OptionScale(playersMenuSpaceBtwText, playersMenuYScale)
  2055. OptionScale(playersMenuCornerRadius, playersMenuXScale)
  2056. playersMenuW := MeasureText("X Players", "Left r4 s" . playersMenuSelectedTextSize . " Bold",playersMenuTextFont) + 2*playersMenuMargin
  2057. playersMenuH := maxPlayers*playersMenuSelectedTextSize + (maxPlayers-1)*playersMenuSpaceBtwText + 2*playersMenuMargin
  2058. playersMenuX := (baseScreenWidth-playersMenuW)//2
  2059. playersMenuY := (baseScreenHeight-playersMenuH)//2
  2060. playersMenuBackgroundBrush := Gdip_BrushCreateSolid("0xDD000000")
  2061. pGraphUpd(playersMenu_G1,playersMenuW,playersMenuH)
  2062. pGraphUpd(playersMenu_G2,playersMenuW,playersMenuH)
  2063. ;Drawing Background
  2064. Gdip_Alt_FillRoundedRectangle(playersMenu_G1, playersMenuBackgroundBrush, 0, 0, playersMenuW, playersMenuH,playersMenuCornerRadius)
  2065. Alt_UpdateLayeredWindow(playersMenu_hwnd1, playersMenu_hdc1, playersMenuX, playersMenuY, playersMenuW, playersMenuH)
  2066. ;Drawing choice list
  2067. SelectedNumberofPlayers := 1
  2068. gosub, DrawPlayersSelectionMenu
  2069. ;Enabling Keys
  2070. If (keymapperEnabled = "true") and (keymapperRocketLauncherProfileEnabled = "true")
  2071. RunKeymapper%zz%("menu",keymapper)
  2072. If keymapperAHKMethod = External
  2073. RunAHKKeymapper%zz%("menu")
  2074. Gosub, EnablePlayersMenuKeys
  2075. LEDBlinky("RL") ; trigger ledblinky profile change if enabled
  2076. ;Waiting for menu to exit
  2077. Loop
  2078. { If PlayersMenuExit
  2079. Break
  2080. Sleep, 100
  2081. }
  2082. LEDBlinky("ROM") ; trigger ledblinky profile change if enabled
  2083. Return SelectedNumberofPlayers
  2084. ;labels to treat menu changes
  2085. DrawPlayersSelectionMenu:
  2086. currentY := 0
  2087. Gdip_GraphicsClear(playersMenu_G2)
  2088. Loop, % maxPlayers
  2089. {
  2090. If (a_index=SelectedNumberofPlayers) {
  2091. currentTextSize := playersMenuSelectedTextSize
  2092. currentTextColor := playersMenuSelectedTextColor
  2093. currentTextStyle := "bold"
  2094. } Else {
  2095. currentTextSize := playersMenuDisabledTextSize
  2096. currentTextColor := playersMenuDisabledTextColor
  2097. currentTextStyle := "normal"
  2098. }
  2099. If (a_index=1)
  2100. currentText := "1 Player"
  2101. Else
  2102. currentText := a_index . " Players"
  2103. currentY := playersMenuMargin + (a_index-1)*(playersMenuSelectedTextSize+playersMenuSpaceBtwText)+(playersMenuSelectedTextSize-currentTextSize)//2
  2104. Gdip_Alt_TextToGraphics(playersMenu_G2, currentText, "x0 y" . currentY . " Center c" . currentTextColor . " r4 s" . currentTextSize . " " . currentTextStyle, playersMenuTextFont, playersMenuW, playersMenuSelectedTextSize)
  2105. }
  2106. Alt_UpdateLayeredWindow(playersMenu_hwnd2, playersMenu_hdc2, playersMenuX, playersMenuY, playersMenuW, playersMenuH)
  2107. Return
  2108. EnablePlayersMenuKeys:
  2109. XHotKeywrapper(navSelectKey,"PlayersMenuSelect","ON")
  2110. XHotKeywrapper(navUpKey,"PlayersMenuUP","ON")
  2111. XHotKeywrapper(navDownKey,"PlayersMenuDown","ON")
  2112. XHotKeywrapper(navP2SelectKey,"PlayersMenuSelect","ON")
  2113. XHotKeywrapper(navP2UpKey,"PlayersMenuUP","ON")
  2114. XHotKeywrapper(navP2DownKey,"PlayersMenuDown","ON")
  2115. XHotKeywrapper(exitEmulatorKey,"CloseProcess","OFF")
  2116. XHotKeywrapper(exitEmulatorKey,"ClosePlayersMenu","ON")
  2117. Return
  2118. DisablePlayersMenuKeys:
  2119. XHotKeywrapper(navSelectKey,"PlayersMenuSelect","OFF")
  2120. XHotKeywrapper(navUpKey,"PlayersMenuUP","OFF")
  2121. XHotKeywrapper(navDownKey,"PlayersMenuDown","OFF")
  2122. XHotKeywrapper(navP2SelectKey,"PlayersMenuSelect","OFF")
  2123. XHotKeywrapper(navP2UpKey,"PlayersMenuUP","OFF")
  2124. XHotKeywrapper(navP2DownKey,"PlayersMenuDown","OFF")
  2125. XHotKeywrapper(exitEmulatorKey,"ClosePlayersMenu","OFF")
  2126. XHotKeywrapper(exitEmulatorKey,"CloseProcess","ON")
  2127. Return
  2128. PlayersMenuUP:
  2129. SelectedNumberofPlayers--
  2130. If (SelectedNumberofPlayers<1)
  2131. SelectedNumberofPlayers:=maxPlayers
  2132. gosub, DrawPlayersSelectionMenu
  2133. Return
  2134. PlayersMenuDown:
  2135. SelectedNumberofPlayers++
  2136. If (SelectedNumberofPlayers>maxPlayers)
  2137. SelectedNumberofPlayers:=1
  2138. gosub, DrawPlayersSelectionMenu
  2139. Return
  2140. ClosePlayersMenu:
  2141. ClosedPlayerMenu := true
  2142. PlayersMenuSelect:
  2143. Gosub, DisablePlayersMenuKeys
  2144. Gdip_DeleteBrush(playersMenuBackgroundBrush)
  2145. Loop, 2 {
  2146. SelectObject(playersMenu_hdc%A_Index%, playersMenu_obm%A_Index%)
  2147. DeleteObject(playersMenu_hbm%A_Index%)
  2148. DeleteDC(playersMenu_hdc%A_Index%)
  2149. Gdip_DeleteGraphics(playersMenu_G%A_Index%)
  2150. Gui, playersMenu_GUI%A_Index%: Destroy
  2151. }
  2152. If ClosedPlayerMenu
  2153. { Log("User cancelled the launch at the Player Select Menu")
  2154. PlayersMenuExit := true
  2155. ExitModule()
  2156. } Else
  2157. Log("Number of Players Selected: " . SelectedNumberofPlayers)
  2158. If (keymapperEnabled = "true") and (keymapperRocketLauncherProfileEnabled = "true")
  2159. RunKeymapper%zz%("load", keymapper)
  2160. If keymapperAHKMethod = External
  2161. RunAHKKeymapper%zz%("load")
  2162. PlayersMenuExit := true
  2163. Return
  2164. }
  2165.  
  2166.  
  2167. ;-------------------------------------------------------------------------------------------------------------
  2168. ;----------------------------------------- HideEmu Functions ---------------------------------------
  2169. ;-------------------------------------------------------------------------------------------------------------
  2170.  
  2171. ; Default is 2ms so it picks up windows as soon as possible
  2172. HideEmuStart(ms=2) {
  2173. Global hideEmu
  2174. Global hideEmuObj
  2175. If (hideEmu = "true")
  2176. { Log("HideEmuStart - Starting HideEmuTimer, scanning for windows defined in hideEmuObj every " . ms . "ms")
  2177. ; First rebuild the single line object into a better one that's easier to track and work with
  2178. newObject := Object()
  2179. For key, value in hideEmuObj
  2180. { currentObj++
  2181. newObject[currentObj,"window"] := key
  2182. newObject[currentObj,"method"] := value
  2183. newObject[currentObj,"status"] := ; default is 0 (0 = not hidden yet, 1 = hidden already)
  2184. }
  2185. hideEmuObj := newObject ; overwrite hideEmuObj with the updated one
  2186. SetTimer, HideEmuTimer, %ms%
  2187. Log("HideEmuStart - Ended")
  2188. }
  2189. }
  2190.  
  2191. HideEmuEnd() {
  2192. Global hideEmu
  2193. Global hideEmuObj
  2194. If (hideEmu = "true")
  2195. { Log("HideEmuEnd - Stopping HideEmuTimer and unhiding flagged windows",4)
  2196. SetTimer, HideEmuTimer, Off
  2197. For key, value in hideEmuObj
  2198. If (hideEmuObj[A_Index,"method"] && hideEmuObj[A_Index,"status"]) { ; if one of the windows was hidden and needs to be unhidden
  2199. WinSet, Transparent, Off, % hideEmuObj[A_Index,"window"]
  2200. Log("HideEmu - Revealed window: " . hideEmuObj[A_Index,"window"],4)
  2201. }
  2202. Log("HideEmuEnd - Ended",4)
  2203. }
  2204. }
  2205.  
  2206. HideEmuTimer:
  2207. For key, value in hideEmuObj
  2208. { If !hideEmuObj[A_Index,"status"]
  2209. { If (A_DetectHiddenWindows != "On")
  2210. DetectHiddenWindows, On
  2211. If WinExist(hideEmuObj[A_Index,"window"])
  2212. { WinSet, Transparent, 0, % hideEmuObj[A_Index,"window"]
  2213. Log("HideEmu - Found a new window to hide: " . hideEmuObj[A_Index,"window"],4)
  2214. WinGet, currentTran, Transparent, % hideEmuObj[A_Index,"window"]
  2215. If (currentTran = 0)
  2216. hideEmuObj[A_Index,"status"] := 1 ; update object that this window is now hidden
  2217. }
  2218. }
  2219. }
  2220. Return
  2221.  
  2222.  
  2223. ;-------------------------------------------------------------------------------------------------------------
  2224. ;---------------------------------------- Decryption Functions -------------------------------------
  2225. ;-------------------------------------------------------------------------------------------------------------
  2226.  
  2227. Decrypt(T,key) ; Text, key-name
  2228. {
  2229. Local p, i, L, u, v, k5, a, c
  2230.  
  2231. StringLeft p, T, 8
  2232. If p is not xdigit ; if no IV: Error
  2233. {
  2234. ErrorLevel := 1
  2235. Return
  2236. }
  2237. StringTrimLeft T, T, 8 ; remove IV from text (no separator)
  2238. k5 = 0x%p% ; set new IV
  2239. p := 0 ; counter to be Encrypted
  2240. i := 9 ; pad-index, force restart
  2241. L := "" ; processed text
  2242. k0 := %key%0
  2243. k1 := %key%1
  2244. k2 := %key%2
  2245. k3 := %key%3
  2246. Loop % StrLen(T)
  2247. {
  2248. i++
  2249. IfGreater i,8, { ; all 9 pad values exhausted
  2250. u := p
  2251. v := k5 ; IV
  2252. p++ ; increment counter
  2253. TEA(u,v, k0,k1,k2,k3)
  2254. Stream9(u,v) ; 9 pads from Encrypted counter
  2255. i := 0
  2256. }
  2257. StringMid c, T, A_Index, 1
  2258. a := Asc(c)
  2259. if a between 32 and 126
  2260. { ; chars > 126 or < 31 unchanged
  2261. a -= s%i%
  2262. IfLess a, 32, SetEnv, a, % a+95
  2263. c := Chr(a)
  2264. }
  2265. L := L . c ; attach Encrypted character
  2266. }
  2267. Return L
  2268. }
  2269.  
  2270. TEA(ByRef y,ByRef z,k0,k1,k2,k3) ; (y,z) = 64-bit I/0 block
  2271. { ; (k0,k1,k2,k3) = 128-bit key
  2272. IntFormat := A_FormatInteger
  2273. SetFormat Integer, D ; needed for decimal indices
  2274. s := 0
  2275. d := 0x9E3779B9
  2276. Loop 32
  2277. {
  2278. k := "k" . s & 3 ; indexing the key
  2279. y := 0xFFFFFFFF & (y + ((z << 4 ^ z >> 5) + z ^ s + %k%))
  2280. s := 0xFFFFFFFF & (s + d) ; simulate 32 bit operations
  2281. k := "k" . s >> 11 & 3
  2282. z := 0xFFFFFFFF & (z + ((y << 4 ^ y >> 5) + y ^ s + %k%))
  2283. }
  2284. SetFormat Integer, %IntFormat%
  2285. y += 0
  2286. z += 0 ; Convert to original ineger format
  2287. }
  2288.  
  2289. Stream9(x,y) ; Convert 2 32-bit words to 9 pad values
  2290. { ; 0 <= s0, s1, ... s8 <= 94
  2291. Local z ; makes all s%i% global
  2292. s0 := Floor(x*0.000000022118911147) ; 95/2**32
  2293. Loop 8
  2294. {
  2295. z := (y << 25) + (x >> 7) & 0xFFFFFFFF
  2296. y := (x << 25) + (y >> 7) & 0xFFFFFFFF
  2297. x := z
  2298. s%A_Index% := Floor(x*0.000000022118911147)
  2299. }
  2300. }
  2301.  
  2302.  
  2303. ;-------------------------------------------------------------------------------------------------------------
  2304. ;------------------------------------ Registry Access Functions ----------------------------------
  2305. ;-------------------------------------------------------------------------------------------------------------
  2306.  
  2307. RegRead(RootKey, SubKey, ValueName = "", RegistryVersion="32")
  2308. { Global winVer
  2309. Log("RegRead - Reading from Registry : RootKey=" . RootKey . ", SubKey=" . SubKey . ", ValueName=" . ValueName . ",RegistryVersion=" . RegistryVersion, 4)
  2310. If (RegistryVersion = "Auto") ;Try finding the correct registry reading based on the windows version
  2311. {
  2312. If (winVer = "64")
  2313. If !OutputVar := RegRead(RootKey, SubKey, ValueName, "64")
  2314. OutputVar := RegRead(RootKey, SubKey, ValueName, "32")
  2315. Else
  2316. OutputVar := RegRead(RootKey, SubKey, ValueName)
  2317. }
  2318. Else If (RegistryVersion = "32")
  2319. RegRead, OutputVar, %RootKey%, %SubKey%, %ValueName%
  2320. Else
  2321. OutputVar := RegRead64(RootKey, SubKey, ValueName)
  2322. Log("RegRead - Registry Read finished, returning " . OutputVar, 4)
  2323. Return OutputVar
  2324. }
  2325.  
  2326. RegWrite(ValueType, RootKey, SubKey, ValueName = "", Value = "", RegistryVersion="32")
  2327. {
  2328. Log("RegWrite - Writing to Registry : RootKey=" . RootKey . ", SubKey=" . SubKey . ", ValueName=" . ValueName . ",Value=" . Value . ",ValueType=" . ValueType . ",RegistryVersion=" . RegistryVersion, 4)
  2329. If (RegistryVersion = "32")
  2330. RegWrite, %ValueType%, %RootKey%, %SubKey%, %ValueName%, %Value%
  2331. Else
  2332. RegWrite64(ValueType, RootKey, SubKey, ValueName, Value)
  2333. Log("RegWrite - Registry Write finished", 4)
  2334. }
  2335.  
  2336. ;-------------------------------------------------------------------------------------------------------------
  2337. ;----------------------------------------- Display Resolution Functions ----------------------------------------
  2338. ;-------------------------------------------------------------------------------------------------------------
  2339.  
  2340. ; Grab current display settings for each monitor
  2341. ; Returns object:
  2342. ; obj[#] = Display Number
  2343. ; obj[#].Name = Display's Name as known in windows. Ex: \\.\DISPLAY1
  2344. ; obj[#].Width = Display's Width
  2345. ; obj[#].Height = Display's Height
  2346. ; obj[#].BitDepth = Display's BitDepth
  2347. ; obj[#].Frequency = Display's Frequency
  2348. ; obj[#].Orientation = Display's Orientation
  2349. ; obj[#].Left = Where this display's Left position starts
  2350. ; obj[#].Right = Where this display's Right position ends
  2351. ; obj[#].Top = Where this display's Top position starts
  2352. ; obj[#].Bottom = Where this display's Bottom position ends
  2353. ; obj[#].WorkingWidth = Display's Working Width. This is the usable space w/o the task bar
  2354. ; obj[#].WorkingHeight = Display's Working Height
  2355. GetDisplaySettings() {
  2356. Global RLObject
  2357. obj := Object()
  2358. monOrientation := Object(0,"Landscape",1,"Portrait",2,"Landscape (Flipped)",3,"Portrait (Flipped)")
  2359. getDisplaySettingsObj := Object(1,"Width",2,"Height",3,"BitDepth",4,"Frequency",5,"Orientation")
  2360. SysGet, MonitorCount, 80 ; MonitorCount
  2361. SysGet, MonitorPrimary, MonitorPrimary
  2362. Loop, %MonitorCount% ; get each monitor's stats for the log
  2363. {
  2364. SysGet, MonitorName, MonitorName, %A_Index%
  2365. SysGet, Monitor, Monitor, %A_Index%
  2366. SysGet, MonitorWorkArea, MonitorWorkArea, %A_Index%
  2367. currentobj:={}
  2368. currentobj.Number := A_Index ; this is the monitor #, an integer
  2369. currentobj.Name := MonitorName ; store monitor's name as it is known as in Windows
  2370. monDetails := RL_getDisplaySettings(MonitorName) ; return 0 if something went wrong, like an invalid displayName is passed. Otherwise it returns a string with this format "width|height|bits|frequency|orientation"
  2371. Loop, Parse, monDetails, |
  2372. currentObj[getDisplaySettingsObj[A_Index]] := A_LoopField ; parse RLObject's return and store into the object
  2373. currentobj.Orientation := monOrientation[currentobj.Orientation] ; replace orientation integer with name from object instead
  2374. currentobj.Left := MonitorLeft ; store where this monitor's Left position starts
  2375. currentobj.Right := MonitorRight ; store where this monitor's Right position ends
  2376. currentobj.Top := MonitorTop ; store where this monitor's Top position starts
  2377. currentobj.Bottom := MonitorBottom ; store where this monitor's Bottom position ends
  2378. currentobj.WorkingWidth := MonitorWorkAreaRight - MonitorWorkAreaLeft ; store this monitor's working width
  2379. currentobj.WorkingHeight := MonitorWorkAreaBottom - MonitorWorkAreaTop ; store this monitor's working height
  2380. obj.Insert(currentobj["Number"], currentobj)
  2381. Log("GetDisplaySettings - Monitor #" . A_Index . " (" . MonitorName . "): " . MonitorRight - MonitorLeft . "x" . MonitorBottom - MonitorTop . " (" . MonitorWorkAreaRight - MonitorWorkAreaLeft . "x" . MonitorWorkAreaBottom - MonitorWorkAreaTop . " work) [" . currentobj.BitDepth . "bit] [" . currentobj.Frequency . "hz] [" . currentobj.Orientation . "] " . (If MonitorPrimary = A_Index ? " (Primary)" : ""),4)
  2382. }
  2383. Return obj
  2384. }
  2385.  
  2386. ; This function will take the | delimited user settings from theses places:
  2387. ; A) RLUI for all monitor/resolution settings and break it apart so it can be used in the various display functions then sent to the DLL
  2388. ; B) Module when called to change the display setting(s)
  2389. ; It supports multiple monitors and parameters for each
  2390. ; array = | delimted string in this order where each monitor is delimted by ; monNumber|monWidth|monHeight|monBitDepth|monFrequency
  2391. ; Example = 1|1600|1200|32|60&2|1024|768|32|60
  2392. ConvertToMonitorObject(array) {
  2393. Global monitorTable
  2394. displaySettingsObj := Object(1,"Name",2,"Width",3,"Height",4,"BitDepth",5,"Frequency")
  2395. obj := Object()
  2396. Loop, Parse, array, &
  2397. {
  2398. currentobj:={}
  2399. currentobj.Number := A_Index ; this is the monitor #, an integer
  2400. Loop, Parse, A_LoopField, |
  2401. {
  2402. If !A_LoopField {
  2403. Log("ConvertToMonitorObject - " . displaySettingsObj[A_Index] . " not supplied in array. Object creation terminated.",3)
  2404. Return
  2405. }
  2406. currentobj[displaySettingsObj[A_Index]] := If displaySettingsObj[A_Index] = "Name" && !InStr(A_LoopField,"DISPLAY") ? "\\.\DISPLAY" . A_LoopField : A_LoopField
  2407. }
  2408. obj.Insert(currentobj["Number"], currentobj)
  2409. }
  2410. Return obj
  2411. }
  2412.  
  2413. ; Handle the supplied object by first checking if parameters are supported by the monitor, then setting them.
  2414. ; This is the function that will be called in features and modules to change display settings.
  2415. SetDisplaySettings(monObj) {
  2416. Global monitorTable
  2417. Log("SetDisplaySettings - Started")
  2418. currentMon := GetDisplaySettings() ; get current parameters to see if res needs to be changed or it can be skipped
  2419. Loop % monObj.MaxIndex()
  2420. {
  2421. ; msgbox % "SetDisplaySettings`n`nobj[" . A_Index . "].Name: " . monObj[A_Index].Name . "`nobj.Width: " . monObj[A_Index].Width . "`nobj.Height: " . monObj[A_Index].Height . "`nobj.BitDepth: " . monObj[A_Index].BitDepth . "`nobj.Frequency: " . monObj[A_Index].Frequency
  2422. x := CheckDisplaySettings(monObj[A_Index].Name,monObj[A_Index].Width,monObj[A_Index].Height,monObj[A_Index].BitDepth,monObj[A_Index].Frequency)
  2423. If x {
  2424. If ((monObj[A_Index].Width = currentMon[A_Index].Width) && (monObj[A_Index].Height = currentMon[A_Index].Height) && (monObj[A_Index].BitDepth = currentMon[A_Index].BitDepth) && (monObj[A_Index].Frequency = currentMon[A_Index].Frequency)) {
  2425. Log("SetDisplaySettings - Not changing " . monObj[A_Index].Name . " as it is already set to " . monObj[A_Index].Width . "x" . monObj[A_Index].Height . " " . monObj[A_Index].BitDepth . "bit " . monObj[A_Index].Frequency . "hz")
  2426. } Else {
  2427. Log("SetDisplaySettings - Changing " . monObj[A_Index].Name . " to " . monObj[A_Index].Width . "x" . monObj[A_Index].Height . " " . monObj[A_Index].BitDepth . "bit " . monObj[A_Index].Frequency . "hz")
  2428. ChangeDisplaySettings(monObj[A_Index].Name,monObj[A_Index].Width,monObj[A_Index].Height,monObj[A_Index].BitDepth,monObj[A_Index].Frequency)
  2429. ; Update monitorTable with new settings so it stays current
  2430. SysGet, Monitor, Monitor, %A_Index%
  2431. SysGet, MonitorWorkArea, MonitorWorkArea, %A_Index%
  2432. monitorTable[A_Index].Width := monObj[A_Index].Width
  2433. monitorTable[A_Index].Height := monObj[A_Index].Height
  2434. monitorTable[A_Index].BitDepth := monObj[A_Index].BitDepth
  2435. monitorTable[A_Index].Frequency := monObj[A_Index].Frequency
  2436. monitorTable[A_Index].Left := MonitorLeft
  2437. monitorTable[A_Index].Right := MonitorRight
  2438. monitorTable[A_Index].Top := MonitorTop
  2439. monitorTable[A_Index].Bottom := MonitorBottom
  2440. monitorTable[A_Index].WorkingWidth := MonitorWorkAreaRight - MonitorWorkAreaLeft
  2441. monitorTable[A_Index].WorkingHeight := MonitorWorkAreaBottom - MonitorWorkAreaTop
  2442. }
  2443. } Else
  2444. Log("SetDisplaySettings - " . monObj[A_Index].Name . " does not support " . monObj[A_Index].Width . "x" . monObj[A_Index].Height . " " . monObj[A_Index].BitDepth . "bit " . monObj[A_Index].Frequency . "hz",2)
  2445. }
  2446. Log("SetDisplaySettings - Ended")
  2447. }
  2448.  
  2449. ; Change screen resolution to supplied parameters
  2450. ; Do not call this function directly, allow SetDisplaySettings to handle it
  2451. ; n = Display Name
  2452. ; w = Screen Width
  2453. ; h = Screen Height
  2454. ; b = Bit Depth
  2455. ; f = Frequency
  2456. ChangeDisplaySettings(n,w,h,b,f) {
  2457. Global RLObject
  2458. Return RL_changeDisplaySettings(n,w,h,b,f)
  2459. }
  2460.  
  2461. ; Check monitor if it can support the screen parameters supplied
  2462. ; Do not call this function directly, allow SetDisplaySettings to handle it
  2463. ; Use this before calling ChangeDisplaySettings
  2464. ; n = Display Name
  2465. ; w = Screen Width
  2466. ; h = Screen Height
  2467. ; b = Bit Depth
  2468. ; f = Frequency
  2469. CheckDisplaySettings(n,w,h,b,f) {
  2470. Global RLObject
  2471. Return RL_checkDisplaySettings(n,w,h,b,f)
  2472. }
  2473.  
  2474. ; http://www.autohotkey.com/forum/topic8355.html
  2475. ; ChangeDisplaySettings( sW, sH, cD, rR ) { ; Change Screen Resolution
  2476. ; VarSetCapacity(dM,156,0), NumPut(156,dM,36)
  2477. ; DllCall( "EnumDisplaySettingsA", UInt,0, UInt,-1, UInt,&dM ), NumPut(0x5c0000,dM,40)
  2478. ; NumPut(cD,dM,104), NumPut(sW,dM,108), NumPut(sH,dM,112), NumPut(rR,dM,120)
  2479. ; Return DllCall( "ChangeDisplaySettingsA", UInt,&dM, UInt,0 )
  2480. ; }
  2481.  
  2482. ; Acquire display "index" screen resolution (index=0,1,...)
  2483. ; GetDisplaySettings(Index) {
  2484. ; VarSetCapacity(device_mode,156,0)
  2485. ; success:=DllCall("EnumDisplaySettings","uint",0,"uint",Index-1,"uint",&device_mode)
  2486. ; If (ErrorLevel or !success)
  2487. ; Return "Break"
  2488. ; Out_1:=NumGet(&device_mode,108,"uint4") ;width
  2489. ; Out_2:=NumGet(&device_mode,112,"uint4") ;height
  2490. ; Out_3:=NumGet(&device_mode,104,"uint4") ;quality
  2491. ; Out_4:=NumGet(&device_mode,120,"uint4") ;frequency
  2492. ; Return Out_1 "|" Out_2 "|" Out_3 "|" Out_4
  2493. ; } ; out "Break"
  2494.  
  2495. ; Acquire current display screen resolution (1=width 2=height 3=quality 4=frequency)
  2496. ; CurrentDisplaySettings(in=0) {
  2497. ; VarSetCapacity(device_mode,156,0),NumPut(156,2,&device_mode,36)
  2498. ; success := DllCall("EnumDisplaySettings","uint",0,"uint",-1,"uint",&device_mode)
  2499. ; Out_1:=NumGet(&device_mode,108,"uint4") ;width
  2500. ; Out_2:=NumGet(&device_mode,112,"uint4") ;height
  2501. ; Out_3:=NumGet(&device_mode,104,"uint4") ;quality
  2502. ; Out_4:=NumGet(&device_mode,120,"uint4") ;frequency
  2503. ; If in = 0
  2504. ; Return Out_1 "|" Out_2 "|" Out_3 "|" Out_4
  2505. ; Else Return (Out_%in%)
  2506. ; }
  2507.  
  2508. ; Check if a given screen resolution is supported by the monitor, and if not, choose the nearest one that is
  2509. ; desiredResTable uses the object defined by ConvertToMonitorObject
  2510. CheckForNearestSupportedRes(monNumber,desiredResTable){
  2511. Log("CheckForNearestSupportedRes - Started")
  2512. If !desiredResTable {
  2513. Log("CheckForNearestSupportedRes - Supplied desired resolution does not contain any data.",3)
  2514. Return
  2515. }
  2516. listOfSupportedRes := EnumDisplaySettings(monNumber)
  2517. If !listOfSupportedRes
  2518. { Log("CheckForNearestSupportedRes - Ended, was supplied a monitor number that is not attached to this system: " . monNumber,3)
  2519. Return
  2520. }
  2521. If RegExMatch(listOfSupportedRes, "i)" desiredResTable[monNumber].Width . "\|" . desiredResTable[monNumber].Height . "\|" . desiredResTable[monNumber].BitDepth . "\|" . desiredResTable[monNumber].Frequency)
  2522. { Log("CheckForNearestSupportedRes - Ended, this resolution is already supported by this display: " . desiredResTable[monNumber].Width . "|" . desiredResTable[monNumber].Height . "|" . desiredResTable[monNumber].BitDepth . "|" . desiredResTable[monNumber].Frequency,4)
  2523. Return desiredResTable
  2524. }
  2525. Log("CheckForNearestSupportedRes - This resolution is not directly supported by your monitor, finding the closest match.",4)
  2526. SupportedResObj := {}
  2527. nearestSupportedRes := {}
  2528. Loop, Parse, listOfSupportedRes, `,
  2529. {
  2530. currentRes := A_Index
  2531. SupportedResObj[currentRes] := {}
  2532. StringSplit,curRes,A_LoopField,|
  2533. SupportedResObj[currentRes].Width := curRes1
  2534. SupportedResObj[currentRes].Height := curRes2
  2535. SupportedResObj[currentRes].BitDepth := curRes3
  2536. SupportedResObj[currentRes].Frequency := curRes4
  2537. SupportedResObj[currentRes]["Distance"] := {}
  2538. SupportedResObj[currentRes]["Distance"].Width := SupportedResObj[currentRes].Width - desiredResTable[monNumber].Width
  2539. SupportedResObj[currentRes]["Distance"].Height := SupportedResObj[currentRes].Height - desiredResTable[monNumber].Height
  2540. SupportedResObj[currentRes]["Distance"].BitDepth := SupportedResObj[currentRes].BitDepth - desiredResTable[monNumber].BitDepth
  2541. SupportedResObj[currentRes]["Distance"].Frequency := SupportedResObj[currentRes].Frequency - desiredResTable[monNumber].Frequency
  2542. }
  2543. previousDeviation := 10**9
  2544. Loop, %currentRes%
  2545. {
  2546. currentDeviation := 100*SupportedResObj[A_Index]["Distance"].Width*SupportedResObj[A_Index]["Distance"].Width + 100*SupportedResObj[A_Index]["Distance"].Height*SupportedResObj[A_Index]["Distance"].Height + 10*SupportedResObj[A_Index]["Distance"].BitDepth*SupportedResObj[A_Index]["Distance"].BitDepth + SupportedResObj[A_Index]["Distance"].Frequency*SupportedResObj[A_Index]["Distance"].Frequency
  2547. If (currentDeviation < previousDeviation) {
  2548. previousDeviation := currentDeviation
  2549. nearestSupportedRes.Width := SupportedResObj[A_Index].Width
  2550. nearestSupportedRes.Height := SupportedResObj[A_Index].Height
  2551. nearestSupportedRes.BitDepth := SupportedResObj[A_Index].BitDepth
  2552. nearestSupportedRes.Frequency := SupportedResObj[A_Index].Frequency
  2553. }
  2554. }
  2555. supportedRes := ConvertToMonitorObject(monNumber . "|" . nearestSupportedRes.Width . "|" . nearestSupportedRes.Height . "|" . nearestSupportedRes.BitDepth . "|" nearestSupportedRes.Frequency) ; convert to object
  2556. Log("CheckForNearestSupportedRes - Ended, closest match found is: " . supportedRes[monNumber].Width . "|" . supportedRes[monNumber].Height . "|" . supportedRes[monNumber].BitDepth . "|" supportedRes[monNumber].Frequency,4)
  2557. Return supportedRes
  2558. }
  2559.  
  2560. ; Enumerate Supported Screen Resolutions
  2561. ; display = the number of the monitor to enumerate supported resolutions for. 1 = Display 1, 2 = display 2, etc
  2562. ; Returns | delimited list of all supported settings
  2563. EnumDisplaySettings(display) {
  2564. VarSetCapacity(DM,156,0), NumPut(156,&DM,36, "UShort")
  2565. DllCall( "EnumDisplaySettings", str,"\\.\DISPLAY" Display, UInt,-1, UInt,&DM )
  2566. CS:=NumGet(DM,108) "|" NumGet(DM,112) "|" NumGet(DM,104) "|" NumGet(DM,120)
  2567. Loop
  2568. If DllCall( "EnumDisplaySettings", str,"\\.\DISPLAY" Display, UInt,A_Index-1, UInt,&DM )
  2569. { EDS:=NumGet(DM,108) "|" NumGet(DM,112) "|" NumGet(DM,104) "|" NumGet(DM,120)
  2570. DS.=(!InStr(DS,EDS) ? "," EDS : "")
  2571. } Else
  2572. Break
  2573. StringReplace, DS, DS, %CS%|, %CS%||, All
  2574. Return SubStr(DS,2)
  2575. }
  2576.  
  2577. OptionScale(ByRef option, scale){ ;selects portrait specifc option value if needed and scales variable to adjust to screen resolution
  2578. Global screenRotationAngle
  2579. If InStr(option,"|")
  2580. {
  2581. StringSplit, opt, option, |
  2582. If ((opt2) and (((A_screenWidth < A_screenHeight) and ((screenRotationAngle=0) or (screenRotationAngle=180))) or ((A_screenWidth > A_screenHeight) and ((screenRotationAngle=90) or (screenRotationAngle=270)))))
  2583. option := If (SubStr(opt2, 0)="p") ? opt2 : round(opt2 * scale)
  2584. Else
  2585. option := If (SubStr(opt1, 0)="p") ? opt1 : round(opt1 * scale)
  2586. } Else
  2587. option := If (SubStr(option, 0)="p") ? option : round(option * scale)
  2588. }
  2589.  
  2590.  
  2591.  
  2592. TextOptionScale(ByRef Option,XScale, YScale){
  2593. RegExMatch(Option, "i)X([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|X([\-\d\.]+)(p*)", xpos)
  2594. RegExMatch(Option, "i)Y([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|Y([\-\d\.]+)(p*)", ypos)
  2595. RegExMatch(Option, "i)W([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|W([\-\d\.]+)(p*)", Width)
  2596. RegExMatch(Option, "i)H([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|H([\-\d\.]+)(p*)", Height)
  2597. RegExMatch(Option, "i)S([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|S([\-\d\.]+)", Size)
  2598. xposValue := SubStr(xpos, 2), yposValue := SubStr(ypos, 2), WidthValue := SubStr(Width, 2), HeightValue := SubStr(Height, 2), SizeValue := SubStr(Size, 2)
  2599. OptionScale(xposValue, XScale)
  2600. OptionScale(yposValue, YScale)
  2601. OptionScale(WidthValue, XScale)
  2602. OptionScale(HeightValue, YScale)
  2603. OptionScale(SizeValue, YScale)
  2604. Option := RegExReplace(Option, "i)X([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|X([\-\d\.]+)(p*)", "x" . xposValue)
  2605. Option := RegExReplace(Option, "i)Y([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|Y([\-\d\.]+)(p*)", "y" . yposValue)
  2606. Option := RegExReplace(Option, "i)W([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|W([\-\d\.]+)(p*)", "w" . WidthValue)
  2607. Option := RegExReplace(Option, "i)H([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|H([\-\d\.]+)(p*)", "h" . HeightValue)
  2608. Option := RegExReplace(Option, "i)S([\-\d\.]+)(p*)\|([\-\d\.]+)(p*)|S([\-\d\.]+)", "s" . SizeValue)
  2609. }
  2610.  
  2611. ;-------------------------------------------------------------------------------------------------------------
  2612. ;---------------------------- Open And Close Process Functions ----------------------------
  2613. ;-------------------------------------------------------------------------------------------------------------
  2614.  
  2615. ProcSus(PID_or_Name) {
  2616. Log("ProcSus - Started",4)
  2617. If InStr(PID_or_Name, ".") {
  2618. Process, Exist, %PID_or_Name%
  2619. PID_or_Name := ErrorLevel
  2620. }
  2621. If !(h := DllCall("OpenProcess", "uInt", 0x1F0FFF, "Int", 0, "Int", PID_or_Name)) {
  2622. Log("ProcSus - Ended, process """ . PID_or_Name . """ not found")
  2623. Return -1
  2624. }
  2625. Log("ProcSus - Suspending Process: " . PID_or_Name)
  2626. DllCall("ntdll.dll\NtSuspendProcess", "Int", h), DllCall("CloseHandle", "Int", h)
  2627. Log("ProcSus - Ended",4)
  2628. }
  2629.  
  2630. ProcRes(PID_or_Name) {
  2631. Log("ProcRes - Started",4)
  2632. If InStr(PID_or_Name, ".") {
  2633. Process, Exist, %PID_or_Name%
  2634. PID_or_Name := ErrorLevel
  2635. }
  2636. If !(h := DllCall("OpenProcess", "uInt", 0x1F0FFF, "Int", 0, "Int", PID_or_Name)) {
  2637. Log("ProcRes - Ended, process """ . PID_or_Name . """ not found")
  2638. Return -1
  2639. }
  2640. Log("ProcRes - Resuming Process: " . PID_or_Name)
  2641. DllCall("ntdll.dll\NtResumeProcess", "Int", h), DllCall("CloseHandle", "Int", h)
  2642. Log("ProcRes - Ended",4)
  2643. }
  2644.  
  2645. ;-------------------------------------------------------------------------------------------------------------
  2646. ;--------------------------------------- Validate IP Functions ---------------------------------------
  2647. ;-------------------------------------------------------------------------------------------------------------
  2648.  
  2649. ValidIP(a) {
  2650. Loop, Parse, a, .
  2651. {
  2652. If A_LoopField is digit
  2653. If A_LoopField between 0 and 255
  2654. e++
  2655. c++
  2656. }
  2657. Return, e = 4 AND c = 4
  2658. }
  2659.  
  2660. ValidPort(a) {
  2661. If a is digit
  2662. If a between 0 and 65535
  2663. e++
  2664. Return e
  2665. }
  2666.  
  2667. GetPublicIP() {
  2668. UrlDownloadToFile, http://www.rlauncher.com/ipcheck/myip.php, %A_Temp%\myip.txt
  2669. FileRead, extIP, %A_Temp%\myip.txt
  2670. Return extIP
  2671. }
  2672.  
  2673. GetLocalIP() {
  2674. array := []
  2675. objWMIService := ComObjGet("winmgmts:{impersonationLevel = impersonate}!\\.\root\cimv2")
  2676. colItems := objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")._NewEnum
  2677. while colItems[objItem]
  2678. {
  2679. array[A_Index,1] := objItem.Description[0]
  2680. array[A_Index,2] := objItem.IPAddress[0]
  2681. array[A_Index,3] := objItem.IPSubnet[0]
  2682. array[A_Index,4] := objItem.DefaultIPGateway[0]
  2683. array[A_Index,5] := objItem.DNSServerSearchOrder[0]
  2684. array[A_Index,6] := objItem.MACAddress[0]
  2685. array[A_Index,7] := objItem.DHCPEnabled[0]
  2686. }
  2687. Return array
  2688. }
  2689.  
  2690.  
  2691. ;-------------------------------------------------------------------------------------------------------------
  2692. ;------------------------------------------- Rotate Screen Functions -------------------------------------------
  2693. ;-------------------------------------------------------------------------------------------------------------
  2694.  
  2695. ; Options:
  2696. ; method = irotate, display, or shortcut
  2697. ; degrees = 0, 90, 180, 270
  2698.  
  2699. Rotate(method="irotate", degrees=0) {
  2700. Log("Rotate - Started")
  2701. Global moduleExtensionsPath
  2702. arrowKeys := { 0: "Up", 1: "Right", 2: "Down", 3: "Left" }
  2703. If !RegExMatch(method,"i)irotate|display|shortcut")
  2704. ScriptError("""" . method . """ is not a valid rotate method, Please choose either ""irotate"" or ""display""")
  2705. If !RegExMatch(degrees,"0|90|180|270")
  2706. ScriptError("""" . degrees . """ is not a valid degree to rotate to, Please choose either 0, 90, 180, or 270")
  2707. rotateExe := CheckFile(moduleExtensionsPath . "\" . method . ".exe") ; check If the exe to our RotateMethod method exists
  2708. If (method = "irotate") {
  2709. Log("Rotate - Rotating display using irotate.exe to " . degrees . " degrees",4)
  2710. Run(rotateExe . " /rotate=" degrees " /exit", moduleExtensionsPath)
  2711. } Else If (method = "display") {
  2712. Log("Rotate - Rotating display using display.exe to " . degrees . " degrees",4)
  2713. Run(rotateExe . " /rotate:" degrees, moduleExtensionsPath)
  2714. } Else If (method = "shortcut") {
  2715. Log("Rotate - Rotating display using shortcut keys to " . degrees . " degrees",4)
  2716. Send, % "{LControl Down}{LAlt Down}{" . arrowKeys[degrees // 90] . " Down}{LControl Up}{LAlt Up}{" . arrowKeys[degrees // 90] . " Up}"
  2717. }
  2718. Log("Rotate - Ended")
  2719. }
  2720.  
  2721.  
  2722. ;-------------------------------------------------------------------------------------------------------------
  2723. ;-------------------------------------------- Database Asset Building ------------------------------------------
  2724. ;-------------------------------------------------------------------------------------------------------------
  2725.  
  2726. ; Builds an object filled with the FE's assets
  2727. BuildAssetsTable(list,label,AssetType,extensions="",obj=""){
  2728. Log("BuildAssetsTable - Started - Building Table for: " . label,4)
  2729. Global logLevel
  2730. StringReplace, extensionsReplaced, extensions, |, `,,All
  2731. If !(obj)
  2732. obj := {}
  2733. StringSplit, labelArray, label, |,
  2734. StringSplit, AssetTypeArray, AssetType, |,
  2735. Loop, Parse, list,|
  2736. { If !(labelArray%A_Index% = "#disabled#")
  2737. {
  2738. Log("BuildAssetsTable - Searching for a " . labelArray%A_Index% . ": " . A_LoopField,4)
  2739. currentLabel := labelArray%A_Index%
  2740. currentAssetType := AssetTypeArray%A_index%
  2741. RASHNDOCT := FileExist(A_LoopField)
  2742. If InStr(RASHNDOCT, "D") { ; it is a folder
  2743. folderName := A_LoopFileName
  2744. Loop, % A_LoopField . "\*.*"
  2745. { If RegExMatch(extensions,"i)" . A_LoopFileExt)
  2746. { currentobj := {}
  2747. If (currentLabel="keepFileName")
  2748. currentobj["Label"] := folderName
  2749. Else
  2750. currentobj["Label"] := currentLabel
  2751. If obj[currentLabel].Label
  2752. { currentobj := obj[currentLabel]
  2753. currentobj.TotalItems := currentobj.TotalItems+1
  2754. } Else {
  2755. currentobj.TotalItems := 1
  2756. obj.TotalLabels := if obj.TotalLabels ? obj.TotalLabels + 1 : 1
  2757. obj[obj.TotalLabels] := currentobj.Label
  2758. }
  2759. currentobj["Path" . currentobj.TotalItems] := A_LoopFileLongPath
  2760. currentobj["Ext" . currentobj.TotalItems] := A_LoopFileExt
  2761. currentobj["AssetType"] := currentAssetType
  2762. currentobj["Type"] := "ImageGroup"
  2763. obj.Insert(currentobj["Label"], currentobj)
  2764. }
  2765. }
  2766. } Else If InStr(RASHNDOCT, "A") { ; it is a file
  2767. SplitPath, A_LoopField, , currentDir,, FileNameWithoutExtension
  2768. Loop, Parse, extensionsReplaced,`,
  2769. {
  2770. If FileExist(currentDir . "\" . FileNameWithoutExtension . "." . A_LoopField)
  2771. { currentobj := {}
  2772. If (currentLabel="keepFileName")
  2773. currentobj["Label"] := FileNameWithoutExtension
  2774. Else
  2775. currentobj["Label"] := currentLabel
  2776. If obj[FileNameWithoutExtension].Label
  2777. { currentobj := obj[FileNameWithoutExtension]
  2778. currentobj.TotalItems := currentobj.TotalItems+1
  2779. } Else {
  2780. currentobj.TotalItems := 1
  2781. obj.TotalLabels := if obj.TotalLabels ? obj.TotalLabels + 1 : 1
  2782. obj[obj.TotalLabels] := currentobj.Label
  2783. }
  2784. currentobj["Path" . currentobj.TotalItems] := currentDir . "\" . FileNameWithoutExtension . "." . A_LoopField
  2785. currentobj["Ext" . currentobj.TotalItems] := A_LoopField
  2786. currentobj["AssetType"] := currentAssetType
  2787. obj.Insert(currentobj["Label"], currentobj)
  2788. }
  2789. }
  2790. }
  2791. } Else
  2792. Log("BuildAssetsTable - This asset has been disabled: " . labelArray%A_Index%,4)
  2793.  
  2794. }
  2795. If (logLevel>=5){
  2796. for index, element in obj
  2797. { Loop, % obj[element.Label].TotalItems
  2798. mediaAssetsLog := % mediaAssetsLog . "`r`n`t`t`t`t`tAsset Label: " . element.Label . " | Asset Path" . a_index . ": " . element["Path" . a_index] . " | Asset Extension" . a_index . ": " . element["Ext" . a_index] . " | Asset Type" . a_index . ": " . element["AssetType"]
  2799. }
  2800. If mediaAssetsLog
  2801. Log("BuildAssetsTable - Media assets found: " . mediaAssetsLog,5)
  2802. }
  2803. Log("BuildAssetsTable - Ended",4)
  2804. Return obj
  2805. }
  2806.  
  2807. BuildAssetsTableOld(list,label,AssetType,extensions=""){
  2808. Log("BuildAssetsTable - Started - Building Table for: " . label,4)
  2809. Global logLevel
  2810. StringReplace, extensionsReplaced, extensions, |, `,,All
  2811. obj:={}
  2812. StringSplit, labelArray, label, |,
  2813. StringSplit, AssetTypeArray, AssetType, |,
  2814. Loop, Parse, list,|
  2815. { labelIndex++
  2816. If !(labelArray%labelIndex% = "#disabled#")
  2817. {
  2818. Log("BuildAssetsTable - Searching for a " . labelArray%labelIndex% . ": " . A_LoopField,4)
  2819. currentLabel := labelArray%labelIndex%
  2820. currentAssetType := AssetTypeArray%A_index%
  2821. RASHNDOCT := FileExist(A_LoopField)
  2822. If InStr(RASHNDOCT, "D") { ; it is a folder
  2823. folderName := A_LoopFileName
  2824. Loop, % A_LoopField . "\*.*"
  2825. { If RegExMatch(extensions,"i)" . A_LoopFileExt)
  2826. { currentobj := {}
  2827. If (currentLabel="keepFileName")
  2828. currentobj["Label"] := folderName
  2829. Else
  2830. currentobj["Label"] := currentLabel
  2831. If obj[currentLabel].Label
  2832. { currentobj := obj[currentLabel]
  2833. currentobj.TotalItems := currentobj.TotalItems+1
  2834. } Else {
  2835. currentobj.TotalItems := 1
  2836. obj.TotalLabels := if obj.TotalLabels ? obj.TotalLabels + 1 : 1
  2837. obj[obj.TotalLabels] := currentobj.Label
  2838. }
  2839. currentobj["Path" . currentobj.TotalItems] := A_LoopFileLongPath
  2840. currentobj["Ext" . currentobj.TotalItems] := A_LoopFileExt
  2841. currentobj["AssetType"] := currentAssetType
  2842. currentobj["Type"] := "ImageGroup"
  2843. obj.Insert(currentobj["Label"], currentobj)
  2844. }
  2845. }
  2846. } Else If InStr(RASHNDOCT, "A") { ; it is a file
  2847. SplitPath, A_LoopField, , currentDir,, FileNameWithoutExtension
  2848. Loop, Parse, extensionsReplaced,`,
  2849. {
  2850. If (InStr(extensionsReplaced , ",") && A_Index >= 2) {
  2851. labelIndex++ ; need to advance the label by one each time a new extension is used
  2852. currentLabel := labelArray%labelIndex%
  2853. }
  2854. If FileExist(currentDir . "\" . FileNameWithoutExtension . "." . A_LoopField)
  2855. { currentobj := {}
  2856. If (currentLabel="keepFileName")
  2857. currentobj["Label"] := FileNameWithoutExtension
  2858. Else
  2859. currentobj["Label"] := currentLabel
  2860. If obj[FileNameWithoutExtension].Label
  2861. { currentobj := obj[FileNameWithoutExtension]
  2862. currentobj.TotalItems := currentobj.TotalItems+1
  2863. } Else {
  2864. currentobj.TotalItems := 1
  2865. obj.TotalLabels := if obj.TotalLabels ? obj.TotalLabels + 1 : 1
  2866. obj[obj.TotalLabels] := currentobj.Label
  2867. }
  2868. currentobj["Path" . currentobj.TotalItems] := currentDir . "\" . FileNameWithoutExtension . "." . A_LoopField
  2869. currentobj["Ext" . currentobj.TotalItems] := A_LoopField
  2870. currentobj["AssetType"] := currentAssetType
  2871. obj.Insert(currentobj["Label"], currentobj)
  2872. }
  2873. }
  2874. }
  2875. } Else
  2876. Log("BuildAssetsTable - This asset has been disabled: " . labelArray%labelIndex%,4)
  2877.  
  2878. }
  2879. If (logLevel>=5){
  2880. for index, element in obj
  2881. { Loop, % obj[element.Label].TotalItems
  2882. mediaAssetsLog := % mediaAssetsLog . "`r`n`t`t`t`t`tAsset Label: " . element.Label . " | Asset Path" . a_index . ": " . element["Path" . a_index] . " | Asset Extension" . a_index . ": " . element["Ext" . a_index] . " | Asset Type" . a_index . ": " . element["AssetType"]
  2883. }
  2884. If mediaAssetsLog
  2885. Log("BuildAssetsTable - Media assets found: " . mediaAssetsLog,5)
  2886. }
  2887. Log("BuildAssetsTable - Ended",4)
  2888. Return obj
  2889. }
  2890.  
  2891.  
  2892. ;-------------------------------------------------------------------------------------------------------------
  2893. ;-------------------------------------- Broadcast and Message Receiving --------------------------------------
  2894. ;-------------------------------------------------------------------------------------------------------------
  2895. ReceiveMessage(wParam, lParam) ; receive messages from other programs
  2896. { Global Pause_Active, Pause_Running, systemName, gameInfo
  2897. ;Global ; it is necessary to use global if the var definition part is uncommented
  2898. StringAddress := NumGet(lParam + 8)
  2899. StringLength := DllCall("lstrlen", UInt, StringAddress)
  2900. If (StringLength <= 0)
  2901. Log("A blank string message was received by RocketLauncher or there was an error.")
  2902. Else
  2903. { VarSetCapacity(CopyOfData, StringLength)
  2904. DllCall("lstrcpy", "str", CopyOfData, "uint", StringAddress)
  2905. StringSplit, Data, CopyOfData, |
  2906. If (Data1)
  2907. {
  2908. If (Data1="command") { ; predefined commands
  2909. If (Data2="RLPause") {
  2910. If (Pause_Active){
  2911. Gosub, TogglePauseMenuStatus
  2912. Log("RocketLauncher received the windows message to unpause the game: " . Data2)
  2913. } Else If !(Pause_Running) {
  2914. Gosub, TogglePauseMenuStatus
  2915. Log("RocketLauncher received the windows message to pause the game: " . Data2)
  2916. }
  2917. } Else If (Data2="RLSelect") {
  2918. If (Pause_Active){
  2919. Gosub, ToggleItemSelectStatus
  2920. }
  2921. } Else If (Data2="RLUp") {
  2922. If (Pause_Active){
  2923. Gosub, MoveUp
  2924. }
  2925. } Else If (Data2="RLDown") {
  2926. If (Pause_Active){
  2927. Gosub, MoveDown
  2928. }
  2929. } Else If (Data2="RLLeft") {
  2930. If (Pause_Active){
  2931. Gosub, MoveLeft
  2932. }
  2933. } Else If (Data2="RLRight") {
  2934. If (Pause_Active){
  2935. Gosub, MoveRight
  2936. }
  2937. } Else If (Data2="RLExit") {
  2938. Gosub, CloseProcess
  2939. } Else {
  2940. Log("RocketLauncher received the windows message to run a inexistent command: " . Data2)
  2941. }
  2942. } Else If (Data1="ping") {
  2943. BroadcastMessage("RocketLauncher Message System is Available.")
  2944. } Else If (Data1="Which system?") {
  2945. BroadcastMessage("RocketLauncher Message. Current System: " . systemName)
  2946. } Else If (Data1="Which game?") {
  2947. BroadcastMessage("RocketLauncher Message. Current Game: " . gameInfo["Name"].Value)
  2948. }
  2949. /*} if (Data1="runlabel") {
  2950. if IsLabel(Data2) {
  2951. Log("RocketLauncher received the windows message to run the label: " . Data2)
  2952. gosub, %Data2%
  2953. } Else {
  2954. Log("RocketLauncher received the windows message to run a inexistent label: " . Data2)
  2955. }
  2956. } Else If (Data1="setvar") {
  2957. Log("RocketLauncher received the windows message to set the variable named " . Data2 . " to the value = " . Data3)
  2958. %Data2% := Data3
  2959. */
  2960. } Else
  2961. Log("RocketLauncher does not recognize the pure string message sent as a valid command: " . CopyOfData)
  2962. }
  2963. Return true
  2964. }
  2965.  
  2966. BroadcastMessage(StringToSend) {
  2967. Global broadcastWindowTitle
  2968. If broadcastWindowTitle {
  2969. VarSetCapacity(CopyDataStruct, 12, 0)
  2970. NumPut(StrLen(StringToSend) + 1, CopyDataStruct, 4)
  2971. NumPut(&StringToSend, CopyDataStruct, 8)
  2972. Prev_DetectHiddenWindows := A_DetectHiddenWindows
  2973. Prev_TitleMatchMode := A_TitleMatchMode
  2974. DetectHiddenWindows On
  2975. SetTitleMatchMode 2
  2976. ; If (BroadcastWindowTitle="All"){
  2977. ; Log("BroadcastMessage - Sending message """ . StringToSend . """ to all windows.")
  2978. ; SendMessage, 0x4a, 0, &CopyDataStruct,, ahk_id 0xFFFF
  2979. If InStr(BroadcastWindowTitle, "|") {
  2980. Loop, Parse, BroadcastWindowTitle, |, %A_Space%
  2981. { Log("BroadcastMessage - Sending message """ . StringToSend . """ to " . A_LoopField . " window.")
  2982. SendMessage, 0x4a, 0, &CopyDataStruct,, % BroadcastWindowTitle
  2983. }
  2984. } Else If (BroadcastWindowTitle){
  2985. If (WinExist(BroadcastWindowTitle) != "0x0") {
  2986. Log("BroadcastMessage - Sending message """ . StringToSend . """ to " . BroadcastWindowTitle . " window.")
  2987. SendMessage, 0x4a, 0, &CopyDataStruct,, % BroadcastWindowTitle
  2988. } Else
  2989. Log("BroadcastMessage - Could not broadcast message """ . StringToSend . """ to " . BroadcastWindowTitle . " because the window could not be found.",2)
  2990. } Else
  2991. Log("Message was not broadcasted because the lack of a valid window target.",4)
  2992. DetectHiddenWindows %Prev_DetectHiddenWindows%
  2993. SetTitleMatchMode %Prev_TitleMatchMode%
  2994. Return ErrorLevel ; Return SendMessage's reply back to our caller.
  2995. }
  2996. }
  2997.  
  2998.  
  2999. ;-------------------------------------------------------------------------------------------------------------
  3000. ;----------------------------------------- Split Screen Module Support ------------------------------------------
  3001. ;-------------------------------------------------------------------------------------------------------------
  3002.  
  3003. ; SplitScreenPos function
  3004. ; Returns an object with the screen coordinates (posArray[screen number].x, posArray[screen number].y, posArray[screen number].w and posArray[screen number].h) for placing split screen emulator screens.
  3005. ; Supports up to 8 screens
  3006. ; splitScreen2PlayersMode can be Vertical or Horizontal
  3007. ; splitScreen3PlayersMode can be P1top, P1left, P1right, P1bottom
  3008. ; maxPlayersPerMonitor defines the maximun amount of player screens to be placed at each monitor. For example, "1|2|3" means that screen 1 will only have the player 1, screen 2 will have the player 2 and 3 and screen 3 will have the players 4, 5 and 6 screens. If the current available monitors is not able to show the selected number of players, the code will automatically increase the screen 1 amount of screens untill all players are displayed
  3009. SplitScreenPos(numberofPlayers,splitScreen2PlayersMode="Horizontal",splitScreen3PlayersMode="P1top",maxPlayersPerMonitor="4|4|4"){
  3010. Global monitorTable
  3011. Log("SplitScreenPos - Started")
  3012. ;Making sure to distribute screens only on current available monitors and find out how many monitors are needed to show the selected number of players
  3013. monitor := []
  3014. StringSplit,playerPerMonitor,maxPlayersPerMonitor,|
  3015. Loop, % monitorTable.MaxIndex()
  3016. { monitor[a_index] := {}
  3017. currentNumberOfPlayers := playerPerMonitor%a_index%
  3018. accumulatedPlayers += currentNumberOfPlayers
  3019. If (accumulatedPlayers>numberofPlayers)
  3020. currentNumberOfPlayers := numberofPlayers - (accumulatedPlayers-currentNumberOfPlayers)
  3021. monitor[a_index].numberOfPlayers := currentNumberOfPlayers
  3022. }
  3023. If (accumulatedPlayers<numberofPlayers){
  3024. Loop, % (numberofPlayers-accumulatedPlayers)
  3025. { count1++
  3026. If ( count1 > monitorTable.MaxIndex() )
  3027. count1 := 1
  3028. monitor[count1].numberOfPlayers += 1
  3029. }
  3030. }
  3031. ;Defining splitscreen positions
  3032. posArray := []
  3033. Loop, % numberofPlayers
  3034. posArray[a_index] := {}
  3035. count := 0
  3036. Loop, % monitor.MaxIndex()
  3037. { currentMonitor := a_index
  3038. If (monitor[currentMonitor].numberOfPlayers = 1){
  3039. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width , posArray[count+1].H := monitorTable[currentMonitor].Height
  3040. } Else If (monitor[currentMonitor].numberOfPlayers = 2){
  3041. If (splitScreen2PlayersMode = "Vertical"){
  3042. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//2 , posArray[count+1].H := monitorTable[currentMonitor].Height
  3043. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height
  3044. } Else {
  3045. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3046. posArray[count+2].X := monitorTable[currentMonitor].Left , posArray[count+2].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+2].W := monitorTable[currentMonitor].Width , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3047. }
  3048. } Else If (monitor[currentMonitor].numberOfPlayers = 3){
  3049. If (splitScreen3PlayersMode = "P1left"){
  3050. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//2 , posArray[count+1].H := monitorTable[currentMonitor].Height
  3051. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3052. posArray[count+3].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+3].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+3].W := monitorTable[currentMonitor].Width//2 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3053. } Else If (splitScreen3PlayersMode = "P1bottom") {
  3054. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+1].W := monitorTable[currentMonitor].Width , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3055. posArray[count+2].X := monitorTable[currentMonitor].Left , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3056. posArray[count+3].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+3].Y := monitorTable[currentMonitor].Top , posArray[count+3].W := monitorTable[currentMonitor].Width//2 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3057. } Else If (splitScreen3PlayersMode = "P1right") {
  3058. posArray[count+1].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//2 , posArray[count+1].H := monitorTable[currentMonitor].Height
  3059. posArray[count+2].X := monitorTable[currentMonitor].Left , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3060. posArray[count+3].X := monitorTable[currentMonitor].Left , posArray[count+3].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+3].W := monitorTable[currentMonitor].Width//2 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3061. } Else { ;top
  3062. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3063. posArray[count+2].X := monitorTable[currentMonitor].Left , posArray[count+2].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3064. posArray[count+3].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+3].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+3].W := monitorTable[currentMonitor].Width//2 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3065. }
  3066. } Else If (monitor[currentMonitor].numberOfPlayers = 4){
  3067. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//2 , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3068. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3069. posArray[count+3].X := monitorTable[currentMonitor].Left , posArray[count+3].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+3].W := monitorTable[currentMonitor].Width//2 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3070. posArray[count+4].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+4].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+4].W := monitorTable[currentMonitor].Width//2 , posArray[count+4].H := monitorTable[currentMonitor].Height//2
  3071. } Else If (monitor[currentMonitor].numberOfPlayers = 5){
  3072. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//2 , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3073. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//2 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//2 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3074. posArray[count+3].X := monitorTable[currentMonitor].Left , posArray[count+3].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+3].W := monitorTable[currentMonitor].Width//3 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3075. posArray[count+4].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//3 , posArray[count+4].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+4].W := monitorTable[currentMonitor].Width//3 , posArray[count+4].H := monitorTable[currentMonitor].Height//2
  3076. posArray[count+5].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//3 , posArray[count+5].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+5].W := monitorTable[currentMonitor].Width//3 , posArray[count+5].H := monitorTable[currentMonitor].Height//2
  3077. } Else If (monitor[currentMonitor].numberOfPlayers = 6){
  3078. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//3 , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3079. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//3 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//3 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3080. posArray[count+3].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//3 , posArray[count+3].Y := monitorTable[currentMonitor].Top , posArray[count+3].W := monitorTable[currentMonitor].Width//3 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3081. posArray[count+4].X := monitorTable[currentMonitor].Left , posArray[count+4].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+4].W := monitorTable[currentMonitor].Width//3 , posArray[count+4].H := monitorTable[currentMonitor].Height//2
  3082. posArray[count+5].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//3 , posArray[count+5].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+5].W := monitorTable[currentMonitor].Width//3 , posArray[count+5].H := monitorTable[currentMonitor].Height//2
  3083. posArray[count+6].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//3 , posArray[count+6].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+6].W := monitorTable[currentMonitor].Width//3 , posArray[count+6].H := monitorTable[currentMonitor].Height//2
  3084. } Else If (monitor[currentMonitor].numberOfPlayers = 7){
  3085. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//3 , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3086. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//3 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//3 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3087. posArray[count+3].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//3 , posArray[count+3].Y := monitorTable[currentMonitor].Top , posArray[count+3].W := monitorTable[currentMonitor].Width//3 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3088. posArray[count+4].X := monitorTable[currentMonitor].Left , posArray[count+4].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+4].W := monitorTable[currentMonitor].Width//4 , posArray[count+4].H := monitorTable[currentMonitor].Height//2
  3089. posArray[count+5].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//4 , posArray[count+5].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+5].W := monitorTable[currentMonitor].Width//4 , posArray[count+5].H := monitorTable[currentMonitor].Height//2
  3090. posArray[count+6].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//4 , posArray[count+6].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+6].W := monitorTable[currentMonitor].Width//4 , posArray[count+6].H := monitorTable[currentMonitor].Height//2
  3091. posArray[count+7].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*3//4 , posArray[count+7].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+7].W := monitorTable[currentMonitor].Width//4 , posArray[count+7].H := monitorTable[currentMonitor].Height//2
  3092. } Else If (monitor[currentMonitor].numberOfPlayers = 8){
  3093. posArray[count+1].X := monitorTable[currentMonitor].Left , posArray[count+1].Y := monitorTable[currentMonitor].Top , posArray[count+1].W := monitorTable[currentMonitor].Width//4 , posArray[count+1].H := monitorTable[currentMonitor].Height//2
  3094. posArray[count+2].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//4 , posArray[count+2].Y := monitorTable[currentMonitor].Top , posArray[count+2].W := monitorTable[currentMonitor].Width//4 , posArray[count+2].H := monitorTable[currentMonitor].Height//2
  3095. posArray[count+3].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//4 , posArray[count+3].Y := monitorTable[currentMonitor].Top , posArray[count+3].W := monitorTable[currentMonitor].Width//4 , posArray[count+3].H := monitorTable[currentMonitor].Height//2
  3096. posArray[count+4].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*3//4 , posArray[count+4].Y := monitorTable[currentMonitor].Top , posArray[count+4].W := monitorTable[currentMonitor].Width//4 , posArray[count+4].H := monitorTable[currentMonitor].Height//2
  3097. posArray[count+5].X := monitorTable[currentMonitor].Left , posArray[count+5].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+5].W := monitorTable[currentMonitor].Width//4 , posArray[count+5].H := monitorTable[currentMonitor].Height//2
  3098. posArray[count+6].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width//4 , posArray[count+6].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+6].W := monitorTable[currentMonitor].Width//4 , posArray[count+6].H := monitorTable[currentMonitor].Height//2
  3099. posArray[count+7].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*2//4 , posArray[count+7].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+7].W := monitorTable[currentMonitor].Width//4 , posArray[count+7].H := monitorTable[currentMonitor].Height//2
  3100. posArray[count+8].X := monitorTable[currentMonitor].Left+monitorTable[currentMonitor].Width*3//4 , posArray[count+8].Y := monitorTable[currentMonitor].Top+monitorTable[currentMonitor].Height//2 , posArray[count+8].W := monitorTable[currentMonitor].Width//4 , posArray[count+8].H := monitorTable[currentMonitor].Height//2
  3101. } Else {
  3102. Log("SplitScreenPos - " . monitor[currentMonitor].numberOfPlayers . " is a nonsupported number of players for the split screen position calculation function.",2)
  3103. }
  3104. Loop, % monitor[currentMonitor].numberOfPlayers
  3105. Log("SplitScreenPos - Player " . count+a_index . " window position: X=" . posArray[count+a_index].X . ", Y=" . posArray[count+a_index].Y . ", W=" . posArray[count+a_index].W . ", H=" . posArray[count+a_index].H,5)
  3106. count += monitor[currentMonitor].numberOfPlayers
  3107. If (count >= numberofPlayers)
  3108. Break
  3109. }
  3110. Log("SplitScreenPos - Ended")
  3111. Return posArray
  3112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement