--[====================================================================================================================[ I2 Cheat Engine Auto Assembler Script Template Generator. And memory record creator. Version: 1.1.7 1.0.1: * First release. 1.0.2: * I2 Template Changes. 1.0.3: * I2 Template Changes. 1.0.4: * I2 Template Changes. 1.0.5: * I2 Template Changes. * I2 Template Memory Record Changes. * Removed I2 templates menu section, menu items now in main section. * Moved main form menu items form "miExtra", to "miTemplates". 1.1.1: * I2 Template Changes. * I2 Template Memory Record Changes. * Fixed template AOB signature function. * Added "Get byte scan signature info" context menu option to memory view form. * Fixed memory record template items setting "OffsetText" and "Offset". * Added CE's "translate" function to the local translate function. * Fixed address errors with "module+offset", now giving proper "module+offset". * Added bring Cheat Engine to front on adding memory records option. * Added "AskToAddToTable" option for templates. * Added "AddToMainOnly" for template menu item creation on only the main form. 1.1.2: * Fixed error with "getModuleAndOffsetFromAddress" if no process is hooked. * Fixed pointer offset conversion error. 1.1.3: * Added Hook Setup form to allow input of hook name address and generate aob option. * Injection point is now input address, defaults to greatest line in memory view form. * Aob is now selected lines in memory view form. * Aob offset calculated form injection point and aob start address. * Added "AOBAddress" and "AOBOffset" template tags. * I2 Template Changes. * I2 Template Memory Record Changes 1.1.4: * Added enter key default for ok button on hook setup form. * Added escape key default for cancel button on hook setup form. * Fixed original code offset padding. * Added "BaseAddressOffsetValue" template key. * I2 Template Changes. * Added "{$strict}" to all ASM templates. * Fixed scripts not being added to open auto assembler form (sorry, forgot about this one). * Added documentation on new features, setting, and template keys. 1.1.5: * Added more documentation. * Put Aob memory view signature scan in threaded function call. 1.1.6: * Generation of Memory View form pop-up menu template items under a sub-menu, to allow short keys to work from Memory View form. * Fixed error with empty check having OR and not an AND as needed. 1.1.7: * Fix I2 memory record error. * Moved Template values for, AOB with Values; To be setup for aligned packed instructions * I2 Template Changes. * Changed "getMainForm()" to "MainForm". * Changed Hook Setup form, moved the address input to the top. Author: Matt - TheyCallMeTim13 - MattI2.com Forked Version of: "customAOBInjectionTemplates.lua": Posting Author: mgr.inz.Player * http://forum.cheatengine.org/viewtopic.php?t=588038 "Custom Lua Script Templates.lua": Posting Author: predprey * http://forum.cheatengine.org/viewtopic.php?t=595096 "aamaker.lua": Posting Author: GH*master * http://forum.cheatengine.org/viewtopic.php?t=587401 Features: - Allows for adding templates as tables or in a directory structure. - Load templates function can be called multiple time to allow for standard and game specific templates. - Allows for template tables to have memory records generated along with the template script. - Memory record string settings are parsed for template keys. - Template table structure sets the menu item structure created. - Generic place holder key replacement though standard input forms. - A Standard header can be set for use in templates. - Gets the file version of the process's executable, for use in templates. - Set the amount of data collected and put in injection information. - Generate byte scan signature from selection of memory view form for AOB templates; or generate byte scan signature from address, plus instruction minimum, for AOB templates. See: "UseMemoryViewFormSelectionForAOBSignature" in settings. * NOTE: Scan is preformed on generated scan signature filled with wild cards. - Generate byte scan signature from selection of memory view form to be printed only. * NOTE: Scan is preformed on generated scan signature filled with wild cards. Example: --- Start --- Game Title: Dishonored Game Version: 1.0.0.0 Process: Dishonored.exe Process Address: 00400000 Start Address: Dishonored.AK::SoundEngine::StartOutputCapture+706CB 00AB427B End Address: Dishonored.AK::SoundEngine::StartOutputCapture+706EA 00AB429A Test byte signature: 8Bxxxxxxxxxx8Bxxxxxxxxxx83xxxxxx8Dxxxxxx89xxxx83xxxx74xx8Bxxxx8Dxxxx Found: 2 Test byte signature is NOT unique. --- End --- Example: --- Start --- Game Title: Tutorial-i386 Game Version: GAME_VERSION Process: Tutorial-i386.exe Process Address: 00400000 Start Address: Tutorial-i386.exe+24B5F 00424B5F End Address: Tutorial-i386.exe+24BAB 00424BAB Test byte signature: 8Bxxxxxxxxxx8Bxxxx89xx8Bxxxx8Bxxxxxxxxxx8Bxx3Bxxxx74xxEBxx8Bxxxx ... Trimmed for documentation Test byte signature is unique. --- End --- For the default templates see: - CE Form >> Ctrl+M >> Ctrl+A >> Menu >> Templates - CE Form >> Main Menu >> Templates To add templates use: local TemplatesTable = { ... } I2CEAutoAssemblerScriptTemplates.loadTemplates(TemplatesTable) To add templates from a directory: I2CEAutoAssemblerScriptTemplates.loadTemplatesDirectory([[x:\SomeOddDirectory]]) Install / Setup Method 1: - Put file in CE autorun folder. Install / Setup Method 2: - Put in CE lua folder (it isn't created by default). And in a file in the CE autorun folder import and add tables. Example: local TemplatesTable = { ... } local I2CEAASTG = require 'pluginI2CEAutoAssemblerScriptTemplateGenerator' ---- You could rename the file if you go this route. I2CEAASTG.loadTemplates(TemplatesTable) Settings: UserNameEnvKey : string - Environment variable key for user name. i.e.: 'CE_USERNAME' or 'HEYBUDDYWHATSTHENAME' UserName : string - Used for overriding the system's user name from environment ('USERNAME'). ** See 'Environment Variable Keys' to override that way. DateFormat : string - Lua date format string. AddMainSeperator : boolean - Set to true to have a separator added to the menu before adding template menu items. InjectionInfoCount : integer - The number of lines before and after injection point in injection info. i.e.: 10 will generate 21 lines of disassembler output. 10 before (addresses less then injection address) 1 injection point 10 after (addresses greater then injection address) PlaceHolderKey : string - The Place holder key used in templates for generic replacement prompts. ** See: 'Template Place Holders' for more info. AutoLoad : boolean - Set to false to stop auto loading of templates. TemplatesDirectory : string - The templates directory to use. ** *** Template files use a unique format, (my change to template files matched with json files for settings) so this should be in a unique spot (IT CAN CLASH with other template generators if in same folder). NopASM : string - ASM for nops. i.e.: 'nop' or 'Nop' or 'nop //// No Operation' * There is a separate template key for nops as data bytes. (i.e.: 'db 90 90 90') AddI2Templates : Set to "false" to disable adding of I2 templates MemoryViewFormByteSignatureScanInfoDescription : Memory view form context menu byte signature scan info description. MemoryViewFormByteSignatureScanInfoShortcut : Memory view form context menu byte signature scan info short cut string. AOBScanByteLengthMin : The min number of bytes that will be accepted with out being prompted for approval. * This is to stop from accidentally scanning for to few bytes (in large games this can that a little while). * But will prompt for approval to allow for scanning (in smaller games scanning for 5 bytes is not a problem). * NOTE: Scan is preformed on generated scan signature filled with wild cards. AOBSignatureLength : integer - The minimum number of bytes for AOB signatures. UseMemoryViewFormSelectionForAOBSignature : Set to true to use memory view form selection instead of "AOBSignatureLength" plus selected address. BringCheatEngineToFrontOnCreateMemoryRecords : Set to true to bring Cheat Engine from to front on adding memory records to table. Template Options: Table of settings for template generating. Required Options: DisplayString : string - The menu display string. Bound Required Options: One or the other. * TemplateString : string - The template string to use. TemplateFile : string - The file path of the template. *** Do not use multi extension files. (still figuring this one out) i.e.: 'AOB_Injection.template.cea' Instead try: 'AOB_Injection-template.cea ' Name : string - The name of the template. *** Used in menu item creation, also in injection information and logging. GetAddress : boolean - Set to true to be prompted for an address. * Address is pulled from disassembler view form selection. So this is a formality. IsFullHook : boolean - Set to true to have no less then 5 bytes for a full jump. GetHookName : boolean - Set to true to be prompted for a hook name. * All template hook keys will be empty strings if not set to true. HookTag : string - The tag to use for prompts. i.e.: 'Hook', 'Hack', 'Cheat', 'Exploit', or what have you. AppendHookTag : boolean - Set to true to have the hook tag appended to the hook name. Unless the hook tag is already in the hook name. FixInputData : boolean - Set to true to fix sloppy input data. * Only affects hook name. * Title cases and removes spaces from input. GetAOBSignature : boolean - Set to true to have an aob signature generated. Memory Records: : table - Table of settings for generating template memory records to add to cheat table. * See: 'Template Memory Records' MemoryRecordsIncludeScript : boolean - Set to true for prompt to say memory records include script. NopPaddingLeft : string - The leading padding for nops lines. i.e.: '\t\t' OriginalCodePaddingLeft : string - The leading padding for the original code lines. i.e.: '\t\t' LineEnd : string - The line end string. (i.e.: '\n' or '\r\n') LineComment : string - The line comment string. (i.e.: '////' or '//') InjectionInfoCommentType : integer:CommentTypes : The injection info comment type. Shortcut : Set to short-cut keys string to use for template menu item. i.e.: 'ctrl+0' AskToAddToTable : set to false to suppress asking to add memory records to table. Note: Must set to false to suppress asking to add memory records to table, else asked by default. AddToMainOnly : Set to true to have menu items for template only added to the main form. Example Table: Templates = { Name = 'I2CEATemplates', SectionDisplayString = 'I2 CEA Templates', SectionName = 'miI2CEATemplatesSection', { DisplayString = 'Address Injection', GetAddress = true, GetHookName = true, HookTag = 'Cheat', AppendHookTag = true, TemplateString = I2_TEMPLATE_ADDRESS_INJECTION, MemoryRecordsIncludeScript = true, MemoryRecords = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = Colors.Teal, }, { Description = '_[== ${HookName} ==]_', IsGroupHeader = true, MemoryRecords = { { Description = 'inj${HookNameParsed}', Address = 'inj${HookNameParsed}', Color = Colors.Red, Type = vtByteArray, Aob = { Size = 0, }, ShowAsHex = true, }, }, }, }, }, } Template Memory Records: Table of settings for memory record generating. ID : integer - Unique ID Description : string - The description of the memory record Address : string - The interpretable address string. OffsetCount : integer - The number of offsets. Set to 0 for a normal address Offset[] : array - integer - Array to access each offset OffsetText[] : array - string - Array to access each offset using the interpretable text style Type : ValueType - The variable type of this record. See vtByte to vtCustom ** *** Set to 'pointer' for a type value of vtQword or vtDword based on pointer size. i.e.: Type = 'POINTER', * If the type is vtString then the following properties are available: String : table - Table with key value pairs. Size : integer - Number of characters in the string Unicode : boolean * If the type is vtBinary then the following properties are available Binary : table - Table with key value pairs. Startbit : integer - First bit to start reading from Size : integer - Number of bits * If the type is vtByteArray then the following properties are available Aob : table - Table with key value pairs. Size : integer - Number of bytes Script : String - If the type is vtAutoAssembler this will contain the auto assembler script ** *** If the type is vtAutoAssembler and no script is set the parsed template will be used. CustomTypeName : string - If the type is vtCustomType this will contain the name of the CustomType Value : string - The value in string form. Active : boolean - Set to true to activate/freeze, false to deactivate/unfreeze Color : integer ShowAsHex : boolean - Self explanatory ShowAsSigned : boolean - Self explanatory AllowIncrease : boolean - Allow value increasing, unfreeze will reset it to false AllowDecrease : boolean - Allow value decreasing, unfreeze will reset it to false Collapsed : boolean - Set to true to collapse this record or false to expand it. Use expand/collapse methods for recursive operations. HotkeyCount : integer - Number of hot-keys attached to this memory record Hotkey[] : array - Array to index the hot-keys DontSave : boolean - Don't save this memoryrecord and it's children Async : boolean - Set to true if activating this entry will be asynchronious. (only for AA/Lua scripts) Collapsed : boolean - Set to true to collapse this record or false to expand it. Use expand/collapse methods for recursive operations. OnActivate : function(memoryrecord, before, currentstate) : boolean - The function to call when the memoryrecord will change (or changed) Active to true. If before is true, not returning true will cause the activation to stop. OnDeactivate : function(memoryrecord, before, currentstate) : boolean - The function to call when the memoryrecord will change (or changed) Active to false. If before is true, not returning true will cause the deactivation to stop. OnDestroy : function() : Called when the memoryrecord is destroyed. options : Memory record options. i.e.: "[moHideChildren]" "[moHideChildren, moActivateChildrenAsWell, moDeactivateChildrenAsWell, " .. "moRecursiveSetValue, moAllowManualCollapseAndExpand, moManualExpandCollapse]" Example Table: MemoryRecords = { { Description = '_[== ${HookName} ==]_', IsGroupHeader = true, Async = true, MemoryRecords = { { Description = 'inj${HookNameParsed}', Address = 'inj${HookNameParsed}', Color = Colors.Red, Type = vtByteArray, Aob = { Size = 0, }, ShowAsHex = true, options = "[moHideChildren]", }, }, }, { Description = 'flg${HookNameParsed}IsAssembled', Address = 'flg${HookNameParsed}IsAssembled', Color = Colors.Olive, Type = vtByte, DropDownList = { Text = '0:Not Assembled\n1:Assembled\n', }, DropDownReadOnly = true, ---- Disallow manual user input DropDownDescriptionOnly = true, ---- Only show the description part DisplayAsDropDownListItem = true, ---- Make the record display values like the dropdownlist }, { Description = 'inj${HookNameParsed}', Address = 'inj${HookNameParsed}', Color = Colors.Red, Type = vtByteArray, Aob = { Size = 0, }, ShowAsHex = true, }, { Description = '${BaseAddressOffset} - ', Color = Colors.Black, Type = vtDword, ShowAsHex = false, OffsetText = { '${BaseAddressOffset}', }, Address = 'ptr${HookNameParsed}', } } Template Keys: - Keys to be used in templates and memory record strings. format: ${TemplateKey} ProcessName - The process name. ProcessAddress - The process address. Module - The address's module, if it is in a module. ModuleAddress - The address's module address, if it is in a module. ModuleSize - The address's module size, if it is in a module. ModuleBitSize - The address's module bit size, if it is in a module. i.e.: '(x32)' or '(x64)' ModuleStr - Will be set to the word 'Module' if the address is in a module. * Used with aob scan. i.e.: 'aobScan${ModuleStr}(...' ModuleDecl - Will be set to the module name with a comma in front, if the address is in a module. * Used with aob scans, and memory allocation. i.e.: 'alloc(SomeUserSymbol, 0x400${ModuleDecl})' Address - The address, will be in module with offset format, if the address is in a module. * Pulled from disassembler view form selection. AddressHex - The address in hex format, length is based on pointer size. Date - The current date. Author - The detected user name. *** Set global 'CE_USERNAME', or environment variable 'CE_USERNAME', to override the windows user name. HookTag - The hook tag word. i.e.: 'Hook', 'Hack', 'Cheat', 'Exploit', or what have you. HookName - The, human readable, hook name. i.e.: 'Ammo DEC Hook', or 'Ammo DEC' HookNameBase - The hook name with out the hook tag appended. * Even if 'AppendHookTag' is set to 'true'. * If 'AppendHookTag' is set to 'false' it will be the same as 'HookName'. HookNameParsed - The, machine readable, hook name. i.e.: 'AmmoDECHook', or 'AmmoDEC' HookNameParsedBase - The parsed hook name with out the hook tag appended. * Even if 'AppendHookTag' is set to 'true'. * If 'AppendHookTag' is set to 'false' it will be the same as 'HookNameParsed'. AOBBytes - AOB byte signature string. AOBMessage - Used if more then one match was found. ** Adds a new line character if there is a message. i.e.: '\n// Matches Found: 25' AOBOffset - The AOBs calculated offset from injection point. This will include a '+' or '-'. AOBAddress - The address of the AOB starting point. OriginalCode - The original code (pulled from disassembler view form) OriginalBytes - The original bytes (pulled from disassembler view form) InstNOPS - Nops matching the original number of bytes. InstNOP90S - Nops, in data byte format, matching the original number of bytes. i.e.: 'db 90 90 90' NOPS - Used if nops are needed. NOP90S - Used if nops are needed. InjectionInfo - The injection information collected (the commented out disassembler output). CEVersion - Cheat Engine's version. PointerSize - The processes pointer size. i.e.: x32 PointerSize is 4 and x64 PointerSize is 8. PointerFtmStr - The processes pointer format string. (for lua use in templates) i.e.: x32 PointerFtmStr is '%08X' and x64 PointerFtmStr is '%016X'. PointerWordSize - The processes pointer declaration word. i.e.: x32 PointerWordSize is 'dd' and x64 PointerWordSize is 'dq'. PointerDefault - The processes pointer declaration with integer 0 value. i.e.: x32 PointerWordSize is 'dd 0' and x64 PointerWordSize is 'dq 0'. PointerDefaultFull - The processes pointer declaration with hex 0 value. i.e.: x32 PointerDefaultFull is 'dd 00000000' and x64 PointerDefaultFull is 'dq 0000000000000000'. GameTitle - The game title. (See: 'Global Variables' for overriding process based value) GameVersion - The game version. (See: 'Global Variables' for overriding determined value) BaseAddressRegistry - Registry pulled form original code of the first line (uses lua matching). BaseAddressOffset - Offset for registry pulled form original code of the first line (uses lua matching). * Looks for most instructions followed by brackets with a registry and offset. Kinda works! i.e.: mov eax,[rsi+10] BaseAddressRegistry will be 'rsi' BaseAddressOffset will be '+10' BaseAddressOffsetValue - The decimal value of the offset for registry pulled form original code. Templates: Key Format: ${TemplateKey} Example: ${Header} define(bytes, ${OriginalBytes}) define(address, ${Address}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] assert(address, bytes) //// //// ---------- Injection Point ---------- address: ${InstNOPS} //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- address: db bytes ${InjectionInfo} Template Place Holders: - User will be prompted for replacement of key words (every thing after place holder key). * Key words are striped of underscores and title cased before prompt. i.e.: PlaceHolder_Some_Value -> "Some Value" PlaceHolder_the_ultimate_question -> "The Ultimate Question" Key Start: PlaceHolder_ Example: ${Header} define(bytes, ${OriginalBytes}) define(address, ${Address}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] assert(address, bytes) //// //// ---------- Injection Point ---------- address: mov [${BaseAddressRegistry}${BaseAddressOffset}],${PlaceHolder_Push_Value_In_Hex} //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- address: db bytes ${InjectionInfo} Template Files: - Template files can be just a CEA file or they can have a settings and template section ** *** Must be just a CEA file, or have '[SETTINGS]' then '[TEMPLATE]' section in that order. i.e.: | Good | Good | Good | Bad | |---------------|---------------|---------------|---------------| | [SETTINGS] | [TEMPLATE] | ... | [TEMPLATE] | | ... | ... | ... | ... | | [TEMPLATE] | ... | ... | [SETTINGS] | | ... | ... | ... | ... | |---------------|---------------|---------------|---------------| CEA Files: - The standard CEA format with templates keys, caption add menu section will be determinate by file name and directory. i.e.: 'some_template.cea' -> 'Some Template' - (Templates Menu) i.e.: 'some_section\some_template.cea' -> 'Some Template' - 'Some Section' (miSomeSection) Settings: - Only allows basic setting (no nested settings at this point ?? json). ** *** Settings and template section keys must be the only thing on that line. Template: - The template to use (reads to end of file). ** *** Template and settings section keys must be the only thing on that line. Example: [SETTINGS] DisplayString = 'Some Template' GetAddress = true GetHookName = true GetAOBSignature = true [TEMPLATE] [ENABLE] {$lua} print('I Have The Power!!') [DISABLE] {$lua} print('Op, its gone.') Global Variables: GAME_TITLE - The game title. * If not set process name with out extension will be used. ** Manually set in table lua files, if needed. GAME_VERSION - The game version. * If not set value from 'getFileVersion' on the first module will be used. ** Manually set in table lua files, if needed. Global Variables (Overridden by Settings): [[ global - setting ]] CE_USERNAME - UserName I2CEAASTG_AUTO_LOAD - AutoLoad I2CEAASTG_TEMPLATES_DIRECTORY - TemplatesDirectory I2CEAASTG_NOP_ASM - NopASM I2CEAASTG_TEMPLATE_MARKER_LINE - TemplateMarkerLine I2CEAASTG_HEADER - TemplateHeader I2CEAASTG_AOB_SCAN_BYTE_MIN - AOBScanByteLengthMin I2CEAASTG_AOB_SIGNATURE_LENGHT - AOBSignatureLength Global Variables (Overridden by Template Options): [[ global - template option ]] I2CEAASTG_HOOK_TAG - HookTag I2CEAASTG_NOP_PADDING_LEFT - NopPaddingLeft I2CEAASTG_ORIGINAL_CODE_PADDING_LEFT - OriginalCodePaddingLeft I2CEAASTG_LINE_END - LineEnd I2CEAASTG_LINE_COMMENT - LineComment I2CEAASTG_INJ_INFO_COMMENT_TYPE - InjectionInfoCommentType Environment Variable Keys: (Overridden by global variables) CE_USERNAME - The name used for 'Author' template key. ]====================================================================================================================]-- local NAME = 'I2 Cheat Engine Auto Assembler Script Template Generator' local CLASS_NAME = 'I2CEAutoAssemblerScriptTemplates' local VERSION = '1.1.7' local AUTHOR = 'Matt Irwin; Matt.Irwin.US@Gmail.com' local LICENSE = [=[MIT License Copyright (c) 2017 Matt Irwin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sub-license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]=] local format = string.format local strE = string.empty or STRING_EMPTY or '' local t = translate local function getPath( ... ) local pathseparator = package.config:sub(1,1) local elements = { ... } return table.concat(elements, pathseparator) end local function exists(path) if type(path) ~= 'string' then return end return os.rename(path, path) and true or false end local function isFile(path) if type(path) ~= 'string' then return end if not exists(path) then return false end local f = io.open(path) if f then f:close() return true end return false end local function isDirectory(path) return (exists(path) and not isFile(path)) end -- -------- -------- -------- Logger -------- local Logger = { ClassName = 'I2Logger', Name = 'I2CEAASTG' } Logger.LEVELS = { OFF = 0, ERROR = 1, WARN = 2, INFO = 3, DEBUG = 4 } Logger.Level = Logger.LEVELS.WARN if DEBUG then Logger.Level = Logger.LEVELS.DEBUG end Logger.print = print function Logger.logEvent(level, msg, ex) if Logger.Level >= level then if Logger.Name ~= nil then msg = Logger.Name .. ': ' .. msg end if Logger.ClassName ~= nil then msg = Logger.ClassName .. '.' .. msg end Logger.print(msg) if ex then Logger.print('Exception: ' .. tostring(ex)) end end end for k,v in pairs(Logger.LEVELS) do if v > 0 then Logger[k:lower()] = function(msg, ex) return Logger.logEvent(v, msg, ex) end Logger[k:lower() .. 'f'] = function(msg, ... ) return Logger.logEvent(v, format(msg, ... )) end end end Logger.debugf('Loaded', Logger.ClassName) -------- -------- Logger -------- -------- local Colors = { Black = 0x000000, White = 0xFFFFFF, Silver = 0xC0C0C0, Grey = 0x808080, Red = 0x0000FF, -- 0xFF0000 Maroon = 0x000080, -- 0x800000 Yellow = 0x00FFFF, -- 0xFFFF00 Olive = 0x008080, -- 0x808000 Lime = 0x00FF00, Green = 0x008000, Aqua = 0xFFFF00, -- 0x00FFFF Teal = 0x808000, -- 0x008080 Blue = 0xFF0000, -- 0x0000FF Navy = 0x800000, -- 0x000080 Fuchsia = 0xFF00FF, Purple = 0x800080, } local CommentTypes = { Block = 1, Line = 2, } local I2CEAASTG_ADD_MAIN_SEPERATOR = (I2CEAASTG_ADD_MAIN_SEPERATOR ~= nil and I2CEAASTG_ADD_MAIN_SEPERATOR) or false local I2CEAASTG_ADD_AA_MAIN_SEPERATOR = (I2CEAASTG_ADD_AA_MAIN_SEPERATOR ~= nil and I2CEAASTG_ADD_AA_MAIN_SEPERATOR) or true local CREATE_MAIN_FORM_MENU_ITEMS = true local MAIN_FORM_PARENT_MENU_ITEM_NAME = 'miTemplates' local MAIN_FORM_PARENT_MENU_ITEM_CAPTION = 'Templates' local MENU_CREATION_TIMER_INTERVALS = 500 local HOOK_TAG = 'Hook' local TEMPLATE_FILE_EXT = 'cea' local FORM_CAPTION = 'Auto assemble' local ADD_I2_TEMPLATES = true local I2_MR_SCRIPT_COLOR = Colors.Green local I2_AOB_SCAN_BYTE_MIN = I2CEAASTG_AOB_SCAN_BYTE_MIN or 16 local I2_AOB_SIGNATURE_LENGHT = I2CEAASTG_AOB_SIGNATURE_LENGHT or I2_AOB_SCAN_BYTE_MIN local AOB_START_STRING = '<<<--- AOB Starts Here' local strSignature = strE local testBytes = 0 local byteScanSignatureMinErrorMag = t('Sorry. You must select more then 5 bytes.') local byteScanSignatureWritableErrorMag = t('Error! Your signature is not located in a section of memory with the proper privileges.') local byteScanSignatureNoResultsErrorMag = t('Nothing Found! You need the proper privileges!') local ADD_I2_TEMPLATES_TO_MEMORY_VIEW_POPUP_MENU = ADD_I2_TEMPLATES_TO_MEMORY_VIEW_POPUP_MENU or true local I2_TEMPLATE_MR_SEP = { Description = '--------------------------------------------------------------------------------' .. '-------------------------', Color = Colors.Grey, IsGroupHeader = true, } local I2_TEMPLATE_MR_GROUP_HEADER = '_[ ${HookName} ]_' local I2_TEMPLATE_MR_AOB = { Description = 'aob${HookNameParsed}', Address = 'aob${HookNameParsed}', Color = Colors.Blue, Type = vtByteArray, Aob = { Size = 0, }, ShowAsHex = true, } local I2_TEMPLATE_MR_INJ = { Description = 'inj${HookNameParsed}', Address = 'inj${HookNameParsed}', Color = Colors.Red, Type = vtByteArray, Aob = { Size = 0, }, ShowAsHex = true, } local I2_TEMPLATE_MR_PTR = { Description = 'ptr${HookNameParsed}', Address = 'ptr${HookNameParsed}', Color = Colors.Grey, Type = 'pointer', ShowAsHex = true, } local I2_TEMPLATE_MR_VAL_INT = { Description = '${BaseAddressOffset} - ', Color = Colors.Black, Type = vtDword, ShowAsHex = false, OffsetText = { '${BaseAddressOffset}', }, Address = 'ptr${HookNameParsed}', } local I2_TEMPLATE_MR_VAL_FLT = { Description = '${BaseAddressOffset} - ', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, OffsetText = { '${BaseAddressOffset}', }, Address = 'ptr${HookNameParsed}', } local I2_TEMPLATE_MR_FLT = { Description = 'flt${HookNameParsed}', Address = 'flt${HookNameParsed}', Color = Colors.Fuchsia, Type = vtSingle, ShowAsHex = false, } local I2_TEMPLATE_MR_INT = { Description = 'int${HookNameParsed}', Address = 'int${HookNameParsed}', Color = Colors.Fuchsia, Type = vtDword, ShowAsHex = false, } local I2_TEMPLATE_MR_FLG = { Description = 'flg${HookNameParsed}', Address = 'flg${HookNameParsed}', Color = Colors.Fuchsia, Type = vtByte, ShowAsHex = true, DropDownList = { Text = '00:' .. t('Disabled') .. '\n01:' .. t('Enabled') .. '\n', }, DropDownReadOnly = true, ---- Disallow manual user input DropDownDescriptionOnly = true, ---- Only show the description part DisplayAsDropDownListItem = true, ---- Make the record display values like the dropdownlist } local I2_TEMPLATE_MR_PTR_VAL = { Description = 'ptr${HookNameParsed}', Address = 'ptr${HookNameParsed}', Color = Colors.Grey, Type = 'pointer', ShowAsHex = true, MemoryRecords = { I2_TEMPLATE_MR_VAL_INT, I2_TEMPLATE_MR_VAL_FLT, }, } -- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- I2 Templates ---------------- local I2_TEMPLATE_HEADER = [========[ { Process : ${ProcessName} - ${ModuleBitSize} Module : ${Module} Game Title : ${GameTitle} Game Version : ${GameVersion} CE Version : ${CEVersion} Script Version : 0.0.1 Date : ${Date} Author : ${Author} Name : ${HookNameParsed} ${HookName} } ]========] ---- ---- Table File Enabler ---- local I2_TEMPLATE_TABLE_FILE_ENABLER = [========[ ${Header} {$lua} if syntaxcheck then return end I2CETableCEA.autoAssembleFile('${HookNameParsed}.CEA', memrec) ------------------------------ ENABLE ------------------------------ [ENABLE] ------------------------------ DISABLE ------------------------------ [DISABLE] ]========] local I2_TEMPLATE_TABLE_FILE_ENABLER__MRS_TBL = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, } ---- ---- Cheat Table Framework ---- local I2_TEMPLATE_CHEAT_TABLE_FRAMEWORK = [========[ {$STRICT} //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] ]========] local I2_TEMPLATE_CHEAT_TABLE_FRAMEWORK__MRS_TBL = { { Description = t('New Cheat Table Framework Script') .. ' ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, } ---- ---- Address Injection ---- local I2_TEMPLATE_ADDRESS_INJECTION = [========[ ${Header} {$STRICT} define(address, ${Address}) define(bytes, ${OriginalBytes}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] define(inj${HookNameParsed}, address) assert(inj${HookNameParsed}, bytes) registerSymbol(inj${HookNameParsed}) //// //// ---------- Injection Point ---------- inj${HookNameParsed}: ${InstNOP90S} //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- inj${HookNameParsed}: db bytes unregisterSymbol(inj${HookNameParsed}) ${InjectionInfo} ]========] local I2_TEMPLATE_ADDRESS_INJECTION__MRS_TBL = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, { Description = I2_TEMPLATE_MR_GROUP_HEADER, IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { I2_TEMPLATE_MR_INJ, }, }, } ---- ---- Address Full Injection ---- local I2_TEMPLATE_ADDRESS_FULL_INJECTION = [========[ ${Header} {$STRICT} define(address, ${Address}) define(bytes, ${OriginalBytes}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] define(inj${HookNameParsed}, address) assert(inj${HookNameParsed}, bytes) registerSymbol(inj${HookNameParsed}) alloc(mem${HookNameParsed}, 0x400, address) label(ptr${HookNameParsed}) registerSymbol(ptr${HookNameParsed}) label(n_code) label(o_code) label(exit) label(return) mem${HookNameParsed}: ptr${HookNameParsed}: ${PointerDefault} align 10 CC n_code: // mov [ptr${HookNameParsed}],${BaseAddressRegistry} // mov [${BaseAddressRegistry}${BaseAddressOffset}], o_code: ${OriginalCode} exit: jmp return //// BaseAddressOffset: ${BaseAddressOffset} //// ---------- Injection Point ---------- inj${HookNameParsed}: jmp n_code${NOPS} return: //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- inj${HookNameParsed}: db bytes unregisterSymbol(inj${HookNameParsed}) unregisterSymbol(ptr${HookNameParsed}) dealloc(mem${HookNameParsed}) ${InjectionInfo} ]========] local I2_TEMPLATE_ADDRESS_FULL_INJECTION__MRS_TBL = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, { Description = I2_TEMPLATE_MR_GROUP_HEADER, IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { I2_TEMPLATE_MR_FLG_IS_ASSEMBLED, I2_TEMPLATE_MR_INJ, I2_TEMPLATE_MR_PTR_VAL, }, }, } ---- ---- AOB Injection ---- local I2_TEMPLATE_AOB_INJECTION = [========[ ${Header} {$STRICT} define(address, ${Address}) define(bytes, ${OriginalBytes}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] aobScan${ModuleStr}(aob${HookNameParsed}${ModuleDecl}, ${AOBBytes})${AOBMessage} define(inj${HookNameParsed}, aob${HookNameParsed}${AOBOffset}) assert(inj${HookNameParsed}, bytes) registerSymbol(inj${HookNameParsed}) //// //// ---------- Injection Point ---------- inj${HookNameParsed}: ${InstNOP90S} //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- inj${HookNameParsed}: db bytes unregisterSymbol(inj${HookNameParsed}) ${InjectionInfo} ]========] local I2_TEMPLATE_AOB_INJECTION__MRS_TBL = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, { Description = I2_TEMPLATE_MR_GROUP_HEADER, IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { I2_TEMPLATE_MR_INJ, }, }, } ---- ---- AOB Full Injection ---- local I2_TEMPLATE_AOB_FULL_INJECTION = [========[ ${Header} {$STRICT} define(address, ${Address}) define(bytes, ${OriginalBytes}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] aobScan${ModuleStr}(aob${HookNameParsed}${ModuleDecl}, ${AOBBytes})${AOBMessage} define(inj${HookNameParsed}, aob${HookNameParsed}${AOBOffset}) assert(inj${HookNameParsed}, bytes) registerSymbol(inj${HookNameParsed}) alloc(mem${HookNameParsed}, 0x400, inj${HookNameParsed}) label(ptr${HookNameParsed}) registerSymbol(ptr${HookNameParsed}) label(n_code) label(o_code) label(exit) label(return) mem${HookNameParsed}: ptr${HookNameParsed}: ${PointerDefault} align 10 CC n_code: // mov [ptr${HookNameParsed}],${BaseAddressRegistry} // mov [${BaseAddressRegistry}${BaseAddressOffset}], o_code: ${OriginalCode} exit: jmp return //// //// ---------- Injection Point ---------- inj${HookNameParsed}: jmp n_code${NOPS} return: //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- inj${HookNameParsed}: db bytes unregisterSymbol(inj${HookNameParsed}) unregisterSymbol(ptr${HookNameParsed}) dealloc(mem${HookNameParsed}) ${InjectionInfo} ]========] local I2_TEMPLATE_AOB_FULL_INJECTION__MRS_TBL = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, { Description = I2_TEMPLATE_MR_GROUP_HEADER, IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { I2_TEMPLATE_MR_INJ, I2_TEMPLATE_MR_PTR_VAL, }, }, } ---- ---- AOB Full Injection With Values ---- local I2_TEMPLATE_AOB_FULL_INJECTION_WITH_VALUES = [========[ ${Header} {$STRICT} define(address, ${Address}) define(bytes, ${OriginalBytes}) //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] aobScan${ModuleStr}(aob${HookNameParsed}${ModuleDecl}, ${AOBBytes})${AOBMessage} define(inj${HookNameParsed}, aob${HookNameParsed}${AOBOffset}) assert(inj${HookNameParsed}, bytes) registerSymbol(inj${HookNameParsed}) alloc(mem${HookNameParsed}, 0x400, inj${HookNameParsed}) label(flt${HookNameParsed}) registerSymbol(flt${HookNameParsed}) label(int${HookNameParsed}) registerSymbol(int${HookNameParsed}) label(flg${HookNameParsed}) registerSymbol(flg${HookNameParsed}) label(ptr${HookNameParsed}) registerSymbol(ptr${HookNameParsed}) label(n_code) label(o_code) label(exit) label(return) mem${HookNameParsed}: flt${HookNameParsed}: dd (float)0 int${HookNameParsed}: dd (int)0 flg${HookNameParsed}: db 00 align 10 ptr${HookNameParsed}: ${PointerDefault} align 10 CC n_code: // mov [ptr${HookNameParsed}],${BaseAddressRegistry} // mov [${BaseAddressRegistry}${BaseAddressOffset}], o_code: ${OriginalCode} exit: jmp return //// //// ---------- Injection Point ---------- inj${HookNameParsed}: jmp n_code${NOPS} return: //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] //// //// ---------- Injection Point ---------- inj${HookNameParsed}: db bytes unregisterSymbol(inj${HookNameParsed}) unregisterSymbol(flt${HookNameParsed}) unregisterSymbol(int${HookNameParsed}) unregisterSymbol(flg${HookNameParsed}) unregisterSymbol(ptr${HookNameParsed}) dealloc(mem${HookNameParsed}) ${InjectionInfo} ]========] local I2_TEMPLATE_AOB_FULL_INJECTION_WITH_VALUES__MRS_TBL = { { Description = '${HookName} ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, { Description = I2_TEMPLATE_MR_GROUP_HEADER, IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { I2_TEMPLATE_MR_INJ, I2_TEMPLATE_MR_PTR_VAL, I2_TEMPLATE_MR_FLT, I2_TEMPLATE_MR_INT, I2_TEMPLATE_MR_FLG, }, -- AddValue = { -- ValueStr = '(int)100', -- ValueType = vtQword, -- AddFlag = false, -- AsHex = false, -- }, -- AddValues = { -- { -- ValueStr = '(float)100', -- ValueType = vtSingle, -- AddFlag = false, -- AsHex = false, -- }, -- { -- ValueStr = '(int)100', -- ValueType = vtDword, -- AddFlag = true, -- AsHex = true, -- }, -- }, }, } ---- ---- Create Thread ---- local I2_TEMPLATE_CREATE_THREAD = [========[ ${Header} {$STRICT} //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] alloc(memThread, 0x400) label(threadStart) label(threadEnd) memThread: threadStart: // body threadEnd: ret createThread(threadStart) //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] dealloc(memThread) ]========] local I2_TEMPLATE_CREATE_THREAD__MRS_TBL = { { Description = t('New Create Thread Script') .. ' ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, } ---- ---- CEA Lua Base ---- local I2_TEMPLATE_CEA_LUA = [========[ {$STRICT} {$lua} if syntaxcheck then return end ------------------------------ ENABLE ------------------------------ [ENABLE] if syntaxcheck then return end ------------------------------ DISABLE ------------------------------ [DISABLE] if syntaxcheck then return end ]========] local I2_TEMPLATE_CEA_LUA__MRS_TBL = { { Description = t('New CEA Lua Script') .. ' ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, }, } ---- ---- I2_TEMPLATE_TEST_VALUES ---- local I2_TEMPLATE_TEST_VALUES = [========[ {$STRICT} //// //// ------------------------------ ENABLE ------------------------------ [ENABLE] alloc(memTestValues, 0x400) registerSymbol(memTestValues) //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] dealloc(memTestValues) ]========] local I2_TEMPLATE_TEST_VALUES__MRS_TBL = { { Description = 'memTestValues ()->', Type = vtAutoAssembler, Color = I2_MR_SCRIPT_COLOR, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues', Address = 'memTestValues', Color = Colors.Grey, Type = vtByteArray, Aob = { Size = 0, }, ShowAsHex = true, }, { Description = '_[ Doubles ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues+0', Address = 'memTestValues+0', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+8', Address = 'memTestValues+8', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+10', Address = 'memTestValues+10', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+18', Address = 'memTestValues+18', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+20', Address = 'memTestValues+20', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+28', Address = 'memTestValues+28', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+30', Address = 'memTestValues+30', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+38', Address = 'memTestValues+38', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+40', Address = 'memTestValues+40', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, { Description = 'memTestValues+48', Address = 'memTestValues+58', Color = Colors.Black, Type = vtDouble, ShowAsHex = false, }, }, }, { Description = '_[ QWords ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues+0', Address = 'memTestValues+0', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+8', Address = 'memTestValues+8', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+10', Address = 'memTestValues+10', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+18', Address = 'memTestValues+18', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+20', Address = 'memTestValues+20', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+28', Address = 'memTestValues+28', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+30', Address = 'memTestValues+30', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+38', Address = 'memTestValues+38', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+40', Address = 'memTestValues+40', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, { Description = 'memTestValues+48', Address = 'memTestValues+48', Color = Colors.Black, Type = vtQword, ShowAsHex = false, }, }, }, { Description = '_[ Singles ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues+0', Address = 'memTestValues+0', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+4', Address = 'memTestValues+4', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+8', Address = 'memTestValues+8', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+C', Address = 'memTestValues+C', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+10', Address = 'memTestValues+10', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+14', Address = 'memTestValues+14', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+18', Address = 'memTestValues+18', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+1C', Address = 'memTestValues+1C', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+20', Address = 'memTestValues+20', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, { Description = 'memTestValues+24', Address = 'memTestValues+24', Color = Colors.Black, Type = vtSingle, ShowAsHex = false, }, }, }, { Description = '_[ DWords ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues+0', Address = 'memTestValues+0', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+4', Address = 'memTestValues+4', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+8', Address = 'memTestValues+8', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+C', Address = 'memTestValues+C', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+10', Address = 'memTestValues+10', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+14', Address = 'memTestValues+14', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+18', Address = 'memTestValues+18', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+1C', Address = 'memTestValues+1C', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+20', Address = 'memTestValues+20', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, { Description = 'memTestValues+24', Address = 'memTestValues+24', Color = Colors.Black, Type = vtDword, ShowAsHex = false, }, }, }, { Description = '_[ Words ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues+0', Address = 'memTestValues+0', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+2', Address = 'memTestValues+2', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+4', Address = 'memTestValues+4', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+6', Address = 'memTestValues+6', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+8', Address = 'memTestValues+8', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+A', Address = 'memTestValues+A', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+C', Address = 'memTestValues+C', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+E', Address = 'memTestValues+E', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+10', Address = 'memTestValues+10', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, { Description = 'memTestValues+12', Address = 'memTestValues+12', Color = Colors.Black, Type = vtWord, ShowAsHex = false, }, }, }, { Description = '_[ Bytes ]_', IsGroupHeader = true, options = "[moHideChildren]", MemoryRecords = { { Description = 'memTestValues+0', Address = 'memTestValues+0', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+1', Address = 'memTestValues+1', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+2', Address = 'memTestValues+2', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+3', Address = 'memTestValues+3', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+4', Address = 'memTestValues+4', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+5', Address = 'memTestValues+5', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+6', Address = 'memTestValues+6', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+7', Address = 'memTestValues+7', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+8', Address = 'memTestValues+8', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, { Description = 'memTestValues+9', Address = 'memTestValues+9', Color = Colors.Black, Type = vtByte, ShowAsHex = false, }, }, }, }, }, } ---- ---- ---- ---- I2 Templates ---- local I2_TEMPLATES = { { Name = 'I2CEA_Table_TableSep', DisplayString = t('Table Separator'), TemplateString = strE, MemoryRecordsIncludeScript = true, MemoryRecords = { I2_TEMPLATE_MR_SEP, I2_TEMPLATE_MR_SEP, I2_TEMPLATE_MR_SEP, I2_TEMPLATE_MR_SEP, I2_TEMPLATE_MR_SEP, }, AskToAddToTable = false, AddToMainOnly = true, }, { Name = 'I2CEA_TestValues', DisplayString = t('Test Values'), TemplateString = I2_TEMPLATE_TEST_VALUES, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_TEST_VALUES__MRS_TBL, AskToAddToTable = false, AddToMainOnly = true, options = "[moHideChildren]", }, { Name = 'I2CEA_Table_TableSepSEPERATOR', DisplayString = '-', AddToMainOnly = true, }, ---- SEPERATOR { Name = 'I2CEA_CheatTableFrameworkCode', DisplayString = t('Cheat table framework code'), TemplateString = I2_TEMPLATE_CHEAT_TABLE_FRAMEWORK, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_CHEAT_TABLE_FRAMEWORK__MRS_TBL, Shortcut = 'ctrl+shift+0', AskToAddToTable = false, options = "[moHideChildren]", }, { Name = 'I2CEA_Lua_CEALuaBase', DisplayString = t('CEA Lua Base'), TemplateString = I2_TEMPLATE_CEA_LUA, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_CEA_LUA__MRS_TBL, Shortcut = 'ctrl+shift+1', AskToAddToTable = false, options = "[moHideChildren]", }, { Name = 'I2CEA_CreateThread', DisplayString = t('Create Thread'), TemplateString = I2_TEMPLATE_CREATE_THREAD, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_CREATE_THREAD__MRS_TBL, Shortcut = 'ctrl+shift+2', AskToAddToTable = false, options = "[moHideChildren]", }, { Name = 'I2CEA_Lua_TableFileEnabler', DisplayString = t('Table File Enabler'), GetHookName = true, HookTag = HOOK_TAG, AppendHookTag = true, TemplateString = I2_TEMPLATE_TABLE_FILE_ENABLER, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_TABLE_FILE_ENABLER__MRS_TBL, Shortcut = 'ctrl+shift+3', AskToAddToTable = false, options = "[moHideChildren]", }, '-----', ---- SEPERATOR { Name = 'I2CEA_AddressInjection', DisplayString = t('Address Injection'), GetAddress = true, GetHookName = true, HookTag = HOOK_TAG, AppendHookTag = true, TemplateString = I2_TEMPLATE_ADDRESS_INJECTION, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_ADDRESS_INJECTION__MRS_TBL, Shortcut = 'alt+1', AskToAddToTable = false, options = "[moHideChildren]", }, { Name = 'I2CEA_AddressFullInjection', DisplayString = t('Address Full Injection'), GetAddress = true, GetHookName = true, HookTag = HOOK_TAG, AppendHookTag = true, IsFullHook = true, TemplateString = I2_TEMPLATE_ADDRESS_FULL_INJECTION, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_ADDRESS_FULL_INJECTION__MRS_TBL, Shortcut = 'alt+2', AskToAddToTable = false, options = "[moHideChildren]", }, '-----', ---- SEPERATOR { Name = 'I2CEA_AOBInjection', DisplayString = t('AOB Injection'), GetAddress = true, GetHookName = true, HookTag = HOOK_TAG, AppendHookTag = true, GetAOBSignature = true, TemplateString = I2_TEMPLATE_AOB_INJECTION, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_AOB_INJECTION__MRS_TBL, Shortcut = 'ctrl+shift+5', AskToAddToTable = false, options = "[moHideChildren]", }, { Name = 'I2CEA_AOBFullInjection', DisplayString = t('AOB Full Injection'), GetAddress = true, GetHookName = true, HookTag = HOOK_TAG, AppendHookTag = true, GetAOBSignature = true, IsFullHook = true, TemplateString = I2_TEMPLATE_AOB_FULL_INJECTION, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_AOB_FULL_INJECTION__MRS_TBL, Shortcut = 'ctrl+shift+6', AskToAddToTable = false, options = "[moHideChildren]", }, { Name = 'I2CEA_AOBFullInjectionWithValues', DisplayString = t('AOB Full Injection with Values'), GetAddress = true, GetHookName = true, HookTag = HOOK_TAG, AppendHookTag = true, GetAOBSignature = true, IsFullHook = true, TemplateString = I2_TEMPLATE_AOB_FULL_INJECTION_WITH_VALUES, MemoryRecordsIncludeScript = true, MemoryRecords = I2_TEMPLATE_AOB_FULL_INJECTION_WITH_VALUES__MRS_TBL, Shortcut = 'ctrl+shift+7', AskToAddToTable = false, options = "[moHideChildren]", }, } ---------------- ---------------- I2 Templates ---------------- ---------------- ---------------- ---------------- ---------------- -- -- ---------------- ---------------- ---------------- ---------------- ---------------- Defaults ---------------- ---- I2CEAASTG_OPCODE_PADDING_RIGHT local default_OpcodePaddingRight = 35 ---- I2CEAASTG_BYTES_PADDING_RIGHT local default_BytesPaddingRight = 26 ---- I2CEAASTG_TEMPLATE_MARKER_LINE local default_TemplateMarkerLine = '//// ------------------------------------------------------------' .. '----------------------' ---- I2_TEMPLATE_HEADER local default_TemplateHeader = I2_TEMPLATE_HEADER ---- I2CEAASTG_DATE_FORMAT local default_DateFormat = '%x' ---- Has Tables Overrides: ---- HookTag - I2CEAASTG_HOOK_TAG local default_HookTag = HOOK_TAG ---- AppendHookTag - I2CEAASTG_APPEND_HOOK_TAG local default_AppendHookTag = true ---- InjectionInfoCommentType - I2CEAASTG_INJ_INFO_COMMENT_TYPE local default_InjectionInfoCommentType = CommentTypes.Block ---- LineComment - I2CEAASTG_LINE_COMMENT local default_LineComment = '//// ' ---- LineEnd - I2CEAASTG_LINE_END local default_LineEnd = '\n' ---- NopPaddingLeft - I2CEAASTG_NOP_PADDING_LEFT local default_NopPaddingLeft = '\t' ---- OriginalCodePaddingLeft - I2CEAASTG_ORIGINAL_CODE_PADDING_LEFT local default_OriginalCodePaddingLeft = '\t\t' ---- FixInputData - I2CEAASTG_FIX_INPUT_DATA local default_FixInputData = true ---------------- ---------------- Defaults ---------------- ---------------- ---------------- ---------------- -- -- ---------------- ---------------- ---------------- ---------------- ---------------- Settings ---------------- ---- I2CEAASTG_AUTO_LOAD local AutoLoad = true ---- I2CEAASTG_DATE_FORMAT local DateFormat = default_DateFormat ---- I2CEAASTG_NOP_ASM local NopASM = 'nop' ---- I2CEAASTG_TEMPLATES_DIRECTORY local TemplatesDirectory = getPath(os.getenv('HOMEPATH') or os.getenv('HOME'), t('My Cheat Tables'), '~I2Templates') ---- I2CEAASTG_ADD_MAIN_SEPERATOR local AddMainSeperator = I2CEAASTG_ADD_MAIN_SEPERATOR ---- I2CEAASTG_ADD_AA_MAIN_SEPERATOR local AddMainAASeperator = I2CEAASTG_ADD_AA_MAIN_SEPERATOR ---- I2CEAASTG_PLACE_HOLDER_KEY local PlaceHolderKey = t('PlaceHolder_') local UserNameEnvKey = 'CE_USERNAME' ---- CE_USER_NAME local UserName = os.getenv(UserNameEnvKey) or os.getenv('USERNAME') or 'USERNAME' local InjectionInfoCount = 20 ---- I2CEAASTG_TEMPLATE_MARKER_LINE local TemplateMarkerLine = default_TemplateMarkerLine ---- I2CEAASTG_HEADER local TemplateHeader = default_TemplateHeader ---- ADD_I2_TEMPLATES local AddI2Templates = ADD_I2_TEMPLATES or false local AOBSignaturePrivileges = nil -- '+X-C-W' local AOBScanByteLengthMin = I2_AOB_SCAN_BYTE_MIN or 16 local AOBSignatureLength = I2_AOB_SIGNATURE_LENGHT or AOBScanByteLengthMin local UseMemoryViewFormSelectionForAOBSignature = true local MemoryViewFormByteSignatureScanInfoDescription = 'Get byte scan signature info' local MemoryViewFormByteSignatureScanInfoShortcut = 'Ctrl+Shift+B' local BringCheatEngineToFrontOnCreateMemoryRecords = true local AddTemplatesToMemoryViewPopupMenu = ADD_I2_TEMPLATES_TO_MEMORY_VIEW_POPUP_MENU local MemoryViewFormTemplateMenuCaption = t('Templates (AA)') ---------------- ---------------- Settings ---------------- ---------------- ---------------- ---------------- -- ---- ---- ---- Class / Base table ---- I2CEAutoAssemblerScriptTemplates = { Name = NAME, ClassName = CLASS_NAME, Version = VERSION, Author = AUTHOR, License = LICENSE, Colors = Colors, CommentTypes = CommentTypes, } -------- -------- -------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- Templates ---------------- I2CEAutoAssemblerScriptTemplates.Templates = { ---- ---- Set "AddI2Templates" to "false" to disable adding of I2 templates ---- -- ---- ---- Here are some example templates: -- '-----', ---- SEPERATOR (any string) -- { -- DisplayString = 'Address Injection', -- GetAddress = true, -- GetHookName = true, -- HookTag = 'Cheat', -- AppendHookTag = true, -- TemplateString = I2_TEMPLATE_ADDRESS_INJECTION, -- MemoryRecordsIncludeScript = true, -- MemoryRecords = { -- { -- Description = '${HookName} ()->', -- Type = vtAutoAssembler, -- Color = Colors.Teal, -- }, -- { -- Description = '_[== ${HookName} ==]_', -- IsGroupHeader = true, -- MemoryRecords = { -- { -- Description = 'inj${HookNameParsed}', -- Address = 'inj${HookNameParsed}', -- Color = Colors.Red, -- Type = vtByteArray, -- Aob = { -- Size = 0, -- }, -- ShowAsHex = true, -- }, -- }, -- }, -- }, -- }, -- { -- DisplayString = 'Address Full Injection', -- GetAddress = true, -- GetHookName = true, -- HookTag = 'Cheat', -- AppendHookTag = true, -- IsFullHook = true, -- TemplateString = I2_TEMPLATE_ADDRESS_FULL_INJECTION, -- MemoryRecordsIncludeScript = true, -- MemoryRecords = { -- { -- Description = '${HookName} ()->', -- Type = vtAutoAssembler, -- Color = Colors.Teal, -- }, -- { -- Description = '_[== ${HookName} ==]_', -- IsGroupHeader = true, -- MemoryRecords = { -- { -- Description = 'flg${HookNameParsed}IsAssembled', -- Address = 'flg${HookNameParsed}IsAssembled', -- Color = Colors.Olive, -- Type = vtByte, -- DropDownList = { -- Text = '0:Not Assembled\n1:Assembled\n', -- }, -- DropDownReadOnly = true, ---- Disallow manual user input -- DropDownDescriptionOnly = true, ---- Only show the description part -- DisplayAsDropDownListItem = true, ---- Make the record display values like the dropdownlist -- }, -- { -- Description = 'inj${HookNameParsed}', -- Address = 'inj${HookNameParsed}', -- Color = Colors.Red, -- Type = vtByteArray, -- Aob = { -- Size = 0, -- }, -- ShowAsHex = true, -- }, -- { -- Description = 'mem${HookNameParsed}', -- Address = 'mem${HookNameParsed}', -- Color = Colors.Green, -- Type = vtByteArray, -- Aob = { -- Size = 0, -- }, -- ShowAsHex = true, -- MemoryRecords = { -- { -- Description = 'mrk${HookNameParsed}MemSTART', -- Address = 'mrk${HookNameParsed}MemSTART', -- Color = Colors.Green, -- Type = vtByteArray, -- Aob = { -- Size = 0, -- }, -- ShowAsHex = true, -- }, -- { -- Description = 'mrk${HookNameParsed}MemEND', -- Address = 'mrk${HookNameParsed}MemEND', -- Color = Colors.Green, -- Type = vtByteArray, -- Aob = { -- Size = 0, -- }, -- ShowAsHex = true, -- }, -- }, -- }, -- { -- Description = '------------------------------------------------------------', -- Color = Colors.Silver, -- IsGroupHeader = true, -- }, -- { -- Description = 'ptr${HookNameParsed}', -- Address = 'ptr${HookNameParsed}', -- Color = Colors.Grey, -- Type = 'pointer', -- ShowAsHex = true, -- }, -- { -- Description = '${HookNameParsedBase} ()->', -- Type = vtAutoAssembler, -- Color = Colors.Teal, -- Script = "[ENABLE]\n{$lua}\nprint('I Have The Power!!')\n[DISABLE]\n{$lua}\nprint('Op. Its gone.')\n", -- }, -- }, -- }, -- }, -- }, -- '-----', ---- SEPERATOR -- { -- DisplayString = 'AOB Injection', -- GetAddress = true, -- GetHookName = true, -- HookTag = 'Hack', -- AppendHookTag = true, -- GetAOBSignature = true, -- TemplateFile = [=[E:\Documents\My Cheat Tables\~CE-Templates\AOB_Injection-template.cea]=], -- MemoryRecordsIncludeScript = true, -- MemoryRecords = I2_TEMPLATE_AOB_INJECTION__MRS_TBL, -- }, -- { -- DisplayString = 'AOB Full Injection', -- GetAddress = true, -- GetHookName = true, -- HookTag = 'Hack', -- AppendHookTag = true, -- IsFullHook = true, -- GetAOBSignature = true, -- TemplateString = I2_TEMPLATE_AOB_FULL_INJECTION, -- MemoryRecordsIncludeScript = true, -- MemoryRecords = I2_TEMPLATE_AOB_FULL_INJECTION__MRS_TBL, -- }, } ---------------- ---------------- Templates ---------------- ---------------- ---------------- ---------------- ---------------- -------- -------- -------- -- -- ---- ---- Add I2 Templates ---- if AddI2Templates and type(I2_TEMPLATES) == 'table' then for i = 1, #I2_TEMPLATES do table.insert(I2CEAutoAssemblerScriptTemplates.Templates, i, I2_TEMPLATES[i]) end end -- -------- -------- -------- Helpers -------- local function getFileVersionStr(path) if path == nil then return end local i, vt = getFileVersion(path) if i and vt then return format('%s.%s.%s.%s', vt.major, vt.minor, vt.release, vt.build) end return nil end function getGameVersionStr() local modules = enumModules() if modules == nil or modules[1] == nil then return end return getFileVersionStr(modules[1].PathToFile) end local function getPointerSize() aasStr = [====[ globalAlloc(memPointerTest, 0x8) memPointerTest: db FF FF FF FF FF FF FF FF ]====] local assembled = autoAssemble(aasStr) if assembled then local p1 = readQword('memPointerTest') local p2 = readPointer('memPointerTest') if p1 == p2 then return 0x8 else return 0x4 end end return nil end local function getPointerSizeStrs() local pointerSize = getPointerSize() local pointerSizeStr = format('0x%X', pointerSize or 0x8) local pointerFtmStr = '%016X' local pointerWordSize = 'dq' local pointerDefaultStr = 'dq 0' if pointerSize == 0x4 then pointerFtmStr = '%08X' pointerWordSize = 'dd' pointerDefaultStr = 'dd 0' end return pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr end local function interp(s, tbl) if s == nil then return end return (s:gsub('($%b{})', function(w) return tbl[w:sub(3, -2)] or w end)) end local function titleCase(s, s_char) if type(s) ~= 'string' then return nil end local patt = '%S+' -- match every thing but spaces. local char = ' ' if s_char == '_' then patt = '[^_]+' -- match every thing but underscores. char = '_' elseif s_char == '.' then patt = '[^\\.]+' -- match every thing but periods. char = '.' elseif s_char == 'p' then patt = '%P+' -- match every thing but punctuation. char = '.' end local r = strE for w in s:gfind(patt) do local f = w:sub(1, 1) if #r > 0 then r = r..char end r = r..f:upper()..w:sub(2):lower() end if #r < 1 then r = s end return r end local function padR(str, len, char) if str == nil or len == nil then return str end if char == nil then char = ' ' end return str .. string.rep(char, len - #str) end local function getModuleFromAddress(address) if address == 0 then return nil end if type(address) == 'string' then address = tonumber(address, 16) end if address == nil then return nil end local modulesTable = enumModules() local size = 0 for i, v in pairs(modulesTable) do size = getModuleSize(v.Name) if size ~= nil then if address >= v.Address and address <= v.Address + size then return v.Name end end end return nil end local function getModuleAndOffsetFromAddress(address) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() if address == 0 then return format(pointerFtmStr, address) end if type(address) == 'string' then address = tonumber(address, 16) end if address == nil then return address end local addModule = getModuleFromAddress() if addModule then return format('%s+%X', addModule, (address - v.Address)) end return getNameFromAddress(address) end -------- -------- Helpers -------- -------- -- -- -------- -------- -------- Functions -------- local function parseBytesStr(str) str = str:gsub(' ', strE) local rtn = strE for i = 1, #str, 2 do rtn = rtn .. ' ' .. str:sub(i, i) .. str:sub(i + 1, i + 1) end return rtn:sub(2) end local function parseDisassembledString(str) if not str then return end local extraField, opcode, bytes, address = splitDisassembledString(str) opcode = padR(opcode, I2CEAASTG_OPCODE_PADDING_RIGHT or default_OpcodePaddingRight) bytes = padR(bytes, I2CEAASTG_BYTES_PADDING_RIGHT or default_BytesPaddingRight) local addressStr = getModuleAndOffsetFromAddress(address) or address return format('%s: %s - %s%s', addressStr, bytes or strE, opcode or strE, extraField or strE) end local function getMenuItemForm(menuItem) local form = nil local item = menuItem for i = 0, 100 do if item.Caption == FORM_CAPTION or item.Caption == t(FORM_CAPTION) then Logger.debugf('getMenuItemForm: form found, steps: %s', i) return item elseif item.Owner == nil then return else item = item.Owner end end end -------- -------- Functions -------- -------- -- -- -------- -------- -------- -------- Byte Scan Signature -------- local function getBytesForAOB(startAddress, stop) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() if type(startAddress) == 'number' then Logger.debugf('getBytesForAOB: getting bytes for: ' .. pointerFtmStr .. ', ' .. pointerFtmStr .. ', ' .. pointerFtmStr, startAddress, length or 0, stop or 0) else Logger.debugf('getBytesForAOB: getting bytes for: %s, ' .. pointerFtmStr .. ', ' .. pointerFtmStr, startAddress, length or 0, stop or 0) end local address = startAddress local length = stop + getInstructionSize(stop) - address local str = strE for i = 1, length do local sizeInstruction = getInstructionSize(address) local _, _, bytes = splitDisassembledString(disassemble(address)) local fstBt, othBt = string.match(bytes, '^%x+'), string.match(bytes, ' .+$') if testBytes then if fstBt then if othBt ~= nil then othBt = string.gsub(string.gsub(othBt, '%s', strE), '%x', 'x') str = str .. fstBt .. othBt else str = str .. string.gsub(fstBt, '%x', 'x') end end else str = str..string.gsub(bytes, '%s', strE) end if address == stop then address = address + sizeInstruction break end address = address + sizeInstruction end Logger.debugf('getBytesForAOB: generated bytes : %s', str) return str end local function getByteScanSignature(address) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() local sigMin = AOBSignatureLength local address = address local stop = address + sigMin local length = stop + getInstructionSize(stop) - address if UseMemoryViewFormSelectionForAOBSignature then address = math.min(dv_address1, dv_address2) stop = math.max(dv_address1, dv_address2) length = stop + getInstructionSize(stop) - address end Logger.debugf('getByteScanSignature: getting byte scan signature for: ' .. pointerFtmStr .. ', ' .. pointerFtmStr, address, stop or 0) local bytestring = readBytes(address, length, true) local strSignature = strE local result local count = -1 local ind = ' ' a2 = getPreviousOpcode(address) a1 = getPreviousOpcode(a2) a4 = address + getInstructionSize(address) a5 = a4 + getInstructionSize(a4) for i = 1, length do strSignature = strSignature .. format('%02X ', bytestring[i]) end strSignature = getBytesForAOB(address, stop) strSignature = string.gsub(strSignature, "%s", strE) if strSignature ~= nil or strSignature ~= strE then local bl = #strSignature / 2 if bl < (AOBScanByteLengthMin or 16) then local msg = t('You have selected').. ' ' .. format('%d', bl) .. ' ' .. t('bytes, this could take a long time.') .. '\n\n' .. t('Are you sure you want to continue with the scan?.') .. '\n\n' .. strSignature local mr = messageDialog(msg, mtConfirmation, mbYes, mbNo, mbCancel) if mr ~= mrYes then Logger.debug('getByteScanSignature: user canceled.') return nil, -1 end end if AOBSignaturePrivileges then Logger.debugf('getByteScanSignature: scanning for (with "%s"): %s', AOBSignaturePrivileges, strSignature) result = AOBScan(strSignature, AOBSignaturePrivileges) else Logger.debugf('getByteScanSignature: scanning for: %s', strSignature) result = AOBScan(strSignature) end if result ~= nil then count = result.Count result.destroy() Logger.debugf('getByteScanSignature: scan found: %d', count) end if count == -1 then local msg = ind .. byteScanSignatureWritableErrorMag .. ' ' .. byteScanSignatureNoResultsErrorMag if AOBSignaturePrivileges then msg = msg .. ' "' .. AOBSignaturePrivileges .. '"' else msg = msg .. ' no privileges set (see: "AOBSignaturePrivileges").' end Logger.warn(msg) end end Logger.debugf('getByteScanSignature: generated byte scan signature: %s', strSignature) return strSignature, count end -------- -------- Byte Scan Signature -------- -------- -------- -- -- -------- -------- -------- -------- -------- local function getSignatureInfoAndPrint() local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() local le = '\r\n' local str = '--- ' .. t('Start') .. ' ---' .. le local address = math.min(dv_address1, dv_address2) local stop = math.max(dv_address1, dv_address2) local length = stop + getInstructionSize(stop) - address Logger.debugf('OnItemMenuGetSignatureInfoClick: getting byte scan signature for: %X, %X', address, stop) local bytestring = readBytes(address, length, true) local strSignature = strE local result = nil local count = -1 local gameTitle = GAME_TITLE or 'GAME_TITLE' ---- To be set in tables lua file local gameVersion = GAME_VERSION or 'GAME_VERSION' ---- To be set in tables lua file local processAddress = 0 local processAddressStr = strE local ind = ' ' if process then gameTitle = GAME_TITLE or process:gsub('.exe', strE) or 'GAME_TITLE' ---- To be set in tables lua file gameVersion = GAME_VERSION or getGameVersionStr() or 'GAME_VERSION' ---- To be set in tables lua file processAddress = getAddress(process) or 0 processAddressStr = format(pointerFtmStr, processAddress) str = str .. t('Game Title') .. ': ' .. gameTitle .. le str = str .. t('Game Version') .. ': ' .. gameVersion .. le str = str .. t('Process') .. ': ' .. process .. le str = str .. t('Process Address') .. ': ' .. processAddressStr .. le str = str .. strE .. le end str = str .. t('Start Address') .. ':' .. le str = str .. ind .. getModuleAndOffsetFromAddress(address) .. le str = str .. ind .. format(pointerFtmStr, address) .. le str = str .. t('End Address') .. ':' .. le str = str .. ind .. getModuleAndOffsetFromAddress(stop) .. le str = str .. ind .. format(pointerFtmStr, stop) .. le str = str .. strE .. le a2 = getPreviousOpcode(address) a1 = getPreviousOpcode(a2) a4 = address + getInstructionSize(address) a5 = a4 + getInstructionSize(a4) str = str .. strE .. le for i = 1, length do strSignature = strSignature .. format('%02X ', bytestring[i]) end strSignature = getBytesForAOB(address, stop) strSignature = string.gsub(strSignature, "%s", strE) if strSignature ~= nil or strSignature ~= strE then local bl = #strSignature / 2 if bl < (AOBScanByteLengthMin or 16) then local msg = t('You have selected').. ' ' .. format('%d', bl) .. ' ' .. t('bytes, this could take a long time.') .. '\n' .. t('Are you sure you want to continue with the scan?.') .. '\n\n' .. t('Scan pattern') .. ': ' .. strSignature .. '\n' .. t('Scan length') .. ': ' .. format('%d', bl) local mr = messageDialog(msg, mtConfirmation, mbYes, mbNo, mbCancel) Logger.debugf('OnItemMenuGetSignatureInfoClick: user selected too few bytes: %d', bl) if mr ~= mrYes then str = str .. t('Scan pattern') .. ': ' .. strSignature .. le str = str .. t('Scan length') .. ': ' .. format('%d', bl) .. le str = str .. t('Scan canceled by user.') .. le str = str .. strE .. le str = str .. '--- ' .. t('End') .. ' ---' .. le str = str .. strE .. le return nil, -1 end end str = str .. t('Test byte signature') .. ':' .. le str = str .. strSignature .. le str = str .. strE .. le if AOBSignaturePrivileges then Logger.debugf('OnItemMenuGetSignatureInfoClick: scanning for (with "%s"): %s', AOBSignaturePrivileges, strSignature) result = AOBScan(strSignature, AOBSignaturePrivileges) else Logger.debugf('OnItemMenuGetSignatureInfoClick: scanning for: %s', strSignature) result = AOBScan(strSignature) end if result == nil then str = str .. ind .. byteScanSignatureWritableErrorMag .. ' ' .. byteScanSignatureNoResultsErrorMag .. ' "' .. tostring(AOBSignaturePrivileges) .. '"' .. le else count = result.Count result.destroy() Logger.debugf('OnItemMenuGetSignatureInfoClick: scan found: %d', count) str = str .. strE .. le if (count == 1) then str = str .. ind .. t('Test byte signature is unique.') .. le else str = str .. ind .. format( t('Found') .. ': %s', count) .. le str = str .. ind .. t('Test byte signature is NOT unique.') .. le end str = str .. strE .. le local msgTbl = { [1] = t('Remember to donate to Dark Byte if you want Cheat Engine to always be here.'), [3] = t('- Your Mother was a Hamster, and your Father smelt of Elderberries!'), [7] = t('Remember to donate to Dark Byte if you love Cheat Engine.'), [13] = t('A: What manner of man are you that can summon up fire without flint or tinder?') .. '\r\n' .. t('T: I... am an enchanter.') .. '\r\n' .. t('A: By what name are you known?') .. '\r\n' .. t('T: There are some who call me... "Tim"?') .. '\r\n' .. t('A: Greetings, Tim the Enchanter.'), [19] = t('- Consult the Book of Armaments!'), [26] = t("- Just Because you know how to use a saw and hammer doesn't make you a carpenter."), [39] = t("- Do what now?"), [45] = t('- Old crone! Is there anywhere in this town where we could buy a shrubbery?'), [52] = t('- Code Happy, Code Freely, Be Awesome.'), [65] = t('- Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony.'), [78] = t("- It's not a question of where he grips it! It's a simple question of weight ratios! A five ounce bird could not carry a one pound coconut."), [98] = t('Remember to donate to Dark Byte, because this stupid thing said to.'), [99] = t("- Oh, what sad times are these when passing ruffians can say 'ni' at will to old ladies. There is a pestilence upon this land. Nothing is sacred. Even those who arrange and design shrubberies are under considerable economic stress at this period in history."), [100] = t('- And Saint Attila raised the hand grenade up on high, saying, "O Lord, bless this thy hand grenade, that with it thou mayst blow thine enemies to tiny bits, in thy mercy." And the Lord did grin. And the people did feast upon the lambs and sloths, and carp and anchovies, and orangutans and breakfast cereals, and fruit-bats and large chu...'), } math.randomseed(os.time()) local rn = math.random(1, 100) if msgTbl[rn] ~= nil and msgTbl[rn] ~= strE then str = str .. ind .. msgTbl[rn] .. le .. le end end end Logger.debugf('OnItemMenuGetSignatureInfoClick: generated byte scan signature: %s', strSignature) str = str .. '--- ' .. t('End') .. ' ---' print(str) end local function getSignatureInfoAndPrintThreaded(thread) thread.terminate() thread.freeOnTerminate(true) return getSignatureInfoAndPrint() end local function OnItemMenuGetSignatureInfoClick(sender) local thread = createThread(getSignatureInfoAndPrintThreaded) end -------- -------- -------- -------- -------- -- local function showHookSetupForm(addressStr, address, generateAob) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() if type(address) == 'number' then address = format(pointerSizeStr, address) end Logger.debugf('showHookSetupForm: at address: %s, %s', addressStr or tostring(addressStr), address) local fW = 400 local row = 0 local lPush = 90 local sX = fW - (lPush + 10) local sY = 23 local pX = 3 local pY = 3 local bW = 75 local bH = 24 local padF = 5 local pad1 = 3 local pad2 = 1 local frmHookSetup = createForm(false) frmHookSetup.centerScreen() frmHookSetup.setSize(fW, fH) frmHookSetup.Name = 'frmHookSetup' frmHookSetup.Caption = t('Hook Setup') local lblHookAddress = createLabel(frmHookSetup) lblHookAddress.Name = 'lblHookAddress' lblHookAddress.setPosition(pX, pY + sY * row + pad1) lblHookAddress.Caption = t('Address') .. ':' local edHookAddress = createEdit(frmHookSetup) edHookAddress.Name ='edHookAddress' edHookAddress.setSize(sX, sY) edHookAddress.setPosition(pX + lPush, pY + sY * row + pad2) edHookAddress.Text = addressStr or address row = row + 1 local lblHookName = createLabel(frmHookSetup) lblHookName.Name = 'lblHookName' lblHookName.setPosition(pX, pY + sY * row + pad1) lblHookName.Caption = t('Hook Name') .. ':' local edHookName = createEdit(frmHookSetup) edHookName.Name = 'edHookName' edHookName.setSize(sX, sY) edHookName.setPosition(pX + lPush, pY + sY * row + pad2) edHookName.Text = '' row = row + 1 local cbxGenerateAob = createCheckBox(frmHookSetup) cbxGenerateAob.Name = 'cbxGenerateAob' cbxGenerateAob.setSize(sX, sY) cbxGenerateAob.setPosition(pX + lPush, pY + sY * row + pad2) cbxGenerateAob.Caption = t('Generate AOB') cbxGenerateAob.Checked = generateAob cbxGenerateAob.Visible = generateAob if cbxGenerateAob.Visible then row = row + 1 end local btnOk = createButton(frmHookSetup) btnOk.Name = 'btnOk' btnOk.Caption = t('OK') btnOk.setSize(bW, bH) btnOk.setPosition((fW / 3) - (bW / 2), pY + sY * row + pad2) btnOk.ModalResult = mrOK btnOk.Default = true local btnCancel = createButton(frmHookSetup) btnCancel.Name = 'btnCancel' btnCancel.Caption = t('Cancel') btnCancel.setSize(bW, bH) btnCancel.setPosition(((fW / 3) * 2) - (bW / 2), pY + sY * row + pad2) btnCancel.ModalResult = mrCancel btnCancel.Cancel = true row = row + 1 frmHookSetup.setSize(fW, pY + sY * row + padF) local mr = frmHookSetup.showModal() Logger.debugf('showHookSetupForm: modal form closed: %d, %s, %s, %s', mr, edHookName.Text, edHookAddress.Text, cbxGenerateAob.Checked) return mr, edHookName.Text, edHookAddress.Text, cbxGenerateAob.Checked end -- ---------------- ---------------- ---------------- ---------------- ---------------- Generate ---------------- function I2CEAutoAssemblerScriptTemplates.generate(menuItem, templateTbl) Logger.debugf('generate: generating template: "%s".', templateTbl.Name or templateTbl.DisplayString) local pointerSize, pointerSizeStr, pointerFtmStr, pointerWordSize, pointerDefaultStr = getPointerSizeStrs() local form = getMenuItemForm(menuItem) local origScript = strE if form ~= nil then origScript = form.Assemblescreen.Lines.Text end local le = templateTbl.LineEnd or I2CEAASTG_LINE_END or default_LineEnd or '\n' local template = nil if templateTbl.TemplateFile ~= nil then local f, err = io.open(templateTbl.TemplateFile, 'r') if not err and f then template = f:read() end elseif templateTbl.TemplateString ~= nil then template = templateTbl.TemplateString else local msg = 'Template was NOT found: "%s"' Logger.errorf('generate: ' .. msg, templateTbl.Name) showMessage(format('ERROR: ' .. t(msg), templateTbl.DisplayString)) return nil, nil end local fixInputData = templateTbl.FixInputData if fixInputData == nil then fixInputData = I2CEAASTG_FIX_INPUT_DATA end if fixInputData == nil then fixInputData = default_FixInputData end local mv = getMemoryViewForm() local dv = memoryview_getDisassemblerView(mv) local dv_address1 = dv.SelectedAddress local dv_address2 = dv.SelectedAddress2 local address = math.min(dv_address1, dv_address2) local addressStr = getModuleAndOffsetFromAddress(address) or address Logger.debugf('generate: selected address: %s', addressStr) local hookAddress = address local hookAddressStr = addressStr local aobOffset = 0 local aobOffsetStr = '' local nameBase = strE local hookName = strE local hookNameParsed = strE local hookNameParsedBase = strE local hookTag = templateTbl.HookTag or I2CEAASTG_HOOK_TAG or default_HookTag or HOOK_TAG local appendHookTag = templateTbl.AppendHookTag if appendHookTag == nil then appendHookTag = I2CEAASTG_APPEND_HOOK_TAG end if appendHookTag == nil then appendHookTag = default_AppendHookTag end local frmHookSetupModalResult, edHookNameText, edHookAddressText, cbxGenerateAobChecked = nil, nil, nil, nil if templateTbl.GetAddress then frmHookSetupModalResult, edHookNameText, edHookAddressText, cbxGenerateAobChecked = showHookSetupForm(addressStr, format(pointerFtmStr, address), templateTbl.GetAOBSignature) if frmHookSetupModalResult == mrOK and edHookNameText and edHookAddressText then hookName = edHookNameText if hookName == nil then Logger.debug('generate: got nil for ' .. hookTag:lower() .. ' name.') if form ~= nil then form.Assemblescreen.Lines.Text = origScript end return nil, nil ---- Exit generating template if prompt canceled. end if fixInputData then hookName = hookName:gsub('_', ' ') hookName = titleCase(hookName) end hookNameParsed = hookName for k, v in pairs({' ', '\\.', ';', ',', ':', '\\?', '\\!', '\\@', '\\#', '\\$', '\\%', '\\^', '\\&', '\\*', '\\(', '\\)', '\\[', '\\]', '\\{', '\\}', '"', "'", '<', '>', '/', '\\\\', '\\+', '\\-', '=', '~', '`'}) do hookNameParsed = hookNameParsed:gsub(v, strE) end nameBase = hookName hookNameParsedBase = hookNameParsed if appendHookTag and not hookName:lower():match(hookTag:lower()) then hookName = hookName .. ' ' .. hookTag hookNameParsed = hookNameParsed .. hookTag end if hookNameParsedBase:lower():match(hookTag:lower()) then hookNameParsedBase = hookNameParsedBase:gsub(hookTag, strE) hookNameParsedBase = hookNameParsedBase:gsub(hookTag:lower(), strE) hookNameParsedBase = hookNameParsedBase:gsub(hookTag:upper(), strE) hookNameParsedBase = hookNameParsedBase:gsub(titleCase(hookTag), strE) end Logger.debugf('generate: ' .. hookTag:lower() .. ' name: %s', hookName) Logger.debugf('generate: parsed ' .. hookTag:lower() .. ' name: %s', hookNameParsed) Logger.debugf('generate: parsed base ' .. hookTag:lower() .. ' name: %s', hookNameParsed) hookAddress = getAddress(edHookAddressText) hookAddressStr = getModuleAndOffsetFromAddress(hookAddress) Logger.debugf('generate: hook address string: %s', hookAddressStr) if address > hookAddress or address < hookAddress then aobOffset = address - hookAddress end if aobOffset > 0 then aobOffsetStr = '-' .. format('%X', aobOffset) elseif aobOffset < 0 then aobOffsetStr = '+' .. format('%X', math.abs(aobOffset)) end Logger.debugf('generate: aob offset: %s', aobOffset) else Logger.debug('generate: user canceled hook setup form') return nil, nil ---- Exit generating template if prompt canceled. end elseif templateTbl.GetHookName then local msg = t('Enter the name of the') .. ' ' .. hookTag:lower() .. ':' if appendHookTag then msg = msg .. '\n\n* "' .. hookTag .. '" ' .. t('will be appended to the name.') end hookName = inputQuery(hookTag .. ' ' .. t('Name') .. '?', msg, strE) if hookName == nil then Logger.debug('I2CEAASTG: generate: got nil for ' .. hookTag:lower() .. ' name.') if form ~= nil then form.Assemblescreen.Lines.Text = origScript end return nil, nil ---- Exit generating template if prompt canceled. end if fixInputData then hookName = titleCase(hookName:gsub('_', ' ')) end hookNameParsed = hookName:gsub(' ', strE) nameBase = hookName hookNameParsedBase = hookNameParsed if appendHookTag and not hookName:lower():match(hookTag:lower()) then hookName = hookName .. ' ' .. hookTag hookNameParsed = hookNameParsed .. hookTag end if hookNameParsedBase:lower():match(hookTag:lower()) then hookNameParsedBase = hookNameParsedBase:gsub(hookTag, strE) hookNameParsedBase = hookNameParsedBase:gsub(hookTag:lower(), strE) hookNameParsedBase = hookNameParsedBase:gsub(hookTag:upper(), strE) hookNameParsedBase = hookNameParsedBase:gsub(titleCase(hookTag), strE) end Logger.debugf('I2CEAASTG: generate: got ' .. hookTag:lower() .. ' name: "%s".', hookName) Logger.debugf('I2CEAASTG: generate: parsed ' .. hookTag:lower() .. ' name: "%s".', hookNameParsed) Logger.debugf('I2CEAASTG: generate: parsed base ' .. hookTag:lower() .. ' name: "%s".', hookNameParsed) end Logger.debugf('generate: hook address: %X', hookAddress) local moduleName = strE local moduleStr = strE local moduleDeclStr = strE local moduleAddressStr = strE local moduleSizeStr = strE local moduleBitSizeStr = strE if process then if inModule(hookAddress) then local modulesTable = enumModules() local size = 0 for i, v in pairs(modulesTable) do size = getModuleSize(v.Name) if size ~= nil then if hookAddress >= v.Address and hookAddress <= v.Address + size then moduleName = v.Name moduleStr = 'Module' moduleDeclStr = ', ' .. v.Name moduleAddressStr = format(pointerFtmStr, v.Address) moduleSizeStr = format(pointerFtmStr, getModuleSize(v.Name)) if v.Is64Bit then moduleBitSizeStr = '(x64)' else moduleBitSizeStr = '(x32)' end break end end end end end local nopASM = I2CEAASTG_NOP_ASM or NopASM or 'nop' local tempMarkerLine = I2CEAASTG_TEMPLATE_MARKER_LINE or TemplateMarkerLine or strE local headerString = I2CEAASTG_HEADER or TemplateHeader or 'I2CEAASTG_HEADER' local nopPaddingLeft = templateTbl.NopPaddingLeft or I2CEAASTG_NOP_PADDING_LEFT or default_NopPaddingLeft or strE local oCodePaddingLeft = templateTbl.OriginalCodePaddingLeft or I2CEAASTG_ORIGINAL_CODE_PADDING_LEFT or default_OriginalCodePaddingLeft or strE local injCommentType = templateTbl.InjectionInfoCommentType or I2CEAASTG_INJ_INFO_COMMENT_TYPE or default_InjectionInfoCommentType or 1 local lineComment = templateTbl.LineComment or I2CEAASTG_LINE_COMMENT or default_LineComment or '//// ' local userName = CE_USERNAME or UserName local placeholderKey = I2CEAASTG_PLACE_HOLDER_KEY or PlaceHolderKey local gameTitle = GAME_TITLE or 'GAME_TITLE' ---- To be set in tables lua file local gameVersion = GAME_VERSION or 'GAME_VERSION' ---- To be set in tables lua file local processAddress = 0 local processAddressStr = strE if process then gameTitle = GAME_TITLE or process:gsub('.exe', strE) or 'GAME_TITLE' ---- To be set in tables lua file gameVersion = GAME_VERSION or getGameVersionStr() or 'GAME_VERSION' ---- To be set in tables lua file processAddress = getAddress(process) or 0 processAddressStr = format(pointerFtmStr, processAddress) Logger.debugf('generate: process address: %s', processAddressStr) end local injectionInfo = strE local iils = lineComment if injCommentType == CommentTypes.Block then iils = strE end local ad = hookAddress local aobAD = strE for i = 1, InjectionInfoCount do ad = getPreviousOpcode(ad) if ad == address and cbxGenerateAobChecked then aobAD = AOB_START_STRING else aobAD = strE end injectionInfo = iils .. parseDisassembledString(disassemble(ad)) .. aobAD .. le .. injectionInfo end if moduleName and moduleName ~= strE then injectionInfo = iils .. '//// ' .. t('Module Size') .. ': ' .. moduleSizeStr .. le .. injectionInfo injectionInfo = iils .. '//// ' .. t('Module') .. ': ' .. moduleName .. ' - ' .. moduleAddressStr .. le .. injectionInfo end if process then injectionInfo = iils .. '//// ' .. t('Process') .. ': ' .. process .. ' - ' .. processAddressStr .. le .. injectionInfo end if address then injectionInfo = iils .. '//// ' .. t('AOB address') .. ': ' .. format(pointerFtmStr, address) .. ' - ' .. addressStr .. le .. injectionInfo end injectionInfo = iils .. '//// ' .. t('Injection Point') .. ': ' .. hookAddressStr .. ' - ' .. format(pointerFtmStr, hookAddress) .. le .. injectionInfo if injCommentType == CommentTypes.Block then injectionInfo = '{' .. le .. injectionInfo end injectionInfo = injectionInfo .. iils .. '//// ' .. t('INJECTING') .. ' ' .. t('START') .. ' ----------------------------------------------------------' .. le if hookAddress == address and cbxGenerateAobChecked then aobAD = AOB_START_STRING else aobAD = strE end injectionInfo = injectionInfo .. iils .. parseDisassembledString(disassemble(hookAddress)) .. aobAD .. le local fullHook = templateTbl.IsFullHook or false local extraField, opcode, bytes, disassembledAddress = splitDisassembledString(disassemble(hookAddress)) local originalCode = oCodePaddingLeft .. opcode bytes = parseBytesStr(bytes) local originalBytesStr = bytes local ad = hookAddress local iSize = getInstructionSize(ad) local iSizeMin = iSize if fullHook then iSizeMin = 5 end local opcodeCount = 1 while iSize < iSizeMin do opcodeCount = opcodeCount + 1 ad = ad + getInstructionSize(ad) local l = getInstructionSize(ad) iSize = iSize + l local extraField, opcode, bytes, disassembledAddress = splitDisassembledString(disassemble(ad)) originalBytesStr = originalBytesStr .. parseBytesStr(bytes) originalCode = originalCode .. le .. oCodePaddingLeft .. opcode end Logger.debugf('generate: original bytes: %s', originalBytesStr) ad = hookAddress for i = 1, InjectionInfoCount do if opcodeCount == i then injectionInfo = injectionInfo .. iils .. '//// ' .. t('INJECTING') .. ' ' .. t('END') .. ' ----------------------------------------------------------' .. le end ad = ad + getInstructionSize(ad) if ad == address and cbxGenerateAobChecked then aobAD = AOB_START_STRING else aobAD = strE end injectionInfo = injectionInfo .. iils .. parseDisassembledString(disassemble(ad)) .. aobAD .. le end injectionInfo = injectionInfo .. '//// ' .. t('Template') .. ': ' .. (templateTbl.Name or templateTbl.DisplayString) .. le injectionInfo = injectionInfo .. '//// ' .. t('Generated with') .. ': ' .. NAME .. le injectionInfo = injectionInfo .. '//// ' .. t('Code Happy, Code Freely, Be Awesome.') .. le if injCommentType == CommentTypes.Block then injectionInfo = injectionInfo .. '}' end local instNopStr = strE local instNop90sStr = strE for i = 1, iSize do if instNopStr == nil or instNopStr == strE then instNopStr = nopASM else instNopStr = instNopStr .. le .. nopPaddingLeft .. nopASM end if instNop90sStr == nil or instNop90sStr == strE then instNop90sStr = 'db' end instNop90sStr = instNop90sStr .. ' 90' end local nopStr = strE local nop90sStr = strE if iSize > iSizeMin then for i = 6, iSize do nopStr = nopStr .. le .. nopPaddingLeft .. nopASM if nop90sStr == nil or nop90sStr == strE then nop90sStr = le .. nopPaddingLeft .. 'db' end nop90sStr = nop90sStr .. ' 90' end end local o_regStr = strE local o_offset = 0 local o_offsetStr = strE if type(originalCode) == 'string' and originalCode ~= strE then local rStr = [=[[fld|fstp|lea|LEA|mov|MOV|add|ADD|sub|SUB|mul|MUL|div|DIV|inc|INC|dec|DEC][ss|SS]*[%s]+[dword|qword]*[%s]*[ptr]*[%s]*[%a|%d|,]*%[([%a]+)([%+|%*|%-][a-fA-F0-9]*)%]]=] o_regStr, o_offsetStr = originalCode:match(rStr) if o_offsetStr ~= nil and o_offsetStr ~= strE then o_offset = math.abs(tonumber(o_offsetStr, 16)) end Logger.debugf('generate: original offset value: %X', o_offset) if o_offset < 0 then o_offsetStr = format('-%X', math.abs(o_offset)) else o_offsetStr = format('+%X', math.abs(o_offset)) end end Logger.debugf('generate: original registry and offset: %s, %s', o_regStr, o_offsetStr) local aobMessage = strE local signatureBytesStr = strE if cbxGenerateAobChecked then local signature, signatureCount = getByteScanSignature(address, pMsg) signatureBytesStr = signature if signatureBytesStr == nil then aobMessage = le .. '//// ' .. t('AOB Scan Error! Signature was nil') signatureBytesStr = strE elseif signatureCount == -1 then aobMessage = le .. '//// ' .. t('AOB Scan Error! Count was -1') elseif signatureCount ~= 1 then aobMessage = le .. '//// ' .. t('AOB Matches Found') .. ': ' .. signatureCount end end local parsedTemplate = template local headerTbl = { Header = headerString or strE } parsedTemplate = interp(parsedTemplate, headerTbl) local valueTbl = { ProcessName = process or strE, ProcessAddress = processAddressStr or strE, Module = moduleName or strE, ModuleStr = moduleStr or strE, ModuleDecl = moduleDeclStr or strE, ModuleAddress = moduleAddressStr or strE, ModuleSize = moduleSizeStr or strE, ModuleBitSize = moduleBitSizeStr or strE, Date = os.date(I2CEAASTG_DATE_FORMAT or DateFormat) or strE, Author = userName or strE, HookTag = hookTag or strE, HookName = hookName or strE, HookNameBase = nameBase or strE, HookNameParsed = hookNameParsed or strE, HookNameParsedBase = hookNameParsedBase or strE, OriginalBytes = parseBytesStr(originalBytesStr) or strE, AOBBytes = signatureBytesStr:gsub("%s", strE) or strE, AOBMessage = aobMessage or strE, AOBOffset = aobOffsetStr or strE, AOBAddress = address or '', OriginalCode = originalCode or strE, Address = hookAddressStr or strE, AddressHex = format(pointerFtmStr, hookAddress), InjectionInfo = injectionInfo or strE, InstNOPS = instNopStr or strE, InstNOP90S = instNop90sStr or strE, NOPS = nopStr or strE, NOP90S = nop90sStr or strE, CEVersion = tostring(getCEVersion() or 0), PointerSize = pointerSizeStr, PointerFtmStr = pointerFtmStr or '%016X', PointerWordSize = pointerWordSize or 'dq', PointerDefault = pointerDefaultStr or 'dq 0', PointerDefaultFull = format(pointerWordSize .. ' ' .. pointerFtmStr, 0x0), GameTitle = gameTitle or strE, GameVersion = gameVersion or strE, BaseAddressRegistry = o_regStr or strE, BaseAddressOffset = o_offsetStr or strE, BaseAddressOffsetValue = tostring(o_offset) or '', } parsedTemplate = interp(parsedTemplate, valueTbl) while (parsedTemplate:find('${' .. placeholderKey .. '.-}') ~= nil) do local placeholderFull, placeholderName = parsedTemplate:match('(${' .. placeholderKey .. '(.-)})') placeholderName = titleCase(placeholderName:gsub('_', ' ')) local placeholderReplace = inputQuery(placeholderName .. '?', t('Enter replacement for keyword') .. ' "' .. placeholderName .. '":', strE) if placeholderReplace == nil then Logger.warnf('generate: got nil for key word replacement: kw: "%s", n: "%s".', placeholderFull, placeholderName) form.Assemblescreen.Lines.Text = origScript return nil, nil ---- Exit generating template if prompt canceled end Logger.debugf('generate: got key word replacement: kw: "%s", n: "%s", r: "%s".', placeholderFull, placeholderName, placeholderReplace) if placeholderReplace == strE then placeholderReplace = placeholderFull end parsedTemplate = parsedTemplate:gsub(placeholderFull, placeholderReplace) valueTbl[placeholderKey] = placeholderReplace end Logger.infof('generate: template generated: "%s".', templateTbl.Name or templateTbl.DisplayString) local logMsg, _ = parsedTemplate:gsub('\r\n', '\n') logMsg, _ = parsedTemplate:gsub('\n', '\r\n') Logger.debug('------------------------------------------------------------') Logger.debug(logMsg) Logger.debug('------------------------------------------------------------') if type(origScript) == 'string' and #origScript > 2 then origScript = origScript .. le .. le .. tempMarkerLine .. le else origScript = strE end if form ~= nil then form.Assemblescreen.Lines.Text = origScript .. parsedTemplate end if templateTbl.MemoryRecords ~= nil then local sctMsg = '* ' .. t('The script is NOT included') .. '!!' if templateTbl.MemoryRecordsIncludeScript then sctMsg = t('The script is included') .. '.' end if templateTbl.AskToAddToTable == false then valueTbl.Script = parsedTemplate local mrTbl = I2CEAutoAssemblerScriptTemplates.createTemplateMemoryRecords(templateTbl, valueTbl) else local msg = t('Would you like to add template memory records to the table?') .. '\n\n' .. sctMsg local mr = messageDialog(msg, mtConfirmation, mbYes, mbNo, mbCancel) if mr == mrYes then valueTbl.Script = parsedTemplate local mrTbl = I2CEAutoAssemblerScriptTemplates.createTemplateMemoryRecords(templateTbl, valueTbl) end end if BringCheatEngineToFrontOnCreateMemoryRecords then MainForm.bringToFront() end end if form ~= nil and parsedTemplate ~= nil then form.Assemblescreen.Lines.Text = parsedTemplate end return parsedTemplate, mrTbl end ---------------- ---------------- Generate ---------------- ---------------- ---------------- ---------------- -- -------- -------- -------- Create Memory Records -------- local function showValueEntryForm(valueStr, vtValueType, addFlag, asHex) Logger.debugf('showValueEntryForm: with starting value: %s', valueStr or '') local fW = 400 local row = 0 local lPush = 90 local sX = fW - (lPush + 10) local sY = 23 local pX = 3 local pY = 3 local bW = 75 local bH = 24 local padF = 5 local pad1 = 3 local pad2 = 1 local frmValueEntry = createForm(false) frmValueEntry.centerScreen() frmValueEntry.setSize(fW, fH) frmValueEntry.Name = 'frmValueEntry' frmValueEntry.Caption = t('Value Entry') local lblValue = createLabel(frmValueEntry) lblValue.Name = 'lblValue' lblValue.setPosition(pX, pY + sY * row + pad1) lblValue.Caption = t('Value') .. ':' local edValue = createEdit(frmValueEntry) edValue.Name = 'edValue' edValue.setSize(sX, sY) edValue.setPosition(pX + lPush, pY + sY * row + pad2) edValue.Text = valueStr or '' row = row + 1 local lblValueType = createLabel(frmValueEntry) lblValueType.Name = 'lblValueType' lblValueType.setPosition(pX, pY + sY * row + pad1) lblValueType.Caption = t('ValueType') .. ':' local cmbValueType = createComboBox(frmValueEntry) cmbValueType.Name = 'cmbValueType' cmbValueType.setSize(sX, sY) cmbValueType.setPosition(pX + lPush, pY + sY * row + pad2) cmbValueType.Text = '' cmbValueType.ReadOnly = true local valueTypeList = { [vtByte + 1] = 'Byte', [vtWord + 1] = 'Word (2 Byte)', [vtDword + 1] = 'Dword (4 Byte)', [vtQword + 1] = 'Qword (8 Byte)', [vtSingle + 1] = 'Single (Float)', [vtDouble + 1] = 'Double', [vtString + 1] = 'String', [vtByteArray + 1] = 'Array Of Bytes', [vtBinary + 1] = 'Binary', } local valueTypeIndex = 0 if vtValueType == nil then vtValueType = vtDword end for i, v in ipairs(valueTypeList) do cmbValueType.Items.add(v) if i - 1 == vtValueType then valueTypeIndex = i - 1 end end cmbValueType.setItemIndex(valueTypeIndex) row = row + 1 local cbxAddFlag = createCheckBox(frmValueEntry) cbxAddFlag.Name = 'cbxAddFlag' cbxAddFlag.setSize(sX, sY) cbxAddFlag.setPosition(pX + lPush, pY + sY * row + pad2) cbxAddFlag.Caption = t('Add Flag') cbxAddFlag.Checked = addFlag or false local cbxAsHex = createCheckBox(frmValueEntry) cbxAsHex.Name = 'cbxAsHex' cbxAsHex.setSize(sX, sY) cbxAsHex.setPosition(pX + lPush + cbxAddFlag.Width + pad2, pY + sY * row + pad2) cbxAsHex.Caption = t('Show As Hex') cbxAsHex.Checked = asHex or false row = row + 1 local btnOk = createButton(frmValueEntry) btnOk.Name = 'btnOk' btnOk.Caption = t('OK') btnOk.setSize(bW, bH) btnOk.setPosition((fW / 3) - (bW / 2), pY + sY * row + pad2) btnOk.ModalResult = mrOK btnOk.Default = true local btnCancel = createButton(frmValueEntry) btnCancel.Name = 'btnCancel' btnCancel.Caption = t('Cancel') btnCancel.setSize(bW, bH) btnCancel.setPosition(((fW / 3) * 2) - (bW / 2), pY + sY * row + pad2) btnCancel.ModalResult = mrCancel btnCancel.Cancel = true row = row + 1 frmValueEntry.setSize(fW, pY + sY * row + padF) local mr = frmValueEntry.showModal() for i, v in ipairs(valueTypeList) do if v == cmbValueType.Items[cmbValueType.ItemIndex] then vtValueType = i - 1 end end Logger.debugf('showValueEntryForm: modal form closed: %d, %s, %s, %s, %s', mr, edValue.Text, vtValueType, cbxAddFlag.Checked, cbxAsHex.Checked) return mr, edValue.Text, vtValueType, cbxAddFlag.Checked, cbxAsHex.Checked end function I2CEAutoAssemblerScriptTemplates.createTemplateMRAddValue(addValueTbl, interpTbl, memoryRecord) Logger.debug('createTemplateMRAddValue: starting add values form') local valueStr = addValueTbl.ValueStr local vtValueType = addValueTbl.ValueType local addFlag = addValueTbl.AddFlag local asHex = addValueTbl.AsHex local mr = nil mr, valueStr, vtValueType, addFlag, asHex = showValueEntryForm(valueStr, vtValueType, addFlag, asHex) if mr == mrOK and valueStr ~= nil and vtValueType ~= nil and addFlag ~= nil and asHex ~= nil then Logger.debug('createTemplateMRAddValue: adding values') local addStr = '${HookNameParsed}' if vtValueType == vtSingle or vtValueType == vtDouble then addStr = 'flt' .. addStr elseif vtValueType == vtString then addStr = 'str' .. addStr elseif vtValueType == vtByteArray then addStr = 'arb' .. addStr elseif vtValueType == vtBinary then addStr = 'bin' .. addStr else addStr = 'int' .. addStr end local tbl = { Description = addStr, Address = addStr, Color = Colors.Fuchsia, Type = vtValueType, ShowAsHex = asHex, } I2CEAutoAssemblerScriptTemplates.createTemplateMR(tbl, interpTbl, memoryRecord) Logger.debug('createTemplateMRAddValue: value added') if addFlag then Logger.debug('createTemplateMRAddValue: adding flag') I2CEAutoAssemblerScriptTemplates.createTemplateMR(I2_TEMPLATE_MR_FLG, interpTbl, memoryRecord) end end end function I2CEAutoAssemblerScriptTemplates.createTemplateMR(mrTbl, interpTbl, appendMr) if mrTbl == nil then return end local addressesList = getAddressList() local memoryRecord = addressesList.createMemoryRecord() local isScript = false local scriptStr = nil for k, v in pairs(mrTbl) do if k == 'MemoryRecords' and type(v) == 'table' then Logger.debug('createTemplateMR: generating child memory records.') for i = 1, #v do local subMemoryRecord = I2CEAutoAssemblerScriptTemplates.createTemplateMR(v[i], interpTbl, memoryRecord) end else if type(v) == 'table' and memoryRecord[k] ~= nil then if k == 'Hotkey' then for v_k, v_v in pairs(v) do if v_v ~= nil then memoryRecord[k][v_k] = v_v end end elseif (k == 'Offset' or k == 'OffsetText') then for v_k, v_v in ipairs(v) do memoryRecord.setOffsetCount(#v) if v_v ~= nil then memoryRecord.setOffset(v_k - 1, tonumber(interp(v_v, interpTbl), 16)) Logger.debugf('createTemplateMR: memoryRecord Offset set: %d, %X', v_k - 1, tonumber(interp(v_v, interpTbl), 16)) end end else for v_k, v_v in pairs(v) do if v_v ~= nil then memoryRecord[k][v_k] = v_v end end end elseif type(v) == 'table' and memoryRecord[k] == nil then if k == 'AddValue' then Logger.debug('createTemplateMR: adding value') I2CEAutoAssemblerScriptTemplates.createTemplateMRAddValue(mrTbl[k], interpTbl, memoryRecord) elseif k == 'AddValues' then Logger.debug('createTemplateMR: adding values') for k_i, k_v in ipairs(mrTbl[k]) do I2CEAutoAssemblerScriptTemplates.createTemplateMRAddValue(mrTbl[k][k_i], interpTbl, memoryRecord) end end else if k == 'Type' and v == vtAutoAssembler then isScript = true elseif k == 'Script' and type(v) == 'string' then scriptStr = interp(v, interpTbl) end if k == 'Type' and type(v) == 'string' and (v:lower() == 'pointer' or v:lower() == 'ptr' or v:lower() == 'p') then if interpTbl.PointerSize == '0x4' then memoryRecord[k] = vtDword else memoryRecord[k] = vtQword end else if type(v) == 'string' then v = interp(v, interpTbl) end memoryRecord[k] = v end end end end if appendMr ~= nil then memoryRecord.appendToEntry(appendMr) end if isScript and scriptStr == nil then memoryRecord.Script = interpTbl.Script elseif scriptStr ~= nil then memoryRecord.Script = scriptStr end local lDStr = memoryRecord.Description:sub(1, 40) Logger.debugf('createTemplateMR: memory record created: ID: % 3d, Type: % 2d, "%s".', memoryRecord.ID, memoryRecord.Type, lDStr) return memoryRecord end function I2CEAutoAssemblerScriptTemplates.createTemplateMemoryRecords(templateTbl, interpTbl) Logger.info('createTemplateMemoryRecords: generating memory records.') if templateTbl == nil or templateTbl.MemoryRecords == nil then return end local addressesList = getAddressList() local mrTbl = templateTbl.MemoryRecords local createdMemoryRecordsTbl = { } local memoryRecord = nil for i = 1, #mrTbl do memoryRecord = I2CEAutoAssemblerScriptTemplates.createTemplateMR(mrTbl[i], interpTbl) createdMemoryRecordsTbl[i] = memoryRecord end return createdMemoryRecordsTbl end -------- -------- Create Memory Records -------- -------- -- -- -------- -------- -------- -------- Setup and Load: -------- function I2CEAutoAssemblerScriptTemplates.createTelplateMenuItem(form, menu, tbl) if form == nil or menu == nil or tbl == nil then return end local items = menu if menu.Items ~= nil then items = menu.Items end if type(tbl) == 'string' then local mi = createMenuItem(menu) mi.Caption = '-' items.add(mi) elseif type(tbl.SectionDisplayString) == 'string' then local name = 'mi' .. titleCase(tbl.SectionDisplayString:gsub('_', ' ')):gsub(' ', strE) if type(tbl.SectionName) == 'string' then name = tbl.SectionName if name:lower():sub(1, 2) ~= 'mi' then name = 'mi' .. name end end for i = 1, items.Count - 1 do if items[i].Name == name then return end end local sectionMenuItem = createMenuItem(menu) sectionMenuItem.Name = name sectionMenuItem.Caption = tbl.SectionDisplayString if sectionMenuItem then Logger.debugf('createTelplateMenuItem: Template Section Menu Item Created: "%s".', sectionMenuItem.Name) end for i = 1, #tbl do I2CEAutoAssemblerScriptTemplates.createTelplateMenuItem(form, sectionMenuItem, tbl[i]) end items.add(sectionMenuItem) elseif type(tbl.DisplayString) == 'string' then local name = 'mi' .. titleCase(tbl.DisplayString:gsub('_', ' ')):gsub(' ', strE) if type(tbl.Name) == 'string' then name = tbl.Name if name:lower():sub(1, 2) ~= 'mi' then name = 'mi' .. name end end for i = 1, items.Count - 1 do if items[i].Name == name then return end end local function mi_click(menuItem) Logger.debugf('createTelplateMenuItem: Template Menu Item Clicked: "%s".', menuItem.Name) I2CEAutoAssemblerScriptTemplates.generate(menuItem, tbl) end local menuItem = createMenuItem(menu) menuItem.Name = name menuItem.OnClick = mi_click menuItem.Caption = tbl.DisplayString if tbl.Shortcut ~= nil then menuItem.setShortcut(tbl.Shortcut) end items.add(menuItem) if menuItem then Logger.debugf('createTelplateMenuItem: Template Menu Item Created: "%s".', menuItem.Name) end return menuItem end end function I2CEAutoAssemblerScriptTemplates.createMenuItems(form, menu) local frmMemoryView = getMemoryViewForm() if I2CEAutoAssemblerScriptTemplates.Templates == nil then return end if form == nil or menu == nil then return end if I2CEAASTG_ADD_MAIN_SEPERATOR or (I2CEAASTG_ADD_MAIN_SEPERATOR == nil and AddMainSeperator) then local mi = createMenuItem(menu) mi.Caption = '-' menu.add(mi) end local addToMenu = menu if form.ClassName == frmMemoryView.ClassName then local mi = createMenuItem(menu) mi.Caption = '-' menu.Items.add(mi) addToMenu = createMenuItem(menu) addToMenu.Name = 'miTemplates' addToMenu.Caption = MemoryViewFormTemplateMenuCaption or t('Templates (AA)') menu.Items.add(addToMenu) end for i = 1, #I2CEAutoAssemblerScriptTemplates.Templates do if I2CEAutoAssemblerScriptTemplates.Templates[i] ~= nil then if (not I2CEAutoAssemblerScriptTemplates.Templates[i].AddToMainOnly) or (I2CEAutoAssemblerScriptTemplates.Templates[i].AddToMainOnly and form.ClassName == MainForm.ClassName) then I2CEAutoAssemblerScriptTemplates.createTelplateMenuItem(form, addToMenu, I2CEAutoAssemblerScriptTemplates.Templates[i]) end end end end function I2CEAutoAssemblerScriptTemplates.loadTemplateDir(path, tbl) if not exists(path) or tbl == nil then return end for k, l in pairs(getFileList(path)) do local path, filename, ext = l:match([==[(.-)([^\/]-%.?([^%.\/]*))$]==]) if ext:lower() == TEMPLATE_FILE_EXT:lower() then local strLst = createStringlist() strLst.loadFromFile(l) local templateStr = strLst.Text local tempTbl = { DisplayString = titleCase(filename:sub(0, -5):gsub('_', ' ')), TemplateString = templateStr, } local secs = { start = 0, settings = 1, template = 2, } local sec = secs.start for i = 0, strLst.count - 1 do if strLst[i]:upper() == '[SETTINGS]' or strLst[i]:upper() == '[SETTINGS]\n' or strLst[i]:upper() == '[SETTINGS]\r\n' then sec = secs.settings elseif strLst[i]:upper() == '[TEMPLATE]' or strLst[i]:upper() == '[TEMPLATE]\n' or strLst[i]:upper() == '[TEMPLATE]\r\n' then sec = secs.template templateStr = strE elseif sec == secs.settings then local rStr1 = [==[^[%s]*([%a_]+[%a%d_%-]*)[%s]*=[%s]*([%a%d_%-]*)[%s]*$]==] local rStr2 = [==[^[%s]*([%a_]+[%a%d_%-]*)[%s]*=[%s]*["|']([%a%d%s_%-]*)["|'][%s]*$]==] local key, value = strLst[i]:match(rStr1) local isStr = false if value == nil then key, value = strLst[i]:match(rStr2) if value ~= nil then isStr = true end end if value ~= nil then if isStr then value = value elseif value:lower() == 'true' or value:lower() == 'yes' or value:lower() == 'on' then value = true elseif value:lower() == 'false' or value:lower() == 'no' or value:lower() == 'off' then value = false elseif tonumber(value) ~= nil then value = tonumber(value) end tempTbl[key] = value end elseif sec == secs.template then local le = tempTbl.LineEnd or I2CEAASTG_LINE_END or default_LineEnd or '\n' templateStr = templateStr .. strLst[i] .. le end end if sec == secs.template then tempTbl.TemplateString = templateStr end table.insert(tbl, tempTbl) end end end function I2CEAutoAssemblerScriptTemplates.loadTemplatesDirectory(path, tbl) if type(path) ~= 'string' then return end if tbl == nil then tbl = I2CEAutoAssemblerScriptTemplates.Templates end if isDirectory(path) then I2CEAutoAssemblerScriptTemplates.loadTemplateDir(path, tbl) for i, j in pairs(getDirectoryList(path)) do local dirPath, dirName = j:match([==[(.-)([^\/]-%.?([^%.\/]*))$]==]) local secTbl = { DisplayString = dirName:gsub('_', ' '), } I2CEAutoAssemblerScriptTemplates.loadTemplateDir(dirPath, secTbl) table.insert(tbl, secTbl) end end Logger.debug('loadTemplatesDirectory: loading templates directory.') I2CEAutoAssemblerScriptTemplates.loadTemplateDir(dirPath, tbl) end function I2CEAutoAssemblerScriptTemplates.formCreateNotify(form) if form.ClassName == 'TfrmAutoInject' then Logger.debugf('formCreateNotify: "%s" form created, creating timer for menu creation.', form.ClassName) local ticks = 0 local intervals = MENU_CREATION_TIMER_INTERVALS or 500 ---- Set timer a little higher to keep menu items in same spot. local timer = createTimer(form) timer.Interval = intervals local function formCreateNotifyTimer_tick(timer) ticks = ticks + 1 if form == nil or form.Menu == nil then return end timer.destroy() Logger.debugf('formCreateNotifyTimer_tick: creating menu items, ' .. 'timer KILLED. Interval: %d, Ticks: %d.', intervals, ticks) local miTemplate = form.emplate1 if I2CEAASTG_ADD_AA_MAIN_SEPERATOR or (I2CEAASTG_ADD_AA_MAIN_SEPERATOR == nil and AddMainAASeperator) then local mi = createMenuItem(miTemplate) mi.Caption = '-' miTemplate.add(mi) end I2CEAutoAssemblerScriptTemplates.createMenuItems(form, miTemplate) end timer.OnTimer = formCreateNotifyTimer_tick end end function I2CEAutoAssemblerScriptTemplates.createMainFormMenu() if MainForm.Menu == nil then return end local menuItems = MainForm.Menu.Items local miExtra = nil for i = 0, menuItems.Count - 1 do if menuItems[i].Name == MAIN_FORM_PARENT_MENU_ITEM_NAME then miExtra = menuItems[i] end end if miExtra == nil then miExtra = createMenuItem(MainForm) miExtra.Name = MAIN_FORM_PARENT_MENU_ITEM_NAME miExtra.Caption = MAIN_FORM_PARENT_MENU_ITEM_CAPTION menuItems.insert(menuItems.Count - 2, miExtra) end Logger.debug('createMainFormMenu: creating main form menu items.') return I2CEAutoAssemblerScriptTemplates.createMenuItems(MainForm, miExtra) end function I2CEAutoAssemblerScriptTemplates.loadTemplates(templates) if templates ~= nil then if templates.DisplayString ~= nil then templates = { templates } end for i = 1, #templates do table.insert(I2CEAutoAssemblerScriptTemplates.Templates, templates[i]) end end Logger.debug('loadTemplates: loading templates.') I2CEAutoAssemblerScriptTemplates.loadTemplatesDirectory(I2CEAASTG_TEMPLATES_DIRECTORY or TemplatesDirectory) registerFormAddNotification(I2CEAutoAssemblerScriptTemplates.formCreateNotify) end local function loadI2CEAutoAssemblerScriptTemplates() local function loadTemplatesTimer_tick(timer) timer.destroy() if (I2CEAASTG_AUTO_LOAD ~= nil and I2CEAASTG_AUTO_LOAD) or (I2CEAASTG_AUTO_LOAD == nil and AutoLoad) then I2CEAutoAssemblerScriptTemplates.loadTemplates() end if CREATE_MAIN_FORM_MENU_ITEMS then I2CEAutoAssemblerScriptTemplates.createMainFormMenu() end end ---- Use timer to allow other files to load templates and keep menu items in same spot. local intervals = 800 local timer = createTimer(MainForm) timer.Interval = intervals timer.OnTimer = loadTemplatesTimer_tick end loadI2CEAutoAssemblerScriptTemplates() local function OnSelectionTracker(disassemblerviewLine, address, address2) dv_address1 = address dv_address2 = address2 end local function AddItemMenuInMemoryViewForm(nameItemMenu, shortcut, functionItemClick, functionSelectiontracker) local frmMemoryView = getMemoryViewForm() local dv = frmMemoryView.DisassemblerView disassemblerview_onSelectionChange(dv, functionSelectiontracker) dv_address1 = dv.SelectedAddress dv_address2 = dv.SelectedAddress2 popupmenu = dv.PopupMenu mi = createMenuItem(popupmenu) mi.Caption = nameItemMenu mi.onClick = functionItemClick mi.Shortcut = shortcut popupmenu.Items.add(mi) if AddTemplatesToMemoryViewPopupMenu then I2CEAutoAssemblerScriptTemplates.createMenuItems(frmMemoryView, popupmenu) end end local function AddItemMenu(menuItem, nameItemMenu, shortcut, functionItemClick) local mi = createMenuItem(popupmenu) mi.Caption = nameItemMenu mi.Shortcut = shortcut mi.onClick = functionItemClick menuItem.add(mi) end local function AddItemMenuSeparatorInMemoryViewForm(functionSelectiontracker) local frmMemoryView = getMemoryViewForm() local dv = frmMemoryView.DisassemblerView disassemblerview_onSelectionChange(dv, functionSelectiontracker) popupmenu = dv.PopupMenu mi = createMenuItem(popupmenu) mi.Caption = '-' popupmenu.Items.add(mi) end AddItemMenuSeparatorInMemoryViewForm(OnSelectionTracker) AddItemMenuInMemoryViewForm(MemoryViewFormByteSignatureScanInfoDescription or t('Get byte scan signature info'), MemoryViewFormByteSignatureScanInfoShortcut or strE, OnItemMenuGetSignatureInfoClick, OnSelectionTracker) -------- -------- Setup and Load: -------- -------- -------- Logger.debugf('%s: Loaded.', I2CEAutoAssemblerScriptTemplates.ClassName) return I2CEAutoAssemblerScriptTemplates