Welcome to June’s Progress Report! This month saw a wide variety of… bzzzt we interrupt this broadcast for an important announcement!
RPCS3’s progress reports are written solely by volunteers and we’re looking for more dedicated writers to help us write them. If you have the knowledge, time and are willing to help, please apply here. And secondly, we have recently added functionality that makes it possible to unlock the framerate limit of many games. While this exciting new feature doesn’t work on every game, some big titles such as Uncharted 1-3, The Last of Us, Red Dead Redemption and more are able to go over their framerate cap of 30FPS for the first time! We require the help of the community to submit test results for as many games as possible to determine the effectiveness of the feature. For more details, please click here.
Now back to our regular coverage! This month saw a wide variety of important contributions from both lead developers, Nekotekina and kd-11 as well as many of our usual contributors. June also marked an important milestone in compatibility for the emulator as shown below. In this report, we’ll be going over the implementation of native MSAA in RPCS3 and mutli-threaded RSX workload support, as well as improvements to PPU scheduling and a significant overhaul to the DevOps environment.
In addition to the following report, further details of Nekotekina and kd-11’s work during June and upcoming contributions can be found in their weekly reports on Patreon. This month’s Patreon reports are:
Table of Contents
Although June was a slow month for compatibility improvements due to our testers taking a break, it did quietly mark the monumental milestone of the Playable category finally becoming the largest category in our compatibility list! This came to fruition from years of development, testing and re-working to ensure a perfect balance of accuracy and performance to emulate the PlayStation 3. While there is still much to be done, the momentum from these milestones continue to accelerate development. In addition to this, the Intro and Loadable categories decreased due to a few games being moved to Ingame or Playable for the first time. The Ingame category also saw a net decrease due to further maintenance done by merging duplicate game entries. This culminated into our second milestone, where the combined percentage of the Loadable and Nothing categories dropped below 1% for the very first time!
On Git statistics, there have been 24284 lines of code added and 14514 removed through 42 pull requests by 12 authors.
Major RPCS3 Improvements
For many months now, kd-11 has been systematically reworking the texture cache implementation in RPCS3 to behave much closer to the PlayStation 3. His work has made massive progress and fixed countless issues, all of which we have detailed in previous progress reports. This month, kd-11 finished the final piece of the puzzle, the feature that necessitated such a large re-implementation, Multisample anti-aliasing (MSAA). The PlayStation 3 had support for a few anti-aliasing techniques such as MSAA and CSAA for which support was previously not present in the emulator. Implementing these anti-aliasing techniques saw significant roadblocks early on due to the vast difference in implementation of these techniques between the PlayStation 3’s RSX and modern PC GPUs. As a stopgap measure, RPCS3 used primitive workarounds to notify games that MSAA was correctly working when in fact it was not. This led to worse image quality at native resolution (720p) on RPCS3 as compared to a PlayStation 3. However, with the introduction of resolution upscaling in 2017, the need for MSAA diminished as users were able to wipe out most aliasing by simply supersampling graphics i.e. setting the internal resolution to 4K and subsequently downsampling the image to the monitor’s resolution (1080p or 1440p). Throw in additional enhancements like anisotropic filtering and users were able to obtain graphics far exceeding the native hardware.
However, this was still a workaround and not the complete solution. Certain games (such as Red Dead Redemption) used MSAA on specific objects in the image (such as foliage) which simple supersampling could not replicate. After analysing the components that needed to be improved, kd-11 shared a broad roadmap to patreons detailing the work that was to be done to bring true MSAA support in RPCS3. Now that all items on that roadmap have been completed, kd-11 was confident that the roadblocks identified years ago were finally overcome and began work on implementing true MSAA support.
But nobody really expected this task to go ahead smoothly which became evident almost immediately. At the outset itself, kd-11 ran into quite a few issues. For starters, even with the basic implementation of MSAA, FPS of many games dropped to single digits. RPCS3 has come a long way since the seconds-per-frame era and kd-11 had no intention to take us back there. Debugging these issues, he identified significant hardware occupancy problems which were summarily addressed, bring performance back to normal. However, this was followed by even greater challenges as MSAA is one of the most heavily guarded techniques. Memory used for stencil buffering with multisampling is completely cut off from write access on NVIDIA GPUs. There are easy ways to tackle this on AMD GPUs, but all supported hardware needs to be taken into account to implement this feature successfully. While initialisation on NVIDIA GPUs is easily doable with CPU assistance, we are required to run a stencil test loop through all possible values which is simply too slow for RPCS3’s requirements. After discussion with other developers in the DXVK discord, kd-11 opted to iterate through all bits instead of all values for NVIDIA GPUs which reduced task complexity by a factor of 8. While this still left NVIDIA GPUs to potentially be 5 times slower than AMD GPUs in processing MSAA, it was thankfully enough to make MSAA easily usable on either GPU.
While the current implementation only supports a restricted version of MSAA that matches the PlayStation 3 layout, kd-11 plans to improve this further to allow more flexible options to be enabled to obtain visuals far exceeding the original hardware in every aspect. Many AAA games (such as Red Dead Redemption, Crysis series, Killzone series, Ratchet & Clank series etc.) rely on MSAA for proper visuals, and as you can see in the images below, visuals are leagues better with this feature enabled.
As a word of caution, please note that MSAA is now enabled by default in RPCS3 which increases the GPU utilisation in titles where this feature is used heavily. Anyone who has used RPCS3 before will know that previously, with most games there was no impact to performance when moving from native resolution to an internal resolution of even 4K on most modern GPUs. However, with the implementation of MSAA, some games may utilise MSAA x4 or even x8 and multiplying the internal resolution by 300% (to achieve 4K) may cause these effects to also multiply by the same proportion, thereby killing performance due to excessive GPU load, causing a bottleneck. Users are advised to test various levels of upscaling (150%, 200%, 300% and so on) to determine the maximum resolution that can be used without impacting performance.
Multi-threading support for RSX workloads (#6112)
Next on his plate, kd-11 implemented a wide set of changes improving various system types. First up is the major change of the lot being the introduction of multi-threading for RSX tasks. The previous set-up saw all RSX tasks occurring on the same thread as it was designed with older CPUs in mind (typically 4 core CPUs with SMT). However, with the current landscape of CPUs releasing with a minimum of 6 cores with SMT, it was time to take advantage of additional resources available. kd-11 analysed areas where the RSX workloads can be easily parallelised and the resulting performance benefits from the same. This led to the implementation of an additional off-loader thread to handle all PCIe transfers (from CPU to GPU) in parallel with the FIFO frame processing.
Overall, the performance uplift is quite significant (especially with the Vulkan renderer), but unfortunately most games may not see the full benefit of this improvement just yet as the performance bottleneck would just be moved to other components of the emulator such as the SPU. While the framerate may not increase much in some games, the working time spent emulating the RSX goes down significantly. In purely PPU + RSX workloads, the performance jump is between 20-50% depending on the system. Also, if users experience flickering visuals with Multi-threaded RSX option enabled, it is a sign that the extra thread is being frequently unscheduled by the operating system and is not able to keep up due to lack of CPU resources. Keeping low core count CPUs in mind, this option is disabled by default. However, more fine-tuning is planned to improve the benefits seen to such users as well.
But kd-11 didn’t stop there, during the research stage of MSAA integration he uncovered major performance differences between AMD and NVIDIA GPUs (especially on Windows). With some quick profiling by contributor Whatcookie, it was revealed that there was an excessive amount of sampler objects being created with Vulkan, and that this step was much slower on AMD drivers compared to NVIDIA drivers. Following this report, kd-11 reimplemented the vertex layout streaming under Vulkan to a streaming model which improves performance by avoiding a costly descriptor copy on every sub-block of a batched draw. This fixed issues on Radeon cards where performance would drop into seconds-per-frame territory with some games.
Afterwards, kd-11 uncovered more problems with how RPCS3 was using Radeon GPUs while integrating MSAA functionality. Thanks to the GPUOpen project and the Radeon GPU profiler, he quickly identified the source of the issue being shader occupancy on some passes where shaders were big, complicated and consumed too much register space unnecessarily. Once kd-11’s work on MSAA integration was merged, he continued investigating some generated shaders and optimizing them by hand, noticing that some shaders were consuming almost 50% more registers while being 3-10x longer in terms of instruction count than needed. This was actually causing shader load problems in some games where, even with a shader cache, it would take too long to preload the shaders. kd-11 restructured the GLSL emitter to output more optimal code and allow the SPIR-V generated to consume fewer registers (VGPRs) and improve CU occupancy.
Another issue identified (especially with the Vulkan renderer) was that there were simply too many barriers in place. Every imaging operation was converting the layout to the expected layout, then doing more barriers and subsequently reverting this change after. This isn’t a problem if done once or twice, but this was happening way too often and causing a performance bottleneck. The solution implemented was to reduce unnecessary memory barriers and resulted in a 30% improvement to Polaris GPUs. Both the above issues mainly affected performance in lower-end systems and weak GPUs, so users with powerful systems may not see the same level of benefits.
Finally, testers had pointed out a few more games with RSX bottlenecks and further digging revealed new bottlenecks in Zcull and index buffer uploads. Index buffer processing was accelerated by using SSSE3 which has the potential for up to 4x faster 32-bit uploads and 8x faster 16-bit uploads. The Zcull job dispatch for the Vulkan renderer was also rewritten to change the model from a one-entry-per-draw to a one-entry-per-commandbuffer system which is much more efficient in games that utilize Zcull heavily.
This led to a large increase in performance across multiple titles and especially many 60FPS games that were stuck in the mid-40s can now hit 60FPS if other parts of the emulator allow it which should improve playability, especially in fighting games. To keep the comparisons fair, we have disabled Multi-threaded RSX support to accurately showcase the performance uplift from the optimisations described above:
Restructure frame submission mechanism (#6069)
Finally, kd-11 restructured frame submission mechanism in the Vulkan renderer to avoid the NVIDIA driver deadlock bug that appeared since the 400 series drivers. Previously, RPCS3 used a fence signal and explicit waiting followed by manually submitting to the present engine with no semaphores. The idea was to control frame submission from the application instead of letting the driver do it, but this triggered a nasty deadlock with the drivers, sometimes forcing a hard reset of the system to get Windows systems working again. This has been resolved by just doing what every other application does and use signal semaphores in the driver instead. This path is bug-free, likely since it’s the most commonly used method by other vulkan applications. While this completely fixed the deadlock bug with NVIDIA GPUs, it also drastically improved frame-pacing in multiple titles, virtually wiping out micro-stuttering that plagued Yakuza games.
kd-11 also implemented a frame management system that allows resources to be released properly when the RPCS3 window is minimized, improving overall system performance and ability to multi-task. Finally, he finished off with a code clean-up which may slightly improve performance due to less overhead.
You may or may not have heard but on May 15th 2019, Intel released new microcode updates to tackle a security vulnerability known as “MDS”. On Windows, users could optionally update to the newer microcode, while on Linux, most distros had the update available immediately. Users who received this update early may have noticed that RPCS3 was performing much slower. While it was easy to correlate the decrease in performance to the MDS mitigations, surprisingly they weren’t the real culprits for the loss.
The performance loss is actually the result of Intel resolving an unspecified erratum in their TSX implementation for Skylake+ CPUs. Intel doesn’t provide detailed release notes for microcode updates, so this information was actually gleaned through viewing old commit messages for the Linux kernel that were submitted by Intel employees. Luckily, it turns out that Intel added some new functionality that we can use to determine whether or not a specific CPU is impacted by this new microcode update. This new functionality is known as TSX_FORCE_ABORT. The presence of TSX_FORCE_ABORT indicates that a new MSR (model specific register) has been exposed with the ability to toggle On/Off 100% abort rate on TSX transactions. RPCS3 does not actually care for this feature, but every CPU that reports this feature can be considered to have a version of TSX which is known to behave differently.
Whatcookie, the new contributor to join our ranks, was responsible for researching and identifying the existence of TSX_FORCE_ABORT. Once this information came to light, he summarily implemented support in the emulator to detect the presence of this feature. If your CPU is affected, then you will now see TSX-FA appear in the second line of the log. In the latest version of RPCS3, many issues with TSX-FA have been resolved, but in the event you continue to experience issues, consider disabling TSX support in the Settings tab.
Once this detection was incorporated into RPCS3, Nekotekina aimed at improving the situation for users with the new microcode. To understand the purpose behind this change, we first need to understand a little about how TSX works. TSX allows us to write multi-threaded software that can operate without the need to use locks for synchronizing threads. After beginning a TSX transaction, any memory touched by that thread is marked as reserved. If another thread tries to touch that reserved memory, it will then cause an “abort” on the thread that reserved the memory, which means that it will roll back any changes made by the original thread, and then everything can continue on as normal. Previously, after aborting a transaction, the strategy was to simply try the TSX path again and again and again until it worked. However, with the latest microcode, the change in TSX implementation resulted in a massive increase in the abort rate, far beyond what is acceptable for RPCS3’s requirements thereby crippling performance. To alleviate this issue, Nekotekina implemented a fallback path where the emulator will now attempt to use the non-TSX path when it detects a high abort rate on the TSX path.
Our test case saw an improvement in performance from 30FPS up to 41FPS. This particular game saw 44FPS with the older microcode, and 39FPS with TSX disabled altogether. While the benefit of TSX has been reduced, it still offers users a performance uplift compared to the non-TSX path, which is always welcome! Nekotekina is also looking into further methods of improving the TSX path to bring performance back to previous levels. With that being said, in the event you experience a sudden decrease in performance and you see TSX-FA in your log, consider disabling TSX support for the time being.
RPCS3 is a massive project totalling over 1100 files and 70 folders (excluding submodules), and as such, it can be quite messy in places. While many volunteers and core members have spent significant time working on keeping the codebase clean, technical debt and other various cruft inevitably creeps in. In June, there was a spike in pull requests dedicated to cleaning up the project itself. While these changes have limited effects on game compatibility and performance, they do have a strong effect on keeping the project open to new contributors, as well as prevent new bugs from being introduced.
Compiler warnings – JohnHolmesII & MSuih
Anyone who has programmed before is certainly familiar with compiler warnings. For those who have not, here’s a brief overview: a compiler will review written code before compiling it, and during this review, it might emit warnings about things that it sees as potentially incorrect code, misleading code, or even stylistically poor code. Most projects are very particular about the way that warnings from the compiler are handled, with some even going so far as to refuse to accept any code that creates warnings. RPCS3, unfortunately, has been on the opposite end of the spectrum in this department.
RPCS3 did not have any additional warnings enabled besides the ones that are enabled by default in the compilers, which is not the best practice to follow. What’s worse is that despite not having many warnings enabled, thousands of warnings were still emitted at compile time. The automated Travis build system, for example, had logs stretching over 8000 lines, most of which were warnings. And if all of that was not enough, the warnings emitted across the 3 compilers used (GCC, Clang, and MSVC) were all different! MSVC being different is understandable, but GCC and Clang have very compatible warning info, and should have been very similar.
The situation was improved by two major contributions. The first, by JohnHolmesII, focused on the Unix side of things while the second, by MSuih, was a follow-up with a focus on cleaning up the warnings in MSVC. The CMake build system was slightly refactored, such that GCC and Clang are now treated as very similar compilers, with MSVC being the odd man out. The warning flag -Wall, a staple in just about any project and usually considered a minimum, was only now enabled for the Unix compilers, as a baseline. It turns out most of those thousands of warnings were trivial fixes, such as adjusting some data types. Some were a little sinister, such as a hidden truncation. Part of the refactor of CMake also included intentionally hiding some warnings which was done for two major reasons. The first being that not all warnings are good warnings, and the second being that fixing many of the existing warnings required significant effort from core developers. With this, the compiler warnings clean-up was a success, bringing the Travis log from over 8000 lines to around 1000 lines, with most lines now being normal compiler output. RPCS3 still has a ways to go in terms of warnings compliance, but significant headway has been made. An important side effect of cleaning up the warnings is that any new warnings introduced will stand out significantly, preventing them from ending up in the code base. Warning systems can be relatively self-maintaining, if they are enforced properly.
Clang-tidy, warnings and modernization – scribam
Finally, we’ll wrap up the major improvements section with the work done by contributor scribam, who went on an absolute tear of work into the nitty-gritty. First, he applied -Wpedantic to the codebase, and fixed a number of the warnings generated there. This warning flag is still not enabled by default, but this was a good start to getting there eventually. Then, scribam ran the linting utility clang-tidy over the codebase. A linting utility is a tool that looks for various issues in code, including everything from things that look like warnings to style recommendations. Importantly, tools like clang-tidy find out-of-date functions and coding techniques that may be harmful to the codebase. An example is the find_first_of and find_last_of string search functions built into the C++ standard library. Clang-tidy was able to remark that searching for single characters instead of entire substrings is substantially faster, allowing some areas of the RSX code that use these functions for shader parsing to become ever-so-slightly more efficient. Quite a number of readability and modernization related suggestions from clang-tidy were implemented, improving the maintainability of the codebase. His final contribution was to update the required GCC version to 8, as the modernization features require this.
DevOps can be nasty work sometimes, as it can seem like a great deal of effort for seemingly no tangible reward. Much of the updating of the codebase requires parsing hundreds of other people’s code, and despite helpful messages from linting tools, the proper changes are not always obvious. Still, this kind of work is necessary for the longevity of a project on this scale, and it is a never-ending task. There is still much more to be done in the short term, including a good deal more work on cleaning warnings, and working on updating the build environment for Windows to be as up to date as possible.
To kick off the games showcase for this month, we have Ubisoft’s first-person shooter Haze. This PlayStation 3 exclusive title previously suffered from graphical issues such as missing text and a permanent “yellow filter” while ingame. All these issues have now been fixed, allowing this title to be fully playable on RPCS3.
The successor to the infamous arcade american football game, Backbreaker Vengeance, finally became playable after the last remaining graphical issues were fixed by kd-11.
Kidou Senshi Gundam UC
Another Gundam title finds its way to playable with the last remaining bugs in Kidou Senshi Gundam UC being addressed. While this game had good performance and graphics, it would previously crash during certain custom cast scenarios. Thanks to the accuracy improvements with the emulator, all such issues have now been summarily fixed.
2010 FIFA World Cup: South Africa
One of the few FIFA titles to not arrive on PC, 2010 FIFA World Cup, finally became playable this month. Users who missed out on the World Cup can now enjoy this game on PC with RPCS3.
Fight Night Champion
The console exclusive boxing title, Fight Night Champion, now goes ingame on RPCS3. However, this game seems to suffer from low performance during the matches keeping it from being playable.
SEGA Rally Online Arcade
If anyone was looking forward to racing titles, look no further. This month SEGA Rally Online Arcade was found to safely go ingame. While the game seems to have good graphics, it suffers from low performance keeping it from being playable.
To finish off the list, this month saw DJ Hero progress past the title screen and go ingame! While the DJ turntables are still not supported on RPCS3, connecting a controller as a Guitar pad allows users to play the DJ-Guitar remix stages. Do note that users may be required to use cheats to unlock all songs and then play the guitar levels.
There have been numerous other pull requests merged during the month that couldn’t make it to the Major Improvements section. We have collected a list of all such improvements here, and attached a brief overview to each. Make sure to check out the links provided for them if you are interested, as their GitHub pages usually uncover further details as well as the code changes themselves. To see this whole list right on GitHub, click here.
6047 – Implemented std::bit_cast and utils::popcnt32, and also addressed certain warnings from the GCC compiler;
6050 – Fixed regression caused by the above pull request;
6060 – Changed PPU thread behaviour to yield on disk access operations;
6085 – Added a workaround in sys_rsx_context_iomap to prevent failure with CELL_EINVAL on vm::main;
6108 – Fixed regression affecting SPU loop detection after the above pull request;
6069 – Implemented frame management when the game window is minimized, allowing resources to be released properly; Removed unnecessary code from the window classes; Removed frame submission control from the application; Fixed the Vulkan fullscreen crash. See coverage in major improvements here;
6068 – Used std::atomic_thread_fence instead of _ReadWriteBarrier() with MSVC as the latter is deprecated;
6099 – Fixed undefined behaviour by trying to obey strict type aliasing rule in ppu_ref cache access;
6120 – Fixed a regression caused by the above pull request;
6115 – Fixed potential overflow in sys_vm;
6116 – Fixed Big-endian endianess arch support in semaphore_406e;
6143 – Prefer vm::ptr<>::ptr over vm::get_addr; Prefer vm::_ptr/base over vm::g_base_addr with offset; Added methods atomic_t<>::bts and atomic_t<>::btr; Removed obsolete rsx::thread::Read/WriteIO32 methods; Removed wrong check in semaphore_release; Added handling for PUTRx commands for RawSPU MFC proxy; Prefer overloaded methods of v128 instead of _mm_… in VPKSHUS ppu interpreter precise; Fixed more potential overflows that may result in wrong behaviour; Added io/size alignment check for sys_rsx_context_iounmap; Added rsx::constants::local_mem_base which represents RSX local memory base address; Removed obsolete rsx::thread::main_mem_addr/ioSize/ioAddress members;
6146 – Use vm::get_addr instead of manually subtracting vm::base(0) from pointer in texture cache code; Prefer std::atomic_thread_fence over _mm_?fence(), adjust usage to be more correct; Used sequentially consistent ordering in semaphore_release for TSX path; Improved memory ordering for sys_rsx_context_iounmap/map; Fixed sync bugs in HLE gcm; Use release memory barrier in lwsync for PPU LLVM;
6153 – Fixed regressions caused by the above pull request.
6061 – Optimised TextGlyphs used in RSX debug overlay;
6048 – Updated AppVeyor and Travis to use the newer Vulkan SDK; Updated VulkanMemoryAllocator to the latest tagged version; Updated stb_image.h and stb_truetype.h files;
6071 – Set minimum supported version of GCC to 8.1 and updated the documentation accordingly. Also, moved building instructions to dedicated BUILDING.md file with additional explanation on how to install GCC on Ubuntu systems. See coverage in major improvements here;
6065 – Added constexpr where necessary within RSX code;
6017 – Added FUNDING.yml that displays the “Sponsor” button at the top of the RPCS3 repository;
6092 – Removed unused variables.
6057 – Fixes an oversight in PR 4450 that added a slash to the game paths in games.yml whenever a game was booted. This bug led to funny paths such as: “C:/games/BLUS12345/PS3_GAME/USRDIR////////////////////////////////EBOOT.BIN”;
6081 – Fixed an issue with the Linux evdev pad handler that caused the KEY_BACK and KEY_HOMEPAGE buttons used by some gamepads to not register in-game. Usually these key IDs are used only by keyboards, but in some cases they are also chosen because the regular button IDs don’t represent the actual button as accurately as these key IDs. It’s a mystery how this bug wasn’t observed in the original implementation since it was added to fix exactly this issue. Currently only those two keys are supported. New keys will have to be added incrementally if the need arises;
6031 – Fixed in-game pad interception issues such as a bug that kept the pad input intercepted after a game aborted a message dialog while using the Qt dialogs instead of native UI dialogs. This caused an inability to control the game any further.
Native dialogs now also skip the on_close callback since it is not called in this function on an actual PlayStation 3. Also, fixed a bug that caused a subset of games to still receive input while native UI dialogs were open;
6095 – Added the option “Remove All Caches” to the game context menu. This removes all SPU, PPU and shader caches for the selected game;
6105 – Properly activates GUI buttons when rebinding your game pad with Linux evdev device handler. Previously, when using the evdev device handler, the buttons in the pad settings dialog were initially shown as disabled until you pressed a button;
6109 – Based on user feedback, increased the maximum mouse acceleration from 5 to 10;
6122 – Improved file decryption where previously users were only able to decrypt .sprx files using the GUI. Now users can decrypt .bin, .self, all binary files (.bin, .self, .sprx) and all other files. Also, the file endings of the decrypted files will be set to .elf in case of .bin or .self.
6096 – Allows linux to sleep in more situations when sys_timer_usleep is called and improved accuracy of usleep.
6138 – Added a timeout for vulkan device enumeration and adds a proper exit strategy.
6097 – Fixed dynamic_library::loaded.
6063 – Updated DualShock 3 message in Pads settings.
6067 – Corrected a typo.
As we mentioned at the start of this report, developer eladash has been working on ways to push performance in some games beyond their framerate limit in a generic way that doesn’t require per-game patches. And when we say the framerate limit, we’re not referring to only 30FPS. Some games that run natively at 60FPS on the PlayStation 3 can be pushed further as well, bringing the performance well past a 100FPS! To reiterate, if you wish to help the developers efforts of identifying games where this is possible, please click here.
We hope you liked this report and look forward to the next one! If you would like to contribute to the project, you can do so either by contributing code, helping the community or becoming a patron. RPCS3 has two full-time developers working on it who greatly benefit from the continued support of the many generous patrons. In exchange, patrons also get special support over on our Discord server and get access to early updates directly from our lead developers. If you are interested in supporting us, consider visiting our Patreon page at the link below and becoming a patron, or join our Discord server to learn about other ways of contribution.
We’re always looking for dedicated writers to help us write these reports. If you have the skill, time and are willing to help, please apply here. Also, come check out our YouTube channel and Discord to stay up-to-date with any big news.
This report was written by HerrHulaHoop, Asinine, JohnHolmesII, Whatcookie, Digitaldude555, Megamouse and MarioSonic2987.