DacoTaco / priiloader

A Wii homebrew application that can prevent and fix some user level bricks
GNU General Public License v2.0
544 stars 101 forks source link

Master / Slave hack support #238

Closed Leseratte10 closed 4 years ago

Leseratte10 commented 4 years ago

As discussed in #222, I started playing around with master / slave hacks.

This means, that there can be one master hack that is not shown in the Hacks Menu, that is compatible with all versions of the System Menu, and then there can be multiple Sub-Hacks / slave hacks that are version-dependant, which add additional version-dependant code related to the master hack.

This supports two new parameters in the hacks_hash.ini file, provide and require. A hack that has a provide parameter will be considered a master hack, and will be completely invisible in the Hacks menu (and will be disabled by default). A hack that has a require parameter that is the same as an existing master hack's provide value, will cause the corresponding master hack to be enabled and disabled simultaneously.

This means, there can be one hack with provide=wiimmfi-v1 that includes most of the Wiimmfi patch which is compatible with all versions, and then there will be many hacks, one for each version, with require=wiimmfi-v1 which include the region-dependant patches.

Let me know if this is something you would want to add, or if we want to stick to the full patches for Wiimmfi for each region. As of now, switching from full patches to this master/slave system brings the size of the Wiimmfi patch down from 88 kB to 10 kB, and that difference is only going to increase when support for more system menu versions is added in the future.

Making this a draft PR as well because I need to do some more testing to see if this works reliably.

Leseratte10 commented 4 years ago

And a generic comment about the lambdas: At least in Java (that's what I found web pages about), lambdas / lambda loop constructions are (as I expected) even slower than normal for loops, and only get an advantage when run in parallel (which we can't really do here): https://blog.jooq.org/2015/12/08/3-reasons-why-you-shouldnt-replace-your-for-loops-by-stream-foreach/ and I'd strongly suspect it'll be the same for C++.

No matter what syntax you use (for loop or lambda expression), the CPU is always going to need to look at every element in the array, load its parameter, and compare it; and then load the next element. A for loop is the simplest way to do that and I can't think of any reason why a lambda would make that faster. Especially not on PowerPC, maybe it does on x64 with all its optimizations. To be honest, I wouldn't be surprised if both the loop and the lambda expression would result in exactly the same PPC assembly.

Leseratte10 commented 4 years ago

Just implemented some of these fixes. The presence of a compatible master hack is now checked in the _addOrRejectHack function, which rejects the sub hack if no compatible master hack has been found. Also, I got rid of one of the for loops by merging it with another one.

I did look at adding lambda support, however I was unable to find out how to use std::find_if together with comparing a std::string element inside the struct in the array element. If you manage to find out how that works, feel free to add it, but I wouldn't keep that as a hard requirement. There are lots of other places in the code where it loops through the hacks array (loading them all from the file, deciding which hacks to display depending on version, deciding which hacks to display depending on the scroll position, actually applying all the enabled hacks (nested loop as well), ... ), all of which do even more with the hacks than checking one value and continue.

In the whole hacks.cpp file I didn't find one occurrence where a find_if is being used instead of a loop, so I can't even take that as an example. In your speed test, did you use a std::find_if over a simple int array? Or a std::find_if over a string that is included in a struct in an array?

Also, it's an array, in RAM, that has maybe 30 entries. Looping through that, even twice or multiple times, is still going to be way, way faster than looping through all the files on NAND (hacks_hash, hack states, ...). It's not like these loops are going to introduce any meaningful delay.


Please let me know if the current state is okay or if there is something else you want me to add.