Results 1 to 21 of 21

Thread: Open Source Updater

  1. #1
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default Open Source Updater

    Java Class Updater



    So, after much deliberation and delays, i'm finally going to release my full updater open source for people to use and learn from (though the latter is quite unlikely). If enough people start using it and contributing, it should help make the updates of the include occur much faster. I kept everything in the updater, so it should be ready to run. As such, once you download and set it up, anyone should be able to run it and submit a pull request to the include to update the hooks.


    I will not be using this thread/tutorial to talk about how to make an updater, or to explain how one works. This thread is simply going to describe how this specific updater is organized and how to best modify it. If you do not already have a good understanding of JVM bytecode or how updater's work, I suggest reading @Brandon;'s tutorial located here. You will most likely be wasting your time if you try and learn much from this thread without having a decent background.

    Issues
    If you find any hooks that are broken, please create a Github issue here. If you are interested in contributing to the updater and there are any issues currently, that is an excellent place to start.



    General Overview

    Much of this updater is written quite neat and organized, while other parts of it are very inefficient and bloated. In my last rewrite of it, I decided to keep the deob bloated, as it works very well and doesn't need updating often (if ever). I spent the majority of my time ensuring that the class and field finders were very easy to modify and use. This updater is strongly based on deobfuscation of the gamepack, much of which is specifically done for an individual pattern. This allows each pattern to be incredible strong, and allows the finding of patterns simple, due to the fact that they rarely change since the deob removes the changes to the bytecode. Many of the patterns used in the updater are your standard regex patterns, i.e ALOAD, GETFIELD, ACONST_NULL. For other patterns, those that can not be easily found with a standard regex pattern, I follow unique conditional statements or opaque predicates. This seems to be a unique approach as compared to the majority of updaters used. It allows the use of very small patterns that don't break, yet are still incredibly unique within the gamepack.

    Deobfuscation
    The deob is located within the deob/ package and that is where all the deobfuscation occurs. The DeobFrame.java is simply an abstract class which we overwrite with the specific deob we are using. Deobsfucate.java contains the running portion of the code in which we add all the deob methods to a list, and run each entry. Method.java removes the unused methods within the pack (this was heavily taken from an old jh thread). Multipliers.java standardizes the way in which the multipliers are written in the pack. EqualSwap.java was originally done in order to standardize the way in which variables were assigned in the pack, but is now just a catch all for any type of deob that I add to the updater (very messy and unorganized). RemoveExceptions.java does just that, removes all exceptions that are added to the pack as a means of obfuscation (much of this was done together with Brandon). OpaquePredicates.java standardizes the comparators within all opaque predicates. MethodName.java removes dummy parameters from method names. Note: this is not the "proper" way in which to do this, and it renders the pack completely unable to run. This is because I don't remove the parameter from references to the method. Since I only use the updater to update and not for a bot, it doesn't affect me.

    Analyzers
    Both the class finders and field finders are located within analysers/package.

    Class Analyzers
    Within analysers/classes is where all the classes and methods live in which all the class names within the gamepack are located and identified. The classAnalyserFrame.java class is the framework that is extended for all of the individual class analyzers to use specifically. Most of the methods and fields that are contained within are self explanatory and easy to use. Each class finder extends the classAnalyserFrame and implements the abstract method "identify()". This is the actual working part of the code that is used to find the specific classes within the client. All of the classAnalsyers are run from a class mainAnalyser.java which is located within analysers/methods. This class loads all the class finders into a list and runs each one individually. If a class is unable to be found, it will prompt you to enter in the class name (if you have it).

    Field Analyzers
    All of the field analyzers are located inside analysers/methods. This is where the majority of the time is spent in maintaining an updater, as these are the most apt to break. Similar to the class analyzers, there is a methodAnalyserFrame.java which is extended to every specific class of finders. Also similar to the class analyzers, the method "identify()" is implemented in every class and contains all the code to find all wanted fields within the class. Objects for the classes are created in the analysers/methods.java class. This allows us to access any of the field values from any location in the updater. This makes it easy to find fields that depend on the location of another. These analyzers are also run from the methods/mainAnalyser.java class.

    Updater Running
    The main class that is run upon execution is the main/eUpdater.java class. There are several useful variables in which you can change depending on what you want:
    • Revision is the current revision of the client, if it is higher than the current gamepack downloaded, it will download a new one.
    • simbaPrint if true will save the hooks file to a simba file located at: "C:/Simba/Includes/Reflection/lib/internal/Hooks.simba"
    • logPrint will print the readable hooks file to the debug
    • forceDeob/Download are self explanatory
    • findMultis will find multipliers if true
    • doRefactor will do a very crappy and basic refactor of the client if set true
    Last edited by Kyle; 11-14-2016 at 06:19 PM.
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  2. #2
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default

    Using the Searchers
    As much as possible, I tried to keep the bulk of the code used in finding fields done within other methods to allow the writing of each pattern to be as short as possible. I didn't want to do this to such an extreme that it made it difficult to make complex patterns either. As such, the searcher/ package contains a multitude of useful methods in which allow important bytecode determinations, with very little code needed.

    FieldSearcher
    As the name implies, the FieldSearcher class contains methods that involve the fields within the gamepack. As such, all of these methods are used on a specific class within the gamepack, never a method (as a method doesn't own a class).
    A FieldSearcher object is created like so:
    Code:
    FieldSearcher Fs = new FieldSearcher(cF); //Where cF is a classFrame
    Most of the FieldSearcher methods or pretty self explanatory, but i'll write a bit about here anyway:
    • findDesc(String desc) -> Returns first field found with matching desc
    • countDesc(String desc) -> Returns the number of fields that have the specified desc
    • findContainsDesc(String desc) -> Same as findDesc, except not exact
    • findAccess(int Acc) -> Returns first field found with matching access
    • findValue(int Acc)-> Returns true if a field is found with the matching value
    • findDescInstance(String desc, int Instance) -> Same as findDesc, but will return the specified instance. This is useful for looping through fields

    The FieldSearcher's are pretty limited and are mainly used for identifying classes, or very basic fields

    multiplierSearcher
    This class is used to find the multiplier for a given integer field. Feel free to look through it to see how it works, but since it's used at the end on all fields, you really won't ever touch it.

    Searcher
    This is the most used class within the updater, and almost every field within the updater is found by using it. It contains the majority of all the finders within the updater.

    To be continued..
    Last edited by Kyle; 11-14-2016 at 10:58 PM.
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  3. #3
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default

    ---Reserved---
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  4. #4
    Join Date
    Dec 2011
    Location
    East Coast, USA
    Posts
    4,217
    Mentioned
    112 Post(s)
    Quoted
    1861 Post(s)

    Default

    You're a gentleman and a scholar, sir. This community (and many others, before too long) thanks you profusely.
    GitLab projects | Simba 1.4 | Find me on IRC or Discord | ScapeRune scripts | Come play bot ScapeRune!

    <BenLand100> we're just in the transitional phase where society reclassifies guns as Bad™ before everyone gets laser pistols

  5. #5
    Join Date
    Sep 2014
    Location
    C:\Simba\
    Posts
    565
    Mentioned
    9 Post(s)
    Quoted
    71 Post(s)

    Default

    Quote Originally Posted by KeepBotting View Post
    and many others


    I think DreamBot can finally start updating their hooks on time, gg.

    EDIT: Also finally, finally I have something to read on for the upcoming weeks
    Feel free to ask me any questions, I will do my best to answer them!

    Previously known as YouPee.

  6. #6
    Join Date
    Nov 2016
    Posts
    31
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Thank you Kyle. Interesting to see where this will go. Looking forward to that tutorial.

  7. #7
    Join Date
    Feb 2012
    Location
    Canada
    Posts
    1,162
    Mentioned
    25 Post(s)
    Quoted
    433 Post(s)

  8. #8
    Join Date
    Sep 2016
    Posts
    1
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Glad I didnt bother you earlier! it seems like there has been a high frequency of updates lately; I was literally scratching my head on how you obtain the values in your hooks file.

    Thanks!


    wow... this is much more expansive than I could have guessed...
    Last edited by Gnossienne; 11-13-2016 at 07:25 PM.

  9. #9
    Join Date
    Feb 2013
    Location
    Rimmington
    Posts
    319
    Mentioned
    33 Post(s)
    Quoted
    183 Post(s)

    Default

    <33





  10. #10
    Join Date
    Mar 2012
    Posts
    107
    Mentioned
    2 Post(s)
    Quoted
    49 Post(s)

    Default

    I want to personally thank you for contributing to this community, great post.

  11. #11
    Join Date
    Apr 2007
    Posts
    373
    Mentioned
    2 Post(s)
    Quoted
    24 Post(s)

    Default

    So the following fields are outdated?
    How can i update them?
    I post them in the GitHub link.

    PHP Code:
    Broken Fields:
     ~> 
    SpokenText
     
    ~> CombatCycle
     
    ~> Health
     
    ~> MaxHealth 
    ~Fre

  12. #12
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default

    Quote Originally Posted by fre View Post
    So the following fields are outdated?
    How can i update them?
    I post them in the GitHub link.

    PHP Code:
    Broken Fields:
     ~> 
    SpokenText
     
    ~> CombatCycle
     
    ~> Health
     
    ~> MaxHealth 
    Yes, there's an issue already for it here. You can update it, but the entire health method in actor changed, so the include for simba needs to be rewritten for proper health support
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  13. #13
    Join Date
    Jan 2017
    Posts
    2
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    looks interesting thanks for sharing.

  14. #14
    Join Date
    Mar 2013
    Posts
    35
    Mentioned
    0 Post(s)
    Quoted
    8 Post(s)

    Default

    Looks good

  15. #15
    Join Date
    Mar 2013
    Posts
    1,010
    Mentioned
    35 Post(s)
    Quoted
    620 Post(s)

    Default

    Quote Originally Posted by AFools View Post
    I am absolutely stumped.. i managed to get the Update working last hook update. But now it keeps downloading Rev 129

    Has this major update broken something in the updater? that Sir. Kyle needs too fix or am i still noob at this?
    https://github.com/KyleHunter/Java-C...dater.java#L12
    #slack4admin2016
    <slacky> I will build a wall
    <slacky> I will ban reflection and OGL hooking until we know what the hell is going on

  16. #16
    Join Date
    Dec 2007
    Posts
    2,112
    Mentioned
    71 Post(s)
    Quoted
    580 Post(s)

    Default

    @AFools; Just change the revision to 133 and re-run the updater.

  17. #17
    Join Date
    Apr 2013
    Posts
    680
    Mentioned
    13 Post(s)
    Quoted
    341 Post(s)

    Default

    that didn't work. have you both been able to update your hooks successfully?

    I delete the previous posts to keep this thread tidy*** but i would love a reply. even by pm

    <------------------>



  18. #18
    Join Date
    Dec 2007
    Posts
    2,112
    Mentioned
    71 Post(s)
    Quoted
    580 Post(s)

    Default

    Quote Originally Posted by AFools View Post
    that didn't work. have you both been able to update your hooks successfully?

    I delete the previous posts to keep this thread tidy*** but i would love a reply. even by pm
    Simba Code:
    const
        ReflectionRevision = '133';
    {Node: db}
     Node_Prev: THook =                  ['cv', 1];
     Node_UID: THook =                   ['cg', 1];
     Node_Next: THook =                  ['cz', 1];

    {Cacheable: dh}

    {Renderable: cg}
     Renderable_ModelHeight: THook =     ['cw', -741542225];

    {Animable: av}

    {Model: cu}

    {AnimationSequence: gc}

    {NpcDefinition: gl}
     NpcDefinition_Actions: THook =      ['u', 1];
     NpcDefinition_Name: THook =         ['j', 1];
     NpcDefinition_ID: THook =           ['w', -644397589];
     NpcDefinition_CombatLevel: THook =  ['m', 492855685];

    {linkedList: dk}
     linkedList_Head: THook =            ['k', 1];
     linkedList_Current: THook =         ['y', 1];

    {Actor: aq}
     Actor_QueueX: THook =               ['ck', 1];
     Actor_QueueY: THook =               ['cy', 1];
     Actor_QueueSize: THook =            ['cu', 50188383];
     Actor_WorldX: THook =               ['aq', -1277733559];
     Actor_WorldY: THook =               ['aw', 904629673];
     Actor_Animation: THook =            ['bf', -914774871];
     Actor_SpokenText: THook =           ['NULL', 1];
     Actor_CombatCycle: THook =          ['NULL', 1];
     Actor_Health: THook =               ['NULL', 1];
     Actor_MaxHealth: THook =            ['NULL', 1];
     Actor_InteractingIndex: THook =     ['bz', 988218421];

    {Npc: am}
     Npc_Definition: THook =             ['k', 1];

    {ObjectDefinition: gb}
     ObjectDefinition_Actions: THook =   ['aw', 1];
     ObjectDefinition_Name: THook =      ['g', 1];

    {Buffer: fm}

    {Widget: ee}
     Widget_Children: THook =            ['ex', 1];
     Widget_ItemID: THook =              ['ep', 2019303675];
     Widget_ItemAmount: THook =          ['ew', -857758291];
     Widget_WidgetID: THook =            ['i', -1084644105];
     Widget_Name: THook =                ['cn', 1];
     Widget_Text: THook =                ['bt', 1];
     Widget_IsHidden: THook =            ['ai', 1];
     Widget_AbsoluteY: THook =           ['ap', 443329775];
     Widget_AbsoluteX: THook =           ['x', -1357818025];
     Widget_RelativeY: THook =           ['aj', 1042321287];
     Widget_RelativeX: THook =           ['af', 922112325];
     Widget_Width: THook =               ['aq', 1692967795];
     Widget_Height: THook =              ['aw', 1871365705];
     Widget_ParentID: THook =            ['aa', -119763401];
     Widget_ScrollY: THook =             ['aj', 1042321287];
     Widget_ScrollX: THook =             ['af', 922112325];
     Widget_InvIDs: THook =              ['ei', 1];
     Widget_BoundsIndex: THook =         ['ea', -1167966953];
     Widget_StackSizes: THook =          ['et', 1];

    {WidgetNode: t}
     WidgetNode_Id: THook =              ['k', -264141929];

    {HashTable: dw}
     HashTable_Buckets: THook =          ['y', 1];
     HashTable_Size: THook =             ['k', 1];
     HashTable_Index: THook =            ['w', 1];

    {GameShell: dr}

    {Player: e}
     Player_Name: THook =                ['k', 1];
     Player_Definition: THook =          ['y', 1];
     Player_CombatLevel: THook =         ['q', 780783815];

    {Client: client}
     Client_LoopCycle: THook =           ['client.u', -1160915299];
     Client_MenuOptions: THook =         ['client.iw', 1];
     Client_MenuActions: THook =         ['client.ik', 1];
     Client_IsMenuOpen: THook =          ['client.hi', 1];
     Client_MenuX: THook =               ['fq.hk', -1705421671];
     Client_MenuY: THook =               ['hp.hw', 1166704265];
     Client_MenuWidth: THook =           ['ce.hc', 352118349];
     Client_MenuHeight: THook =          ['f.ht', 1699315237];
     Client_MenuCount: THook =           ['client.hf', -676073067];
     Client_Region: THook =              ['be.dl', 1];
     Client_Plane: THook =               ['az.gu', -202288423];
     Client_LocalPlayers: THook =        ['client.gd', 1];
     Client_DestinationY: THook =        ['client.my', -1853127321];
     Client_DestinationX: THook =        ['client.mz', -2089549517];
     Client_LocalPlayer: THook =         ['ck.hm', 1];
     Client_BaseX: THook =               ['ds.dj', 148386865];
     Client_BaseY: THook =               ['aw.dv', -2113345181];
     Client_Widgets: THook =             ['ee.k', 1];
     Client_GameSettings: THook =        ['ea.o', 1];
     Client_CurrentLevels: THook =       ['client.hj', 1];
     Client_RealLevels: THook =          ['client.hg', 1];
     Client_Experiences: THook =         ['client.hd', 1];
     Client_Weight: THook =              ['client.jb', 896323235];
     Client_Energy: THook =              ['client.jl', -1201387633];
     Client_CurrentWorld: THook =        ['client.j', -991946675];
     Client_WidgetNodeCache: THook =     ['client.it', 1];
     Client_TileSettings: THook =        ['g.y', 1];
     Client_TileHeights: THook =         ['g.k', 1];
     Client_LocalNpcs: THook =           ['client.ch', 1];
     Client_NpcIndices: THook =          ['client.ct', 1];
     Client_CrossHairColor: THook =      ['client.gx', 1273935027];
     Client_MapOffset: THook =           ['client.ed', 1960296863];
     Client_MapAngle: THook =            ['client.fb', -701834271];
     Client_MapScale: THook =            ['client.et', 1198943407];
     Client_CameraPitch: THook =         ['gv.fy', -1960299599];
     Client_Sine: THook =                ['cy.e', 1];
     Client_Cosine: THook =              ['cy.l', 1];
     Client_CameraYaw: THook =           ['r.fm', -1354163607];
     Client_CameraZ: THook =             ['ai.fe', -641523113];
     Client_CameraX: THook =             ['gk.fc', 1755627167];
     Client_CameraY: THook =             ['p.fo', -1666790629];
     Client_GroundItems: THook =         ['client.hp', 1];
     Client_LoginState: THook =          ['client.f', -398258759];
     Client_PlayerIndex: THook =         ['client.gn', 1012417049];
     Client_WidgetPositionX: THook =     ['client.lz', 1];
     Client_WidgetPositionY: THook =     ['client.lx', 1];
     Client_WidgetWidths: THook =        ['client.lb', 1];
     Client_WidgetHeights: THook =       ['client.le', 1];

    {Region: ca}
     Region_SceneTiles: THook =          ['j', 1];

    {BoundaryObject: cz}
     BoundaryObject_ID: THook =          ['d', 361638875];
     BoundaryObject_Flags: THook =       ['n', 237331929];
     BoundaryObject_LocalX: THook =      ['y', -1960985619];
     BoundaryObject_LocalY: THook =      ['o', -151355893];
     BoundaryObject_Plane: THook =       ['k', 881373909];
     BoundaryObject_Render: THook =      ['j', 1];
     BoundaryObject_Render2: THook =     ['q', 1];
     BoundaryObject_Orientation: THook = ['r', -825712711];
     BoundaryObject_Height: THook =      ['w', 390668661];

    {GameObject: cr}
     GameObject_ID: THook =              ['i', -1720341121];
     GameObject_Flags: THook =           ['v', -1821318125];
     GameObject_Plane: THook =           ['k', -1974480323];
     GameObject_WorldX: THook =          ['o', -86230869];
     GameObject_WorldY: THook =          ['r', 691719557];
     GameObject_Height: THook =          ['y', 40754033];
     GameObject_Render: THook =          ['w', 1];
     GameObject_Orientation: THook =     ['j', -484814025];
     GameObject_LocalX: THook =          ['q', -471364253];
     GameObject_LocalY: THook =          ['n', -627130765];
     GameObject_OffsetX: THook =         ['d', 1028189815];
     GameObject_OffsetY: THook =         ['c', 2076095165];

    {FloorDecoration: ci}
     FloorDecoration_Render: THook =     ['r', 1];
     FloorDecoration_LocalX: THook =     ['y', -1753048791];
     FloorDecoration_LocalY: THook =     ['o', 775897375];
     FloorDecoration_Plane: THook =      ['k', 1530199991];
     FloorDecoration_ID: THook =         ['w', 1076621313];
     FloorDecoration_Flags: THook =      ['j', 1465975205];

    {WallDecoration: cm}
     WallDecoration_ID: THook =          ['c', 1404301829];
     WallDecoration_Flags: THook =       ['s', -2031378505];
     WallDecoration_LocalX: THook =      ['y', 1989015177];
     WallDecoration_LocalY: THook =      ['o', 1606769689];
     WallDecoration_Plane: THook =       ['k', 1715294221];
     WallDecoration_Renderable: THook =  ['d', 1];
     WallDecoration_Renderable2: THook = ['n', 1];
     WallDecoration_Orientation: THook = ['r', -428581447];
     WallDecoration_Height: THook =      ['w', 1520110451];
     WallDecoration_RelativeX: THook =   ['j', 1216538467];
     WallDecoration_RelativeY: THook =   ['q', 902214613];

    {SceneTile: ct}
     SceneTile_GameObject: THook =       ['g', 1];
     SceneTile_BoundaryObject: THook =   ['q', 1];
     SceneTile_WallDecoration: THook =   ['d', 1];
     SceneTile_GroundDecoration: THook = ['n', 1];

    {Item: au}
     Item_ID: THook =                    ['k', -1628923779];
     Item_StackSizes: THook =            ['y', 2022815601];

  19. #19
    Join Date
    May 2013
    Posts
    98
    Mentioned
    1 Post(s)
    Quoted
    33 Post(s)

    Default

    I ran this and it updated my hooks, most reflection stuff seemed OK but all my functions for using inv items dont work

    then I ran

    Simba Code:
    myInvArray.getAll;
    writeln(high(myInvArray));

    and it returned -1.

    For Item the hooks were:
    StackSizes : ao.f * -789244747
    ID : ao.i * -166911529

    Anyone else getting this? if not can some1 post the item hooks lol

  20. #20
    Join Date
    Dec 2017
    Posts
    3
    Mentioned
    0 Post(s)
    Quoted
    2 Post(s)

    Default

    I'm looking at Method.java (redundant/unused method deobber) and wondering two things:

    Code:
        public int Deob() {
            int Total = 0;
            int Fixed = 10;
            while (Fixed != 0) {
                Fixed = Run();
                Total = Total + Fixed;
            }
            System.out.print("Removed " + Total + " Dummy Methods");
            return Total;
        }
    The while loop here I think means that it is doing multiple passes over the class nodes; why does it take more than one pass to remove all of the unused methods?

    Code:
            for (ClassNode Class : CLASSES.values()) {
                getInterfaces(Class);
                getInvoked(Class);
                List<MethodNode> Methods = Class.methods;
                for (MethodNode Method : Methods) {
                    totalMethods.add(new MethodInfo(Class.name, Method.name, Method.desc));
                    if (Method.name.length() > 2 || Modifier.isAbstract(Method.access) || isOverridden(Class, Method)) {
                        MethodInfo mInfo = new MethodInfo(Class.name, Method.name, Method.desc);
                        Add(mInfo, goodMethods);
                    }
                }
            }
    Here it is considering any method with a name length > 2 as a used method. Why is that? Is this specific to Jagex's obfuscation or am I missing something obvious here.

    thanks

  21. #21
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by jknox View Post
    ...

    There is no method in the entire obfuscated jar that is more than 2 letters UNLESS it is a JDK method.. This also goes for class names and field names (with the exception of "client"). It's the way Jagex's obfuscator works. In my own de-obber, I don't check for name length because I use mine for RS3 as well..

    Also, it does multiple passes because if one unused method is calling another method, that other method wouldn't have been registered as "un-used" the first time around.. So once you do the first pass, you will now have new un-used methods that aren't called by any other methods or any other unused methods.. Therefore multiple passes helps in this case. It's easier to do multiple passes rather than storing a stack of possible unused methods.


    Example:

    1st pass (scan for unused methods and remove them):
    Java Code:
    void foo() {  //Foo is unused..  Will be removed at the end of the first pass.
         int i = 0;
         print(bar(i));  //Bar is being used..
    }

    int bar(int i) {  //Unused parameter.
        return 0;
    }

    2nd pass (scan for new unused methods and remove them): foo ()V was removed in the first pass..
    Java Code:
    int bar(int i) {  //Unused parameter. Unused method.
        return 0;
    }

    3rd pass..: -- bar (I)I removed in the second pass..
    Last edited by Brandon; 12-12-2017 at 03:02 AM.
    I am Ggzz..
    Hackintosher

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •