Compare commits

...

23 Commits

Author SHA1 Message Date
Maschell 6fa1a45d68
Update README.md 2023-01-06 09:56:31 +01:00
Maschell 0c0f9f36e2 Add missing libs for linking to fix compiling 2019-05-14 22:29:28 +02:00
Maschell 2e51b9918d Update Readme: bulding instructions 2019-05-14 22:29:02 +02:00
Maschell 284912c3ea Stub libntfs usage. 2019-05-14 22:28:30 +02:00
Maschell 597e98d60a Fix the path to the portlibs.zip 2019-03-01 19:32:02 +01:00
Maschell 16fb3a7080 Formatting 2019-03-01 19:31:45 +01:00
Maschell 9442c5d62a Not log every hook call anymore 2019-03-01 19:27:01 +01:00
Maschell 8b0df7b6b8 Fix return type of checkMagic function 2019-03-01 19:26:36 +01:00
Maschell 81ce92aae7 Added support for the WUPS_LOADER_HOOK_VID_DRC_DRAW and WUPS_LOADER_HOOK_VID_TV_DRAW which allow a plugin to draw on the screen. 2019-03-01 19:26:15 +01:00
Maschell c29e3e77cd Add function TextureUtils::copyToTexture which allows to copy a given ColorBuffer to a GX2Texture 2019-03-01 19:23:21 +01:00
Maschell e647925e50 Implement function "HasHookCallHook(wups_loader_hook_type_t hook_type)" which returns true when a plugin exists that has implemented the given hook 2019-03-01 19:20:32 +01:00
Maschell 492571207d Implement support for DrawTexture hook 2019-03-01 19:18:03 +01:00
Maschell fb71817c33 Implementation of the ConvertImageToTexture function 2019-02-08 20:13:25 +01:00
Maschell 7ccc9e0b92 Fixed header 2019-02-08 19:15:59 +01:00
Maschell 7f491da297 Added support for the Video Memory hook. 2019-02-08 16:43:45 +01:00
Maschell 40bb31885a Patch __OSPhysicalToEffectiveCached,__OSPhysicalToEffectiveUncached, OSEffectiveToPhysical and OSIsAddressValid to be compatible with out own mapped memory. 2019-02-08 16:42:39 +01:00
Maschell 14d4ab0b5c Do memory mapping on default, remove some debug output and tests. 2019-02-08 16:40:37 +01:00
Maschell 2fc11412f3 Add PhysicaltoEffective and EffectiveToPhysical for own mapped memory. 2019-02-08 16:34:52 +01:00
Maschell 64e4ed5f71 Add memory region for area usable for the GPU 2019-02-08 12:49:49 +01:00
Maschell 2c743ec133 FIX: mark our mapped memory properly as executable 2019-02-08 12:44:14 +01:00
Maschell 9ed45f82de Load values from SD only once at the beginning. 2019-02-07 17:03:43 +01:00
Maschell e6f246b947 [CONFIG] Only load values from the SD Card at the beginning. Add a save to SD card when existing a application. 2019-02-07 16:37:13 +01:00
Maschell 993b328f4c add support for shoulder buttons in config menu 2019-02-07 13:04:26 +01:00
37 changed files with 1060 additions and 284 deletions

View File

@ -77,7 +77,7 @@ MAKEFLAGS += --no-print-directory
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lgui -lm -lgcc -lfat -lntfs -liosuhax -lutils -ldynamiclibs -lfreetype -lgd -lpng -ljpeg -lz -lmad -lvorbisidec
LIBS := -lgui -lm -lgcc -lfat -liosuhax -lutils -ldynamiclibs -lfreetype -lgd -lpng -ljpeg -lz -lmad -lvorbisidec -logg -lbz2
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@ -1,4 +1,6 @@
[Nightly builds](https://github.com/Maschell/WiiUPluginLoader/releases) | [Issue Tracker](https://github.com/Maschell/WiiUPluginLoader/issues) | [Discussion](https://gbatemp.net/threads/wii-u-plugin-system.496659/) | [Discord](https://discord.gg/bZ2rep2) | [Wiki](https://maschell.github.io/WiiUPluginSystem/dev_overview.html)
# This project is outdated, new version is at: https://github.com/wiiu-env/WiiUPluginLoaderBackend
[Nightly builds](https://github.com/Maschell/WiiUPluginLoader/releases) | [Issue Tracker](https://github.com/Maschell/WiiUPluginLoader/issues) | [Discussion](https://gbatemp.net/threads/wii-u-plugin-system.496659/) | [Discord](https://discord.gg/bZ2rep2) | [Wiki](https://maschell.github.io/WiiUPluginSystem/dev_overview.html)
# Wii U Plugin Loader [![Build Status](https://api.travis-ci.org/Maschell/WiiUPluginLoader.svg?branch=master)](https://travis-ci.org/Maschell/WiiUPluginLoader)
@ -33,10 +35,14 @@ This means it's not possible to combine this with other homebrews (yet).
Information on how to create plugin can be found in the [wiki](https://maschell.github.io/WiiUPluginSystem/dev_plugin_creation_overview.html).
## Building
Make sure the toolchain is uptodate `pacman -Syu devkitPPC devkitARM vim general-tools`
For building you need:
- [libiosuhax](https://github.com/dimok789/libiosuhax) (Build WITHOUT the WUT flag set.)
- [libfat](https://github.com/Maschell/libfat/) (Build with `make wiiu-release && make wiiu-install`)
- [dynamic_libs](https://github.com/Maschell/dynamic_libs/tree/lib) for access to the functions.
- [libutils](https://github.com/Maschell/libutils) for common functions.
- [libutils](https://github.com/Maschell/libutils) for common functions.
- [libgui](https://github.com/Maschell/libgui) for the gui elements.
Install them (in this order) according to their README's. Don't forget the dependencies of the libs itself.
@ -69,4 +75,4 @@ More information about wiiload and alternatives can be found here: http://wiibre
Some files are based on brainslug by Chadderz:
https://github.com/Chadderz121/brainslug-wii
Much stuff also wouldn't be possible without dimok789. He made many great tools and homebrew this stuff in based on (Makefiles, Mocha, homebrew channel, udp logger, dynamic_libs etc.)
Also thanks to everyone who made actual exploits.
Also thanks to everyone who made actual exploits.

View File

@ -1,12 +1,11 @@
#! /bin/bash
#
7z x -y ./loader/libs/portlibs.zip -o${DEVKITPRO}
7z x -y ./libs/portlibs.zip -o${DEVKITPRO}
mkdir portlib_repos
cd portlib_repos
((git clone https://github.com/Maschell/dynamic_libs.git -b lib && (7z x -y ./dynamic_libs/libs/portlibs.zip -o${DEVKITPRO})) || (cd dynamic_libs && git pull))
(git clone https://github.com/dimok789/libiosuhax.git || (cd libiosuhax && git pull))
(git clone https://github.com/Maschell/libfat.git || (cd libfat && git pull))
(git clone https://github.com/Maschell/libntfs-wiiu.git || (cd libntfs-wiiu && git pull))
(git clone https://github.com/Maschell/libutils.git || (cd libutils && git pull))
((git clone https://github.com/Maschell/libgui.git && (7z x -y ./libgui/libs/portlibs.zip -o${DEVKITPRO})) || (cd libgui && git pull))
(git clone https://github.com/Maschell/fs_wrapper.git || (cd fs_wrapper && git pull))
@ -14,7 +13,6 @@ cd portlib_repos
(cd dynamic_libs && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))
(cd libiosuhax && make -j8 && make install)
(cd libfat && make wiiu-release && make wiiu-install)
(cd libntfs-wiiu && make wiiu-install)
(cd libutils && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))
(cd libgui && ((make -j8 | grep -c "built ... ") && make install) || echo "no need for make install")
(cd fs_wrapper && ((make -j8 | grep -c "built ... ") && make install && echo "installed" ) || (echo "no need for make install" && make))

View File

@ -187,7 +187,7 @@ void Application::executeThread(void) {
bool result = linkPluginsCallback();
if(!result) {
// On linking errors return to the HBL.
#warning TODO: proper error handling when linking fails.
#warning TODO: proper error handling when linking fails.
exitCode = APPLICATION_CLOSE_MIIMAKER;
}
}

View File

@ -4,6 +4,7 @@ replacement_data_t gbl_replacement_data __attribute__((section(".data")));
dyn_linking_relocation_data_t gbl_dyn_linking_data __attribute__((section(".data")));
uint8_t gAppStatus __attribute__((section(".data"))) = 0;
bool g_NotInLoader __attribute__((section(".data"))) = false;
uint64_t gGameTitleID __attribute__((section(".data"))) = 0;
volatile uint8_t gSDInitDone __attribute__((section(".data"))) = 0;
@ -16,3 +17,10 @@ struct buffer_store tv_store __attribute__((section(".data")));
char gbl_common_data[0x20000] __attribute__((section(".data")));
char * gbl_common_data_ptr __attribute__((section(".data"))) = gbl_common_data;
GX2ColorBuffer g_vid_main_cbuf __attribute__((section(".data")));
GX2Texture g_vid_drcTex __attribute__((section(".data")));
GX2Sampler g_vid_sampler __attribute__((section(".data")));
GX2Texture g_vid_tvTex __attribute__((section(".data")));
GX2ContextState* g_vid_ownContextState __attribute__((section(".data")));
GX2ContextState* g_vid_originalContextSave __attribute__((section(".data")))= NULL;

View File

@ -2,10 +2,14 @@
#define RETAINS_VARS_H_
#include "patcher/function_patcher.h"
#include "plugin/dynamic_linking_defines.h"
#include <dynamic_libs/gx2_functions.h>
extern replacement_data_t gbl_replacement_data;
extern dyn_linking_relocation_data_t gbl_dyn_linking_data;
extern bool g_NotInLoader;
extern uint8_t gAppStatus;
extern uint64_t gGameTitleID;
extern volatile uint8_t gSDInitDone;
@ -17,4 +21,11 @@ extern int32_t ntfs_mount_count;
extern struct buffer_store drc_store;
extern struct buffer_store tv_store;
extern GX2ColorBuffer g_vid_main_cbuf;
extern GX2Texture g_vid_drcTex;
extern GX2Texture g_vid_tvTex;
extern GX2ContextState* g_vid_ownContextState;
extern GX2ContextState* g_vid_originalContextSave;
extern GX2Sampler g_vid_sampler;
#endif // RETAINS_VARS_H_

View File

@ -20,16 +20,15 @@
*/
DefaultGuiSelectBox::DefaultGuiSelectBox(std::string caption, GuiFrame *parent)
: GuiSelectBox(NULL,caption)
,topBackgroundImg_imgdata(Resources::GetImageData("gameSettingsButton.png"))
,topBackgroundImg_img(topBackgroundImg_imgdata)
,topHighlightedImg_imgdata(Resources::GetImageData("gameSettingsButtonSelected.png"))
,topHighlightedImg_img(topHighlightedImg_imgdata)
,valueImageData(Resources::GetImageData("gameSettingsButtonEx.png"))
,valueSelectedImageData(Resources::GetImageData("gameSettingsButtonExSelected.png"))
,valueHighlightedImageData(Resources::GetImageData("gameSettingsButtonExHighlighted.png"))
,buttonClickSound(Resources::GetSound("settings_click_2.mp3"))
{
: GuiSelectBox(NULL,caption)
,topBackgroundImg_imgdata(Resources::GetImageData("gameSettingsButton.png"))
,topBackgroundImg_img(topBackgroundImg_imgdata)
,topHighlightedImg_imgdata(Resources::GetImageData("gameSettingsButtonSelected.png"))
,topHighlightedImg_img(topHighlightedImg_imgdata)
,valueImageData(Resources::GetImageData("gameSettingsButtonEx.png"))
,valueSelectedImageData(Resources::GetImageData("gameSettingsButtonExSelected.png"))
,valueHighlightedImageData(Resources::GetImageData("gameSettingsButtonExHighlighted.png"))
,buttonClickSound(Resources::GetSound("settings_click_2.mp3")) {
setSize(topBackgroundImg_img.getWidth(),topBackgroundImg_img.getHeight());
this->setImageTopBackground(&topBackgroundImg_img);
this->setImageTopHighlighted(&topHighlightedImg_img);
@ -41,8 +40,7 @@ DefaultGuiSelectBox::DefaultGuiSelectBox(std::string caption, GuiFrame *parent)
/**
* Destructor for the DefaultGuiSelectBox class.
*/
DefaultGuiSelectBox::~DefaultGuiSelectBox()
{
DefaultGuiSelectBox::~DefaultGuiSelectBox() {
Resources::RemoveImageData(topBackgroundImg_imgdata);
Resources::RemoveImageData(topHighlightedImg_imgdata);
Resources::RemoveImageData(valueImageData);

View File

@ -20,26 +20,26 @@
#include <gui/GuiSelectBox.h>
//!A simple select box with default values.
class DefaultGuiSelectBox : public GuiSelectBox{
public:
//!Constructor
//!\param checked Checked
DefaultGuiSelectBox(std::string caption, GuiFrame *parent = NULL);
//!Destructor
virtual ~DefaultGuiSelectBox();
class DefaultGuiSelectBox : public GuiSelectBox {
public:
//!Constructor
//!\param checked Checked
DefaultGuiSelectBox(std::string caption, GuiFrame *parent = NULL);
//!Destructor
virtual ~DefaultGuiSelectBox();
protected:
GuiImageData * topBackgroundImg_imgdata;
GuiImage topBackgroundImg_img;
protected:
GuiImageData * topBackgroundImg_imgdata;
GuiImage topBackgroundImg_img;
GuiImageData * topHighlightedImg_imgdata;
GuiImage topHighlightedImg_img;
GuiImageData * topHighlightedImg_imgdata;
GuiImage topHighlightedImg_img;
GuiImageData * valueImageData;
GuiImageData * valueSelectedImageData;
GuiImageData * valueHighlightedImageData;
GuiImageData * valueImageData;
GuiImageData * valueSelectedImageData;
GuiImageData * valueHighlightedImageData;
GuiSound * buttonClickSound;
GuiSound * buttonClickSound;
};
#endif

View File

@ -20,16 +20,15 @@
*/
DefaultGuiSwitch::DefaultGuiSwitch(bool checked)
: GuiSwitch(NULL,checked)
,switchbase_imgdata(Resources::GetImageData("switchIconBase.png"))
,switchbase_img(switchbase_imgdata)
,switchbase_highlighted_imgdata(Resources::GetImageData("switchIconBaseHighlighted.png"))
,switchbase_highlighted_img(switchbase_highlighted_imgdata)
,switchOn_imgdata(Resources::GetImageData("switchIconOn.png"))
,switchOn_img(switchOn_imgdata)
,switchOff_imgdata(Resources::GetImageData("switchIconOff.png"))
,switchOff_img(switchOff_imgdata)
{
: GuiSwitch(NULL,checked)
,switchbase_imgdata(Resources::GetImageData("switchIconBase.png"))
,switchbase_img(switchbase_imgdata)
,switchbase_highlighted_imgdata(Resources::GetImageData("switchIconBaseHighlighted.png"))
,switchbase_highlighted_img(switchbase_highlighted_imgdata)
,switchOn_imgdata(Resources::GetImageData("switchIconOn.png"))
,switchOn_img(switchOn_imgdata)
,switchOff_imgdata(Resources::GetImageData("switchIconOff.png"))
,switchOff_img(switchOff_imgdata) {
setSize(switchbase_img.getWidth(),switchbase_img.getHeight());
this->setImageBackground(&switchbase_img);
this->setImageHighlighted(&switchbase_highlighted_img);
@ -39,8 +38,7 @@ DefaultGuiSwitch::DefaultGuiSwitch(bool checked)
/**
* Destructor for the DefaultGuiSwitch class.
*/
DefaultGuiSwitch::~DefaultGuiSwitch()
{
DefaultGuiSwitch::~DefaultGuiSwitch() {
Resources::RemoveImageData(switchbase_imgdata);
Resources::RemoveImageData(switchbase_highlighted_imgdata);
Resources::RemoveImageData(switchOn_imgdata);

View File

@ -20,26 +20,26 @@
#include <gui/GuiSwitch.h>
//!A simple switch
class DefaultGuiSwitch : public GuiSwitch{
public:
//!Constructor
//!\param checked Checked
DefaultGuiSwitch(bool checked);
//!Destructor
virtual ~DefaultGuiSwitch();
class DefaultGuiSwitch : public GuiSwitch {
public:
//!Constructor
//!\param checked Checked
DefaultGuiSwitch(bool checked);
//!Destructor
virtual ~DefaultGuiSwitch();
protected:
GuiImageData * switchbase_imgdata = NULL;
GuiImage switchbase_img;
protected:
GuiImageData * switchbase_imgdata = NULL;
GuiImage switchbase_img;
GuiImageData * switchbase_highlighted_imgdata = NULL;
GuiImage switchbase_highlighted_img;
GuiImageData * switchbase_highlighted_imgdata = NULL;
GuiImage switchbase_highlighted_img;
GuiImageData * switchOn_imgdata = NULL;
GuiImage switchOn_img;
GuiImageData * switchOn_imgdata = NULL;
GuiImage switchOn_img;
GuiImageData * switchOff_imgdata = NULL;
GuiImage switchOff_img;
GuiImageData * switchOff_imgdata = NULL;
GuiImage switchOff_img;
};
#endif

View File

@ -52,7 +52,9 @@
#include "Application.h"
#include "patcher/function_patcher.h"
#include "patcher/hooks_patcher.h"
#include "patcher/hooks_patcher_static.h"
#include "plugin/dynamic_linking_defines.h"
#include "myutils/mem_utils.h"
#include "myutils/mocha.h"
#include "myutils/libntfs.h"
#include "myutils/libfat.h"
@ -95,8 +97,15 @@ extern "C" int32_t Menu_Main(int32_t argc, char **argv) {
init_kernel_syscalls();
wups_init_kernel_syscalls();
if(!MemoryMapping::isMemoryMapped()) {
MemoryMapping::setupMemoryMapping();
}
gGameTitleID = OSGetTitleID();
g_vid_ownContextState = NULL;
g_vid_originalContextSave = NULL;
int32_t result = 0;
//Reset everything when were going back to the Mii Maker
@ -129,13 +138,22 @@ extern "C" int32_t Menu_Main(int32_t argc, char **argv) {
memoryRelease();
CSettings::destroyInstance();
PluginLoader::destroyInstance();
MemoryUtils::init();
// Memory on custon heap is reset anyway so we don't need to free the image buffers.
memset((void*)&g_vid_main_cbuf,0,sizeof(g_vid_main_cbuf));
memset((void*)&g_vid_drcTex,0,sizeof(g_vid_drcTex));
memset((void*)&g_vid_tvTex,0,sizeof(g_vid_tvTex));
g_vid_originalContextSave = NULL;
g_vid_ownContextState = NULL;
g_NotInLoader = false;
} else {
g_NotInLoader = true;
}
if(result == APPLICATION_CLOSE_APPLY_MEMORY) {
if(!MemoryMapping::isMemoryMapped()) {
MemoryMapping::setupMemoryMapping();
}
}
DEBUG_FUNCTION_LINE("Patch own stuff\n");
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
DEBUG_FUNCTION_LINE("Do relocations\n");
@ -149,12 +167,11 @@ extern "C" int32_t Menu_Main(int32_t argc, char **argv) {
if(!isInMiiMakerHBL()) {
DEBUG_FUNCTION_LINE("Apply patches.\n");
ApplyPatchesAndCallHookStartingApp();
ConfigUtils::loadConfigFromSD();
if(MemoryMapping::isMemoryMapped()) {
DEBUG_FUNCTION_LINE("Mapping was already done. Running %016llX\n",gGameTitleID);
readAndPrintSegmentRegister(NULL,NULL);
MemoryMapping::readTestValuesFromMemory();
//MemoryMapping::readTestValuesFromMemory();
} else {
DEBUG_FUNCTION_LINE("<-----------------------------------------------------> \n");
DEBUG_FUNCTION_LINE("<---------------- COPY PASTE ME START-----------------> \n");
@ -169,9 +186,11 @@ extern "C" int32_t Menu_Main(int32_t argc, char **argv) {
}
if(result == APPLICATION_CLOSE_APPLY || result == APPLICATION_CLOSE_APPLY_MEMORY) {
CallHook(WUPS_LOADER_HOOK_INIT_VID_MEM);
CallHook(WUPS_LOADER_HOOK_INIT_KERNEL);
CallHook(WUPS_LOADER_HOOK_INIT_FS);
CallHook(WUPS_LOADER_HOOK_INIT_OVERLAY);
ConfigUtils::loadConfigFromSD();
CallHook(WUPS_LOADER_HOOK_INIT_PLUGIN);
DEBUG_FUNCTION_LINE("Loading the system menu.\n");
DeInit();
@ -191,6 +210,7 @@ extern "C" int32_t Menu_Main(int32_t argc, char **argv) {
}
void ApplyPatchesAndCallHookStartingApp() {
PatchInvidualMethodHooks(method_hooks_hooks_static, method_hooks_size_hooks_static, method_calls_hooks_static);
PatchInvidualMethodHooks(method_hooks_hooks, method_hooks_size_hooks, method_calls_hooks);
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
CallHookEx(WUPS_LOADER_HOOK_STARTING_APPLICATION,plugin_index);
@ -209,6 +229,7 @@ void RestorePatches() {
new_RestoreInvidualInstructions(&gbl_replacement_data.plugin_data[plugin_index]);
}
RestoreInvidualInstructions(method_hooks_hooks, method_hooks_size_hooks);
RestoreInvidualInstructions(method_hooks_hooks_static, method_hooks_size_hooks_static);
}
int32_t isInMiiMakerHBL() {

View File

@ -231,7 +231,7 @@ bool ContentHome::linkPlugins() {
void ContentHome::update(GuiController * c) {
ContentTemplate::update(c);
if(updateButtons){
if(updateButtons) {
for (auto const& x : selectionMapping) {
int index = x.first;
GuiToggle* toggle = x.second;

View File

@ -8,20 +8,17 @@
extern "C" {
#endif
typedef struct _sr_table_t
{
typedef struct _sr_table_t {
uint32_t value[16];
uint32_t sdr1;
} sr_table_t;
typedef struct _bat_t
{
typedef struct _bat_t {
uint32_t h;
uint32_t l;
} bat_t;
typedef struct _bat_table_t
{
typedef struct _bat_table_t {
bat_t bat[8];
} bat_table_t;

View File

@ -58,22 +58,23 @@ static void KernelWriteSRs(sr_table_t * table) {
// Writing didn't work for all at once so we only write number 8.
// TODO: fix this and change it if required.
/*asm volatile("mtsr 0, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 1, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 2, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 3, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 4, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 5, %0" : : "r" (table->value[i])); i++;*/
//asm volatile("mtsr 6, %0" : : "r" (table->value[6])); i++;
/*asm volatile("mtsr 7, %0" : : "r" (table->value[i])); i++;*/
asm volatile("mtsr 8, %0" : : "r" (table->value[8])); i++;
/*asm volatile("mtsr 9, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 10, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 11, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 12, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 13, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 14, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 15, %0" : : "r" (table->value[i])); i++;*/
/*asm volatile("mtsr 0, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 1, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 2, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 3, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 4, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 5, %0" : : "r" (table->value[i])); i++;*/
//asm volatile("mtsr 6, %0" : : "r" (table->value[6])); i++;
/*asm volatile("mtsr 7, %0" : : "r" (table->value[i])); i++;*/
asm volatile("mtsr 8, %0" : : "r" (table->value[8]));
i++;
/*asm volatile("mtsr 9, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 10, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 11, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 12, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 13, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 14, %0" : : "r" (table->value[i])); i++;
asm volatile("mtsr 15, %0" : : "r" (table->value[i])); i++;*/
asm volatile("isync");
@ -87,7 +88,7 @@ void KernelReadPTE(uint32_t* dest, uint32_t size) {
asm volatile("mfmsr %0" : "=r" (msr));
oldmsr = msr;
msr &= ~0x10;
for(uint32_t i = 0;i<size/0x04;i++){
for(uint32_t i = 0; i<size/0x04; i++) {
uint32_t value_read = 0;
uint32_t addr = addr_base + (i*4);
// Disable Data address translation
@ -107,7 +108,7 @@ void KernelWritePTE(uint32_t * in_addr, uint32_t size) {
asm volatile("mfmsr %0" : "=r" (msr));
oldmsr = msr;
msr &= ~0x10;
for(uint32_t i = 0;i<size/0x04;i++){
for(uint32_t i = 0; i<size/0x04; i++) {
uint32_t addr = addr_base + (i*4);
uint32_t value = in_addr[i];
// Disable Data address translation
@ -135,7 +136,7 @@ void KernelWriteWitoutDAT(uint32_t addr, uint32_t value) {
void SC0x0A_KernelWriteWitoutDAT(uint32_t addr,uint32_t value);
void wups_init_kernel_syscalls(){
void wups_init_kernel_syscalls() {
//! assign 1 so that this variable gets into the retained .data section
static uint8_t ucSyscallsSetupRequired = 1;
if(!ucSyscallsSetupRequired)

View File

@ -76,6 +76,14 @@ uint32_t MemoryMapping::getHeapSize() {
return getAreaSizeFromPageTable(MEMORY_START_PLUGIN_HEAP,MEMORY_START_PLUGIN_HEAP_END - MEMORY_START_PLUGIN_HEAP);
}
uint32_t MemoryMapping::getVideoMemoryAddress() {
return MEMORY_START_VIDEO_SPACE;
}
uint32_t MemoryMapping::getVideoMemorySize() {
return getAreaSizeFromPageTable(MEMORY_START_VIDEO_SPACE,MEMORY_START_VIDEO_SPACE_END - MEMORY_START_VIDEO_SPACE);
}
void MemoryMapping::searchEmptyMemoryRegions() {
DEBUG_FUNCTION_LINE("Searching for empty memory.\n");
@ -325,7 +333,7 @@ void MemoryMapping::setupMemoryMapping() {
// This is nice because it leads to SR[8] which also seems to be unused (was set to 0x30FFFFFF)
// The content of the segment was chosen randomly.
uint32_t segment_index = MEMORY_START_BASE >> 28;
uint32_t segment_content = 0x20000000 | SEGMENT_UNIQUE_ID;
uint32_t segment_content = 0x00000000 | SEGMENT_UNIQUE_ID;
DEBUG_FUNCTION_LINE("Setting SR[%d] to %08X\n",segment_index,segment_content);
srTableCpy.value[segment_index] = segment_content;
@ -349,10 +357,10 @@ void MemoryMapping::setupMemoryMapping() {
runOnAllCores(readAndPrintSegmentRegister,NULL,0,16,0x80000);
searchEmptyMemoryRegions();
//searchEmptyMemoryRegions();
writeTestValuesToMemory();
readTestValuesFromMemory();
//writeTestValuesToMemory();
//readTestValuesFromMemory();
}
@ -549,9 +557,8 @@ void MemoryMapping::printPageTableTranslation(sr_table_t srTable, uint32_t * tra
for(std::vector<pageInformation>::iterator it = pageInfos.begin(); it != pageInfos.end(); ++it) {
pageInformation cur = *it;
// TODO: print if it's executable
DEBUG_FUNCTION_LINE("%08X %08X -> %08X %08X. user access %s. supervisor access %s. %s\n",cur.addr,cur.addr+cur.size,cur.phys,cur.phys+cur.size,cur.kp ? access2[cur.pp] : access1[cur.pp],
cur.ks ? access2[cur.pp] : access1[cur.pp],cur.nx? " not executable " : " executable");
cur.ks ? access2[cur.pp] : access1[cur.pp],cur.nx? "not executable" : "executable");
}
}
@ -676,3 +683,66 @@ bool MemoryMapping::mapMemory(uint32_t pa_start_address,uint32_t pa_end_address,
return true;
}
uint32_t MemoryMapping::PhysicalToEffective(uint32_t phyiscalAddress) {
uint32_t result = 0;
const memory_values_t * curMemValues = NULL;
int32_t curOffset = 0;
//iterate through all own mapped memory regions
for(int32_t i = 0; true; i++) {
if(mem_mapping[i].physical_addresses == NULL) {
break;
}
curMemValues = mem_mapping[i].physical_addresses;
uint32_t curOffsetInEA = 0;
// iterate through all memory values of this region
for(int32_t j= 0; true; j++) {
if(curMemValues[j].end_address == 0) {
break;
}
if(phyiscalAddress >= curMemValues[j].start_address && phyiscalAddress < curMemValues[j].end_address) {
// calculate the EA
result = (phyiscalAddress - curMemValues[j].start_address) + (mem_mapping[i].effective_start_address + curOffsetInEA);
return result;
}
curOffsetInEA += curMemValues[j].end_address - curMemValues[j].start_address;
}
}
return result;
}
uint32_t MemoryMapping::EffectiveToPhysical(uint32_t effectiveAddress) {
uint32_t result = 0;
// CAUTION: The data may be fragmented between multiple areas in PA.
const memory_values_t * curMemValues = NULL;
int32_t curOffset = 0;
for(int32_t i = 0; true; i++) {
if(mem_mapping[i].physical_addresses == NULL) {
break;
}
if(effectiveAddress >= mem_mapping[i].effective_start_address && effectiveAddress < mem_mapping[i].effective_end_address) {
curMemValues = mem_mapping[i].physical_addresses;
curOffset = mem_mapping[i].effective_start_address;
break;
}
}
if(curMemValues == NULL) {
return result;
}
for(int32_t i= 0; true; i++) {
if(curMemValues[i].end_address == 0) {
break;
}
int32_t curChunkSize = curMemValues[i].end_address - curMemValues[i].start_address;
if(effectiveAddress < (curOffset + curChunkSize)) {
result = (effectiveAddress - curOffset) + curMemValues[i].start_address;
break;
}
curOffset += curChunkSize;
}
return result;
}

View File

@ -25,6 +25,7 @@ typedef struct _memory_values_t {
typedef struct _memory_mapping_t {
uint32_t effective_start_address;
uint32_t effective_end_address;
const memory_values_t* physical_addresses;
} memory_mapping_t;
@ -35,7 +36,8 @@ typedef struct _memory_mapping_t {
#define MEMORY_START_BASE 0x80000000
#define MEMORY_LOADER_SPACE_SIZE 0x00800000 // At most: 8MB for the plugin loader.
#define MEMORY_PLUGIN_SPACE_SIZE 0x07800000 // At most: 120MB for plugins.
#define MEMORY_PLUGIN_SPACE_SIZE 0x04000000 // At most: 64MB for plugins.
#define MEMORY_VIDEO_SPACE_SIZE 0x03600000 // At most: 56MB for video.
#define MEMORY_PLUGIN_HEAP_SIZE 0x08000000 // At most: 128MB for plugins heap.
#define MEMORY_START_PLUGIN_LOADER MEMORY_START_BASE
@ -44,16 +46,53 @@ typedef struct _memory_mapping_t {
#define MEMORY_START_PLUGIN_SPACE MEMORY_START_PLUGIN_LOADER_END
#define MEMORY_START_PLUGIN_SPACE_END MEMORY_START_PLUGIN_SPACE + MEMORY_PLUGIN_SPACE_SIZE
#define MEMORY_START_PLUGIN_HEAP MEMORY_START_PLUGIN_SPACE_END
#define MEMORY_START_VIDEO_SPACE MEMORY_START_PLUGIN_SPACE_END
#define MEMORY_START_VIDEO_SPACE_END MEMORY_START_VIDEO_SPACE + MEMORY_VIDEO_SPACE_SIZE
#define MEMORY_START_PLUGIN_HEAP MEMORY_START_VIDEO_SPACE_END
#define MEMORY_START_PLUGIN_HEAP_END MEMORY_START_PLUGIN_HEAP + MEMORY_PLUGIN_HEAP_SIZE
const memory_values_t mem_vals_loader[] = {
{0x28000000 + 0x06620000 , 0x28000000 + 0x06E20000}, // 8MB 0x80000000 0x80800000 -> 0x2E700000 0x2EF00000
{0x28000000 + 0x06620000, 0x28000000 + 0x06E20000}, // 8MB 0x80000000 0x80800000 -> 0x2E700000 0x2EF00000
{0,0}
};
const memory_values_t mem_vals_plugins[] = {
{0x28000000 + 0x06E20000 , 0x28000000 + 0x07E20000}, // 16MB 0x80800000 0x81800000 -> 0x2EF00000 0x2FF00000
{0x28000000 + 0x06E20000, 0x28000000 + 0x07E20000}, // 16MB 0x80800000 0x81800000 -> 0x2EF00000 0x2FF00000
{0,0}
};
const memory_values_t mem_vals_video[] = {
// The GPU doesn't have access to the 0x28000000 - 0x32000000 area, so we need memory from somewhere else.
// From the SharedReadHeap of the loader.
//
// #define TinyHeap_Alloc ((int32_t (*)(void* heap, int32_t size, int32_t align,void ** outPtr))0x0101235C)
// #define TinyHeap_Free ((void (*)(void* heap, void * ptr))0x01012814)
// uint32_t SharedReadHeapTrackingAddr = 0xFA000000 + 0x18 + 0x830 // see https://github.com/decaf-emu/decaf-emu/blob/master/src/libdecaf/src/cafe/loader/cafe_loader_shared.cpp#L490
//
// Map the area of the heap to somewhere in the user space and test allocation with
// void * heap = (void*) SharedReadHeapTrackingAddr - [delta due mapping e.g (0xF8000000 + 0x80000000)];
// int size = 0x20000; // value have to be a multiple of 0x20000;
// while(true){
// void * outPtr = NULL;
// if(TinyHeap_Alloc(heap,size, 0x20000,&outPtr) == 0){ // value have to be a multiple of 0x20000;
// DEBUG_FUNCTION_LINE("Allocated %d kb on heap %08X (PA %08X)\n",size/1024,(uint32_t)outPtr, OSEffectiveToPhysical(outPtr));
// TinyHeap_Free(heap, outPtr);
// }else{
// DEBUG_FUNCTION_LINE("Failed %08X\n",(uint32_t)outPtr);
// break;
// }
// size += 0x20000; // value have to be a multiple of 0x20000;
// }
//
{0x1A020000, 0x1A020000 +0xE60000}, // size: 14720 kB
// The following chunk were empty while early tests and are maybe promising. However we can get 15mb from
// a loader heap. Which should be enough for now.
//{0x14000000 + 0x02E00000 , 0x14000000 +0x034E0000}, // size: 7040 kB
//{0x14000000 + 0x02820000 , 0x14000000 +0x02C20000}, // size: 4096 kB
//{0x14000000 + 0x05AE0000 , 0x14000000 +0x06000000}, // size: 5248 kB
//{0x14000000 + 0x08040000 , 0x14000000 +0x08400000}, // size: 3840 kB
//{0x18000000 , 0x18000000 +0x3000000}, // size: 3840 kB
{0,0}
};
@ -102,10 +141,11 @@ const memory_values_t mem_vals_heap[] = {
};
const memory_mapping_t mem_mapping[] = {
{MEMORY_START_PLUGIN_LOADER, mem_vals_loader},
{MEMORY_START_PLUGIN_SPACE, mem_vals_plugins},
{MEMORY_START_PLUGIN_HEAP, mem_vals_heap},
{0,NULL}
{MEMORY_START_VIDEO_SPACE, MEMORY_START_VIDEO_SPACE_END, mem_vals_video},
{MEMORY_START_PLUGIN_LOADER, MEMORY_START_PLUGIN_LOADER_END, mem_vals_loader},
{MEMORY_START_PLUGIN_SPACE, MEMORY_START_PLUGIN_SPACE_END, mem_vals_plugins},
{MEMORY_START_PLUGIN_HEAP, MEMORY_START_PLUGIN_HEAP_END, mem_vals_heap},
{0,0,NULL}
};
class MemoryMapping {
@ -127,8 +167,20 @@ public:
static uint32_t getHeapSize();
static uint32_t getVideoMemoryAddress();
static uint32_t getVideoMemorySize();
static uint32_t getAreaSizeFromPageTable(uint32_t start, uint32_t maxSize);
// Caution when using the result. A chunk of memory in effective address may be split up
// into several small chunks inside physical space.
static uint32_t PhysicalToEffective(uint32_t phyiscalAddress);
// Caution when using the result. A chunk of memory in effective address may be split up
// into several small chunks inside physical space.
static uint32_t EffectiveToPhysical(uint32_t effectiveAddress);
private:
static void memoryMappingForRegions(const memory_mapping_t * memory_mapping, sr_table_t SRTable, uint32_t * translation_table);

View File

@ -25,12 +25,10 @@ ConfigInformation::ConfigInformation(WUPSConfig * config, std::string persistPat
this->persistPath = persistPath;
this->persistFileName = persistFileName;
createConfigSettings();
loadValuesFromSD();
}
ConfigInformation::~ConfigInformation() {
if(configSettings != NULL) {
updateAndSaveSettings();
delete configSettings;
configSettings = NULL;
}
@ -89,12 +87,12 @@ bool ConfigInformation::loadValuesFromSD() {
return true;
}
void ConfigInformation::updateAndSaveSettings() {
void ConfigInformation::updateAndSaveSettings(bool forceAll) {
if(this->config == NULL || this->configSettings == NULL) {
return;
}
updateConfigSettings();
configSettings->Save();
configSettings->Save(forceAll);
}
bool ConfigInformation::updateConfigSettings() {
@ -106,7 +104,7 @@ bool ConfigInformation::updateConfigSettings() {
for (auto & curItem : curCat->getItems()) {
std::string configID = curItem->getConfigID();
std::string newValue = curItem->persistValue();
if(this->configSettings->setValueAsString(this->configSettings->getIdByName(configID), newValue)){
if(this->configSettings->setValueAsString(this->configSettings->getIdByName(configID), newValue)) {
// When the value has changed, call the callback.
DEBUG_FUNCTION_LINE("Called callback. Reason. Menu was closed and value has changed\n");
curItem->callCallback();

View File

@ -35,12 +35,13 @@ public:
/**
Deletes the given WUPSConfig
Calls updateAndSaveSettings
Deletes the created ConfigSettings
**/
~ConfigInformation();
void updateAndSaveSettings();
void updateAndSaveSettings(bool forceAll);
bool loadValuesFromSD();
WUPSConfig * getConfig() {
return config;
@ -48,7 +49,6 @@ public:
private:
bool createConfigSettings();
bool loadValuesFromSD();
bool updateConfigSettings();
WUPSConfig * config = NULL;

View File

@ -167,6 +167,18 @@ void ConfigUtils::configMenuOpenedCallback(wups_overlay_options_type_t screen, v
if(vpad_data.btns_d & VPAD_BUTTON_RIGHT) {
pressedButtons |= WUPS_CONFIG_BUTTON_RIGHT;
}
if(vpad_data.btns_d & VPAD_BUTTON_L) {
pressedButtons |= WUPS_CONFIG_BUTTON_L;
}
if(vpad_data.btns_d & VPAD_BUTTON_R) {
pressedButtons |= WUPS_CONFIG_BUTTON_R;
}
if(vpad_data.btns_d & VPAD_BUTTON_ZL) {
pressedButtons |= WUPS_CONFIG_BUTTON_ZL;
}
if(vpad_data.btns_d & VPAD_BUTTON_ZR) {
pressedButtons |= WUPS_CONFIG_BUTTON_ZR;
}
if(vpad_data.btns_r & VPAD_BUTTON_DOWN) {
newSelect++;
@ -217,9 +229,9 @@ void ConfigUtils::configMenuOpenedCallback(wups_overlay_options_type_t screen, v
if(!ignore && curSelect == inSelect) {
if(curSelect == 0) {
curScreenOffset = 0;
}else if(cur_visible_rows + curScreenOffset >= visible_rows_range) {
} else if(cur_visible_rows + curScreenOffset >= visible_rows_range) {
curScreenOffset -= (cur_visible_rows + curScreenOffset) - visible_rows_range;
}else if(cur_visible_rows + curScreenOffset < visible_rows_range/2 && cur_visible_rows >= visible_rows_range/2) {
} else if(cur_visible_rows + curScreenOffset < visible_rows_range/2 && cur_visible_rows >= visible_rows_range/2) {
curScreenOffset -= (cur_visible_rows + curScreenOffset) - visible_rows_range/2;
}
ignore = true;
@ -330,12 +342,35 @@ void ConfigUtils::deleteConfigInformation(std::vector<ConfigInformation *> confi
}
void ConfigUtils::loadConfigFromSD() {
deleteConfigInformation(getConfigInformation());
std::vector<ConfigInformation *> configInfos = getConfigInformation();
for (auto & curConfig : configInfos) {
curConfig->loadValuesFromSD();
}
deleteConfigInformation(configInfos);
}
void ConfigUtils::saveConfigToSD() {
std::vector<ConfigInformation *> configInfos = getConfigInformation();
for (auto & curConfig : configInfos) {
curConfig->updateAndSaveSettings(true);
}
deleteConfigInformation(configInfos);
}
void ConfigUtils::openConfigMenu() {
std::vector<ConfigInformation *> configInfos = getConfigInformation();
// We rely on the default values here.
//if(loadFromSD){
// for (auto & curConfig : configInfos) {
// configs.loadValuesFromSD();
// }
//}
std::vector<WUPSConfig *> configs;
for (auto & curConfig : configInfos) {
@ -352,5 +387,9 @@ void ConfigUtils::openConfigMenu() {
DCFlushRange(curConfig, sizeof(WUPSConfig));
}
for (auto & curConfig : configInfos) {
curConfig->updateAndSaveSettings(false);
}
deleteConfigInformation(configInfos);
}

View File

@ -26,15 +26,21 @@ class ConfigUtils {
public:
/**
Loads the configuration files of all loaded plugins from the SDCard
and triggers the "loadValue" if they differ the default value.
and triggers the "callback" if they differ the default/current value.
**/
static void loadConfigFromSD();
/**
Get the current values from all plugins via the WUPS_GET_CONFIG() hook and
save them to the SD Card.
**/
static void saveConfigToSD();
/**
Opens the configuration menu where plugins can be configured.
Plugins need to implement the WUPS_GET_CONFIG() hook to show up in the menu.
The menu will be rendered on the TV and DRC screen, with optimization for the DRC.
If the menu is low, the menu may be only rendered to the DRC.
If the memory is low, the menu may be only rendered to the DRC.
**/
static void openConfigMenu();

View File

@ -4,11 +4,11 @@
#include <utils/logger.h>
#include "libntfs.h"
#include <iosuhax.h>
#include <ntfs.h>
//#include <ntfs.h>
#include "common/retain_vars.h"
int32_t mountAllNTFS() {
int32_t i;
/*int32_t i;
// Mount all NTFS volumes on all inserted block devices
ntfs_mount_count = ntfsMountAll((ntfs_md **) &ntfs_mounts, NTFS_DEFAULT | NTFS_RECOVER);
if (ntfs_mount_count == -1) {
@ -22,11 +22,12 @@ int32_t mountAllNTFS() {
for (i = 0; i < ntfs_mount_count; i++) {
DEBUG_FUNCTION_LINE("%i - %s:/ (%s)\n", i + 1, ((ntfs_md *)ntfs_mounts)[i].name, ntfsGetVolumeName(((ntfs_md *)ntfs_mounts)[i].name));
}
return ntfs_mount_count;
return ntfs_mount_count;*/
return 0;
}
int32_t unmountAllNTFS(void) {
if (ntfs_mounts) {
/*if (ntfs_mounts) {
int32_t i = 0;
for (i = 0; i < ntfs_mount_count; i++) {
ntfsUnmount(((ntfs_md *)ntfs_mounts)[i].name, true);
@ -34,6 +35,6 @@ int32_t unmountAllNTFS(void) {
free(ntfs_mounts);
ntfs_mounts = NULL;
ntfs_mount_count = 0;
}
}*/
return 0;
}

37
src/myutils/mem_utils.cpp Normal file
View File

@ -0,0 +1,37 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <utils/logger.h>
#include <wups.h>
#include <stdarg.h>
#include "dynamic_libs/os_functions.h"
#include "mem_utils.h"
#include "mymemory/memory_mapping.h"
int32_t memHandle __attribute__((section(".data"))) = -1;
void MemoryUtils::init() {
memHandle = MEMCreateExpHeapEx((void*)MemoryMapping::getVideoMemoryAddress(), MemoryMapping::getVideoMemorySize(), 0);
}
void* MemoryUtils::alloc(uint32_t size, int32_t align) {
return MEMAllocFromExpHeapEx(memHandle,size, align);
}
void MemoryUtils::free(void * ptr) {
MEMFreeToExpHeap(memHandle,ptr);
}

32
src/myutils/mem_utils.h Normal file
View File

@ -0,0 +1,32 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef __MEMORY_UTILS_UTILS_H_
#define __MEMORY_UTILS_UTILS_H_
class MemoryUtils {
public:
static void init();
static void* alloc(uint32_t size, int32_t align);
static void free(void * ptr);
private:
MemoryUtils() {}
~MemoryUtils() {}
};
#endif

View File

@ -18,8 +18,12 @@ uint32_t * getFromGX2Buffer(struct buffer_store store, uint32_t size) {
}
void overlay_helper(wups_overlay_options_type_t screen, overlay_callback callback, void * args) {
if(callback == NULL) return;
if(!OSIsHomeButtonMenuEnabled()) return; // This pauses the game. Make sure to only do it when the home button is allowed.
if(callback == NULL) {
return;
}
if(!OSIsHomeButtonMenuEnabled()) {
return; // This pauses the game. Make sure to only do it when the home button is allowed.
}
//TODO: Make sure this actually pauses the game (Hook on GX2VSync?) . Currently only tested from VPADRead which also pauses the game.

View File

@ -0,0 +1,174 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <utils/logger.h>
#include "texture_utils.h"
#include <wups.h>
#include <gd.h>
#include <dynamic_libs/gx2_functions.h>
#include <dynamic_libs/gx2_types.h>
#include "mem_utils.h"
void gdImageToUnormR8G8B8A8(gdImagePtr gdImg, u32 *imgBuffer, u32 width, u32 height, u32 pitch) {
for(u32 y = 0; y < height; ++y) {
for(u32 x = 0; x < width; ++x) {
u32 pixel = gdImageGetPixel(gdImg, x, y);
u8 a = 254 - 2*((u8)gdImageAlpha(gdImg, pixel));
if(a == 254)
a++;
u8 r = gdImageRed(gdImg, pixel);
u8 g = gdImageGreen(gdImg, pixel);
u8 b = gdImageBlue(gdImg, pixel);
imgBuffer[y * pitch + x] = (r << 24) | (g << 16) | (b << 8) | (a);
}
}
}
void TextureUtils::drawTexture(GX2Texture * texture, GX2Sampler* sampler, float x, float y, int32_t width, int32_t height, float alpha = 1.0f) {
float widthScaleFactor = 1.0f / (float)1280;
float heightScaleFactor = 1.0f / (float)720;
glm::vec3 positionOffsets = glm::vec3(0.0f);
positionOffsets[0] = (x-((1280)/2)+(width/2)) * widthScaleFactor * 2.0f;
positionOffsets[1] = -(y-((720)/2)+(height/2)) * heightScaleFactor * 2.0f;
glm::vec3 scale(width*widthScaleFactor,height*heightScaleFactor,1.0f);
Texture2DShader::instance()->setShaders();
Texture2DShader::instance()->setAttributeBuffer();
Texture2DShader::instance()->setAngle(0.0f);
Texture2DShader::instance()->setOffset(positionOffsets);
Texture2DShader::instance()->setScale(scale);
Texture2DShader::instance()->setColorIntensity(glm::vec4(alpha));
Texture2DShader::instance()->setBlurring(glm::vec3(0.0f));
Texture2DShader::instance()->setTextureAndSampler(texture, sampler);
Texture2DShader::instance()->draw();
}
void TextureUtils::copyToTexture(GX2ColorBuffer* sourceBuffer, GX2Texture * target) {
if(sourceBuffer == NULL || target == NULL) {
return;
}
if (sourceBuffer->surface.aa == GX2_AA_MODE_1X) {
// If AA is disabled, we can simply use GX2CopySurface.
GX2CopySurface(&sourceBuffer->surface,
sourceBuffer->view_mip,
sourceBuffer->view_first_slice,
&target->surface, 0, 0);
GX2DrawDone();
} else {
// If AA is enabled, we need to resolve the AA buffer.
// Allocate surface to resolve buffer onto
GX2Surface tempSurface;
tempSurface = sourceBuffer->surface;
tempSurface.aa = GX2_AA_MODE_1X;
GX2CalcSurfaceSizeAndAlignment(&tempSurface);
tempSurface.image_data = MemoryUtils::alloc(
tempSurface.image_size,
tempSurface.align
);
if(tempSurface.image_data == NULL) {
DEBUG_FUNCTION_LINE("VideoSquoosher: failed to allocate AA surface\n");
if(target->surface.image_data != NULL) {
MemoryUtils::free(target->surface.image_data);
target->surface.image_data = NULL;
}
return;
}
// Resolve, then copy result to target
GX2ResolveAAColorBuffer(sourceBuffer,&tempSurface, 0, 0);
GX2CopySurface(&tempSurface, 0, 0,&target->surface, 0, 0);
if(tempSurface.image_data != NULL) {
MemoryUtils::free(tempSurface.image_data);
tempSurface.image_data = NULL;
}
GX2DrawDone();
GX2Invalidate(GX2_INVALIDATE_CPU, target->surface.image_data, target->surface.image_size);
}
}
bool TextureUtils::convertImageToTexture(const uint8_t *img, int32_t imgSize, void * _texture) {
if(!img || (imgSize < 8) || _texture == NULL) {
return false;
}
GX2Texture * texture = (GX2Texture *) _texture;
gdImagePtr gdImg = 0;
if (img[0] == 0xFF && img[1] == 0xD8) {
//! not needed for now therefore comment out to safe ELF size
//! if needed uncomment, adds 200 kb to the ELF size
// IMAGE_JPEG
gdImg = gdImageCreateFromJpegPtr(imgSize, (uint8_t*) img);
} else if (img[0] == 'B' && img[1] == 'M') {
// IMAGE_BMP
//gdImg = gdImageCreateFromBmpPtr(imgSize, (uint8_t*) img);
} else if (img[0] == 0x89 && img[1] == 'P' && img[2] == 'N' && img[3] == 'G') {
// IMAGE_PNG
gdImg = gdImageCreateFromPngPtr(imgSize, (uint8_t*) img);
}
//!This must be last since it can also intefere with outher formats
else if(img[0] == 0x00) {
// Try loading TGA image
//gdImg = gdImageCreateFromTgaPtr(imgSize, (uint8_t*) img);
}
if(gdImg == 0) {
return false;
}
uint32_t width = (gdImageSX(gdImg));
uint32_t height = (gdImageSY(gdImg));
//! Initialize texture
GX2InitTexture(texture, width, height, 1, 0, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GX2_SURFACE_DIM_2D, GX2_TILE_MODE_LINEAR_ALIGNED);
//! if this fails something went horribly wrong
if(texture->surface.image_size == 0) {
gdImageDestroy(gdImg);
return false;
}
texture->surface.image_data = MemoryUtils::alloc(texture->surface.image_size, texture->surface.align);
//! check if memory is available for image
if(!texture->surface.image_data) {
gdImageDestroy(gdImg);
return false;
}
//! set mip map data pointer
texture->surface.mip_data = NULL;
gdImageToUnormR8G8B8A8(gdImg, (uint32_t*)texture->surface.image_data, texture->surface.width, texture->surface.height, texture->surface.pitch);
//! free memory of image as its not needed anymore
gdImageDestroy(gdImg);
//! invalidate the memory
GX2Invalidate(GX2_INVALIDATE_CPU_TEXTURE, texture->surface.image_data, texture->surface.image_size);
return true;
}

View File

@ -0,0 +1,33 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef __TEXTURE_UTILS_UTILS_H_
#define __TEXTURE_UTILS_UTILS_H_
#include <stdint.h>
#include <dynamic_libs/gx2_functions.h>
#include <video/shaders/Texture2DShader.h>
class TextureUtils {
public:
static bool convertImageToTexture(const uint8_t *img, int32_t imgSize, void * texture);
static void drawTexture(GX2Texture * texture, GX2Sampler* sampler, float x, float y, int32_t width, int32_t height, float alpha);
static void copyToTexture(GX2ColorBuffer* sourceBuffer, GX2Texture * target);
private:
TextureUtils() {}
~TextureUtils() {}
};
#endif

View File

@ -8,17 +8,7 @@
#include "main.h"
#include "utils.h"
#include "mymemory/memory_mapping.h"
DECL(void, __PPCExit, void) {
// Only continue if we are in the "right" application.
//if(OSGetTitleID() == gGameTitleID) {
//DEBUG_FUNCTION_LINE("__PPCExit\n");
//CallHook(WUPS_LOADER_HOOK_ENDING_APPLICATION);
//DeInit();
//}
real___PPCExit();
}
#include <video/shaders/Texture2DShader.h>
DECL(uint32_t, ProcUIProcessMessages, uint32_t u) {
uint32_t res = real_ProcUIProcessMessages(u);
@ -29,114 +19,17 @@ DECL(uint32_t, ProcUIProcessMessages, uint32_t u) {
CallHook(WUPS_LOADER_HOOK_APP_STATUS_CHANGED);
if(gAppStatus == WUPS_APP_STATUS_CLOSED) {
CallHook(WUPS_LOADER_HOOK_ENDING_APPLICATION);
ConfigUtils::saveConfigToSD();
DeInit();
Texture2DShader::destroyInstance();
}
}
return res;
}
DECL(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, int32_t format, int32_t buffering_mode) {
tv_store.buffer = buffer;
tv_store.buffer_size = buffer_size;
tv_store.mode = tv_render_mode;
tv_store.surface_format = format;
tv_store.buffering_mode = buffering_mode;
return real_GX2SetTVBuffer(buffer,buffer_size,tv_render_mode,format,buffering_mode);
}
DECL(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, int32_t drc_mode, int32_t surface_format, int32_t buffering_mode) {
drc_store.buffer = buffer;
drc_store.buffer_size = buffer_size;
drc_store.mode = drc_mode;
drc_store.surface_format = surface_format;
drc_store.buffering_mode = buffering_mode;
return real_GX2SetDRCBuffer(buffer,buffer_size,drc_mode,surface_format,buffering_mode);
}
DECL(void, GX2WaitForVsync, void) {
CallHook(WUPS_LOADER_HOOK_VSYNC);
real_GX2WaitForVsync();
}
uint8_t vpadPressCooldown = 0xFF;
uint8_t angleX_counter = 0;
float angleX_delta = 0.0f;
float angleX_last = 0.0f;
uint8_t angleX_frameCounter = 0;
bool checkMagic(VPADData *buffer) {
// buffer->angle stores the rotations per axis since the app started.
// Each full rotation add/subtracts 1.0f (depending on the direction).
// Check for rotation every only 5 frames.
angleX_frameCounter++;
if(angleX_frameCounter >= 5) {
// Get how much the gamepad rotated within the last 5 frames.
float diff_angle = -(buffer->angle.x - angleX_last);
// We want the gamepad to make (on average) at least 0.16% (1/6) of a full rotation per 5 frames (for 6 times in a row).
float target_diff = (0.16f);
// Calculate if rotated enough in this step (including the delta from the last step).
float total_diff = (diff_angle + angleX_delta) - target_diff;
if(total_diff > 0.0f) {
// The rotation in this step was enough.
angleX_counter++;
// When the gamepad rotated ~0.16% for 6 times in a row we made a full rotation!
if(angleX_counter > 5) {
ConfigUtils::openConfigMenu();
// reset stuff.
angleX_counter = 0;
angleX_delta = 0.0f;
} else {
// Save difference as it will be added on the next check.
angleX_delta = total_diff;
}
} else {
// reset counter if it stopped rotating.
angleX_counter = 0;
}
angleX_frameCounter = 0;
angleX_last = buffer->angle.x;
}
}
DECL(int32_t, VPADRead, int32_t chan, VPADData *buffer, uint32_t buffer_size, int32_t *error) {
int32_t result = real_VPADRead(chan, buffer, buffer_size, error);
if(result > 0 && (buffer[0].btns_h == (VPAD_BUTTON_PLUS | VPAD_BUTTON_R | VPAD_BUTTON_L)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
if(MemoryMapping::isMemoryMapped()) {
MemoryMapping::readTestValuesFromMemory();
} else {
DEBUG_FUNCTION_LINE("Memory was not mapped. To test the memory please exit the plugin loader by pressing MINUS\n");
}
vpadPressCooldown = 0x3C;
}
if(result > 0 && (buffer[0].btns_h == (VPAD_BUTTON_L | VPAD_BUTTON_DOWN | VPAD_BUTTON_MINUS)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
ConfigUtils::openConfigMenu();
vpadPressCooldown = 0x3C;
} else if(result > 0 && OSIsHomeButtonMenuEnabled()) {
checkMagic(buffer);
}
if(vpadPressCooldown > 0) {
vpadPressCooldown--;
}
return result;
}
hooks_magic_t method_hooks_hooks[] __attribute__((section(".data"))) = {
MAKE_MAGIC(__PPCExit, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(ProcUIProcessMessages, LIB_PROC_UI, DYNAMIC_FUNCTION),
MAKE_MAGIC(GX2SetTVBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetDRCBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2WaitForVsync, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION),
MAKE_MAGIC(ProcUIProcessMessages, LIB_PROC_UI, DYNAMIC_FUNCTION),
};

View File

@ -0,0 +1,340 @@
#include <utils/logger.h>
#include <utils/function_patcher.h>
#include <dynamic_libs/vpad_functions.h>
#include "common/retain_vars.h"
#include "hooks_patcher.h"
#include "myutils/overlay_helper.h"
#include "myutils/ConfigUtils.h"
#include <malloc.h>
#include "main.h"
#include "utils.h"
#include "mymemory/memory_mapping.h"
#include "myutils/mem_utils.h"
#include "myutils/texture_utils.h"
DECL(void, __PPCExit, void) {
// Only continue if we are in the "right" application.
//if(OSGetTitleID() == gGameTitleID) {
//DEBUG_FUNCTION_LINE("__PPCExit\n");
//CallHook(WUPS_LOADER_HOOK_ENDING_APPLICATION);
//DeInit();
//}
real___PPCExit();
}
DECL_FUNCTION(uint32_t, __OSPhysicalToEffectiveCached, uint32_t phyiscalAddress) {
uint32_t result = real___OSPhysicalToEffectiveCached(phyiscalAddress);
if(result == 0) {
result = MemoryMapping::PhysicalToEffective(phyiscalAddress);
//DEBUG_FUNCTION_LINE("__OSPhysicalToEffectiveCached in %08X out %08X\n",phyiscalAddress,result);
}
return result;
}
DECL_FUNCTION(uint32_t, __OSPhysicalToEffectiveUncached, uint32_t phyiscalAddress) {
uint32_t result = real___OSPhysicalToEffectiveUncached(phyiscalAddress);
if(result == 0) {
result = MemoryMapping::PhysicalToEffective(phyiscalAddress);
//DEBUG_FUNCTION_LINE("__OSPhysicalToEffectiveUncached in %08X out %08X\n",phyiscalAddress,result);
return result;
}
return result;
}
DECL_FUNCTION(uint32_t, OSEffectiveToPhysical, uint32_t virtualAddress) {
uint32_t result = real_OSEffectiveToPhysical(virtualAddress);
if(result == 0) {
result = MemoryMapping::EffectiveToPhysical(virtualAddress);
//DEBUG_FUNCTION_LINE("OSEffectiveToPhysical in %08X out %08X\n",virtualAddress,result);
return result;
}
return result;
}
DECL_FUNCTION(int32_t, OSIsAddressValid, uint32_t virtualAddress) {
int32_t result = real_OSIsAddressValid(virtualAddress);
if(result == 0) {
result = (MemoryMapping::EffectiveToPhysical(virtualAddress) > 0);
//DEBUG_FUNCTION_LINE("OSIsAddressValid in %08X out %d\n",virtualAddress,result);
return result;
}
return result;
}
DECL(void, GX2SetTVBuffer, void *buffer, uint32_t buffer_size, int32_t tv_render_mode, int32_t format, int32_t buffering_mode) {
tv_store.buffer = buffer;
tv_store.buffer_size = buffer_size;
tv_store.mode = tv_render_mode;
tv_store.surface_format = format;
tv_store.buffering_mode = buffering_mode;
return real_GX2SetTVBuffer(buffer,buffer_size,tv_render_mode,format,buffering_mode);
}
DECL(void, GX2SetDRCBuffer, void *buffer, uint32_t buffer_size, int32_t drc_mode, int32_t surface_format, int32_t buffering_mode) {
drc_store.buffer = buffer;
drc_store.buffer_size = buffer_size;
drc_store.mode = drc_mode;
drc_store.surface_format = surface_format;
drc_store.buffering_mode = buffering_mode;
return real_GX2SetDRCBuffer(buffer,buffer_size,drc_mode,surface_format,buffering_mode);
}
DECL(void, GX2WaitForVsync, void) {
CallHook(WUPS_LOADER_HOOK_VSYNC);
real_GX2WaitForVsync();
}
uint8_t vpadPressCooldown = 0xFF;
uint8_t angleX_counter = 0;
float angleX_delta = 0.0f;
float angleX_last = 0.0f;
uint8_t angleX_frameCounter = 0;
void checkMagic(VPADData *buffer) {
// buffer->angle stores the rotations per axis since the app started.
// Each full rotation add/subtracts 1.0f (depending on the direction).
// Check for rotation every only 5 frames.
angleX_frameCounter++;
if(angleX_frameCounter >= 5) {
// Get how much the gamepad rotated within the last 5 frames.
float diff_angle = -(buffer->angle.x - angleX_last);
// We want the gamepad to make (on average) at least 0.16% (1/6) of a full rotation per 5 frames (for 6 times in a row).
float target_diff = (0.16f);
// Calculate if rotated enough in this step (including the delta from the last step).
float total_diff = (diff_angle + angleX_delta) - target_diff;
if(total_diff > 0.0f) {
// The rotation in this step was enough.
angleX_counter++;
// When the gamepad rotated ~0.16% for 6 times in a row we made a full rotation!
if(angleX_counter > 5) {
ConfigUtils::openConfigMenu();
// reset stuff.
angleX_counter = 0;
angleX_delta = 0.0f;
} else {
// Save difference as it will be added on the next check.
angleX_delta = total_diff;
}
} else {
// reset counter if it stopped rotating.
angleX_counter = 0;
}
angleX_frameCounter = 0;
angleX_last = buffer->angle.x;
}
}
DECL(int32_t, VPADRead, int32_t chan, VPADData *buffer, uint32_t buffer_size, int32_t *error) {
int32_t result = real_VPADRead(chan, buffer, buffer_size, error);
if(result > 0 && (buffer[0].btns_h == (VPAD_BUTTON_PLUS | VPAD_BUTTON_R | VPAD_BUTTON_L)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
if(MemoryMapping::isMemoryMapped()) {
MemoryMapping::readTestValuesFromMemory();
} else {
DEBUG_FUNCTION_LINE("Memory was not mapped. To test the memory please exit the plugin loader by pressing MINUS\n");
}
vpadPressCooldown = 0x3C;
}
if(result > 0 && (buffer[0].btns_h == (VPAD_BUTTON_L | VPAD_BUTTON_DOWN | VPAD_BUTTON_MINUS)) && vpadPressCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
ConfigUtils::openConfigMenu();
vpadPressCooldown = 0x3C;
} else if(result > 0 && OSIsHomeButtonMenuEnabled()) {
checkMagic(buffer);
}
if(vpadPressCooldown > 0) {
vpadPressCooldown--;
}
return result;
}
void setupContextState() {
g_vid_ownContextState = (GX2ContextState*)memalign(
GX2_CONTEXT_STATE_ALIGNMENT,
sizeof(GX2ContextState)
);
if(g_vid_ownContextState == NULL) {
OSFatal("VideoSquoosher: Failed to alloc g_vid_ownContextState\n");
}
GX2SetupContextStateEx(g_vid_ownContextState, 1);
GX2SetContextState(g_vid_ownContextState);
GX2SetColorBuffer(&g_vid_main_cbuf, GX2_RENDER_TARGET_0);
//GX2SetDepthBuffer(&tvDepthBuffer);
GX2SetContextState(g_vid_originalContextSave);
DEBUG_FUNCTION_LINE("Setup contest state done\n");
}
void initTextures() {
GX2InitColorBuffer(&g_vid_main_cbuf,
GX2_SURFACE_DIM_2D,
1280, 720, 1,
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM,
GX2_AA_MODE_1X
);
if (g_vid_main_cbuf.surface.image_size) {
g_vid_main_cbuf.surface.image_data = MemoryUtils::alloc(
g_vid_main_cbuf.surface.image_size,
g_vid_main_cbuf.surface.align
);
if(g_vid_main_cbuf.surface.image_data == NULL) {
OSFatal("Failed to alloc g_vid_main_cbuf\n");
}
DEBUG_FUNCTION_LINE("Allocated %dx%d g_vid_main_cbuf %08X\n",
g_vid_main_cbuf.surface.width,
g_vid_main_cbuf.surface.height,
g_vid_main_cbuf.surface.image_data);
} else {
DEBUG_FUNCTION_LINE("GX2InitTexture failed for g_vid_main_cbuf!\n");
}
GX2InitTexture(&g_vid_drcTex,
854, 480, 1, 0,
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM,
GX2_SURFACE_DIM_2D,
GX2_TILE_MODE_LINEAR_ALIGNED
);
g_vid_drcTex.surface.use = (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE);
if (g_vid_drcTex.surface.image_size) {
g_vid_drcTex.surface.image_data = MemoryUtils::alloc(
g_vid_drcTex.surface.image_size,
g_vid_drcTex.surface.align);
if(g_vid_drcTex.surface.image_data == NULL) {
OSFatal("VideoSquoosher: Failed to alloc g_vid_drcTex\n");
}
GX2Invalidate(GX2_INVALIDATE_CPU, g_vid_drcTex.surface.image_data, g_vid_drcTex.surface.image_size);
DEBUG_FUNCTION_LINE("VideoSquoosher: allocated %dx%d g_vid_drcTex %08X\n",
g_vid_drcTex.surface.width,
g_vid_drcTex.surface.height,
g_vid_drcTex.surface.image_data);
} else {
DEBUG_FUNCTION_LINE("VideoSquoosher: GX2InitTexture failed for g_vid_drcTex!\n");
}
GX2InitTexture(&g_vid_tvTex,
1280, 720, 1, 0,
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM,
GX2_SURFACE_DIM_2D,
GX2_TILE_MODE_LINEAR_ALIGNED
);
g_vid_tvTex.surface.use =
(GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE);
DCFlushRange(&g_vid_tvTex, sizeof(GX2Texture));
if (g_vid_tvTex.surface.image_size) {
g_vid_tvTex.surface.image_data = MemoryUtils::alloc(
g_vid_tvTex.surface.image_size,
g_vid_tvTex.surface.align
);
if(g_vid_tvTex.surface.image_data == NULL) {
OSFatal("VideoSquoosher: Failed to alloc g_vid_tvTex\n");
}
GX2Invalidate(GX2_INVALIDATE_CPU, g_vid_tvTex.surface.image_data, g_vid_tvTex.surface.image_size);
DEBUG_FUNCTION_LINE("VideoSquoosher: allocated %dx%d g_vid_tvTex %08X\n",
g_vid_tvTex.surface.width,
g_vid_tvTex.surface.height,
g_vid_tvTex.surface.image_data);
} else {
DEBUG_FUNCTION_LINE("VideoSquoosher: GX2InitTexture failed for g_vid_tvTex!\n");
}
GX2InitSampler(&g_vid_sampler,
GX2_TEX_CLAMP_CLAMP,
GX2_TEX_XY_FILTER_BILINEAR
);
}
DECL_FUNCTION(void, GX2SetContextState, GX2ContextState * curContext) {
if(gAppStatus == WUPS_APP_STATUS_FOREGROUND) {
g_vid_originalContextSave = curContext;
}
real_GX2SetContextState(curContext);
}
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer* cbuf, int32_t target) {
bool hasDRCHook = HasHookCallHook(WUPS_LOADER_HOOK_VID_DRC_DRAW);
bool hasTVHook = HasHookCallHook(WUPS_LOADER_HOOK_VID_TV_DRAW);
if(gAppStatus != WUPS_APP_STATUS_FOREGROUND || !g_NotInLoader || (!hasDRCHook && !hasTVHook)) {
return real_GX2CopyColorBufferToScanBuffer(cbuf,target);
}
if (!g_vid_drcTex.surface.image_data) {
initTextures();
}
if(g_vid_ownContextState == NULL) {
setupContextState();
}
if(target == 1) {
TextureUtils::copyToTexture(cbuf,&g_vid_tvTex);
if(!hasTVHook) {
return real_GX2CopyColorBufferToScanBuffer(cbuf,target);
}
} else if(target == 4) {
TextureUtils::copyToTexture(cbuf,&g_vid_drcTex);
if(!hasDRCHook) {
return real_GX2CopyColorBufferToScanBuffer(cbuf,target);
}
}
GX2SetContextState(g_vid_ownContextState);
GX2ClearColor(&g_vid_main_cbuf, 1.0f, 1.0f, 1.0f, 1.0f);
GX2SetContextState(g_vid_ownContextState);
GX2SetViewport(
0.0f, 0.0f,
g_vid_main_cbuf.surface.width, g_vid_main_cbuf.surface.height,
0.0f, 1.0f
);
GX2SetScissor(
0, 0,
g_vid_main_cbuf.surface.width, g_vid_main_cbuf.surface.height
);
if(target == 1) {
//drawTexture(&g_vid_tvTex, &g_vid_sampler, 0, 0, 1280, 720, 1.0f);
CallHook(WUPS_LOADER_HOOK_VID_TV_DRAW);
} else if(target == 4) {
//drawTexture(&g_vid_drcTex, &g_vid_sampler, 0, 0, 1280, 720, 1.0f);
CallHook(WUPS_LOADER_HOOK_VID_DRC_DRAW);
}
GX2SetContextState(g_vid_originalContextSave);
return real_GX2CopyColorBufferToScanBuffer(&g_vid_main_cbuf,target);
}
hooks_magic_t method_hooks_hooks_static[] __attribute__((section(".data"))) = {
MAKE_MAGIC(__PPCExit, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetTVBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetDRCBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2WaitForVsync, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2CopyColorBufferToScanBuffer, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(GX2SetContextState, LIB_GX2, STATIC_FUNCTION),
MAKE_MAGIC(VPADRead, LIB_VPAD, STATIC_FUNCTION),
MAKE_MAGIC(OSIsAddressValid, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(__OSPhysicalToEffectiveUncached, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(__OSPhysicalToEffectiveCached, LIB_CORE_INIT, STATIC_FUNCTION),
MAKE_MAGIC(OSEffectiveToPhysical, LIB_CORE_INIT, STATIC_FUNCTION),
};
uint32_t method_hooks_size_hooks_static __attribute__((section(".data"))) = sizeof(method_hooks_hooks_static) / sizeof(hooks_magic_t);
//! buffer to store our instructions needed for our replacements
volatile uint32_t method_calls_hooks_static[sizeof(method_hooks_hooks_static) / sizeof(hooks_magic_t) * FUNCTION_PATCHER_METHOD_STORE_SIZE] __attribute__((section(".data")));

View File

@ -0,0 +1,18 @@
#ifndef _HOOKS_STATIC_FUNCTION_PATCHER_H
#define _HOOKS_STATIC_FUNCTION_PATCHER_H
#include <utils/function_patcher.h>
#ifdef __cplusplus
extern "C" {
#endif
extern hooks_magic_t method_hooks_hooks_static[];
extern uint32_t method_hooks_size_hooks_static;
extern volatile uint32_t method_calls_hooks_static[];
#ifdef __cplusplus
}
#endif
#endif /* _HOOKS_STATIC_FUNCTION_PATCHER_H */

View File

@ -81,14 +81,14 @@ public:
protected:
private:
DynamicLinkingHelper() {
}
DynamicLinkingHelper() {
}
~DynamicLinkingHelper() {
~DynamicLinkingHelper() {
}
}
static DynamicLinkingHelper *instance;
};
static DynamicLinkingHelper *instance;
};
#endif // DYNAMICLINKINGHELPER_H

View File

@ -272,7 +272,7 @@ bool ElfTools::elfLink(Elf *elf, size_t shndx, void *destination, Elf32_Sym *sym
uint32_t size = symtab[symbol].st_size;
uint32_t address = pluginData->getMemoryForCommonBySymbol(symbol, align, size);
if(address == 0){
if(address == 0) {
DEBUG_FUNCTION_LINE("Failed to get memory for common relocation\n");
return false;
}
@ -494,7 +494,8 @@ bool ElfTools::elfLinkOne(char type, size_t offset, int32_t addend, void *destin
result = true;
exit_error:
if (!result) DEBUG_FUNCTION_LINE("Plugin_ElfLinkOne: exit_error\n");
if (!result)
DEBUG_FUNCTION_LINE("Plugin_ElfLinkOne: exit_error\n");
return result;
}

View File

@ -75,7 +75,7 @@ std::vector<PluginInformation *> PluginLoader::getPluginInformation(const char *
}
}
}
if(dfd != NULL){
if(dfd != NULL) {
closedir(dfd);
}
@ -467,7 +467,7 @@ void PluginLoader::copyPluginDataIntoGlobalStruct(std::vector<PluginData *> plug
replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index];
#warning TODO: add GUI option to let the user choose
#warning TODO: add GUI option to let the user choose
plugin_data->kernel_allowed = true;
plugin_data->kernel_init_done = false;

View File

@ -54,25 +54,26 @@ extern const uint32_t switchIconOn_png_size;
extern const uint8_t TwitterIcon_png[];
extern const uint32_t TwitterIcon_png_size;
static ResourceFile ResourceList[] =
{
{"font.ttf", font_ttf, font_ttf_size, NULL, 0},
{"gameSettingsButton.png", gameSettingsButton_png, gameSettingsButton_png_size, NULL, 0},
{"gameSettingsButtonEx.png", gameSettingsButtonEx_png, gameSettingsButtonEx_png_size, NULL, 0},
{"gameSettingsButtonExHighlighted.png", gameSettingsButtonExHighlighted_png, gameSettingsButtonExHighlighted_png_size, NULL, 0},
{"gameSettingsButtonExSelected.png", gameSettingsButtonExSelected_png, gameSettingsButtonExSelected_png_size, NULL, 0},
{"gameSettingsButtonSelected.png", gameSettingsButtonSelected_png, gameSettingsButtonSelected_png_size, NULL, 0},
{"GithubIcon.png", GithubIcon_png, GithubIcon_png_size, NULL, 0},
{"HomeButtonIcon.png", HomeButtonIcon_png, HomeButtonIcon_png_size, NULL, 0},
{"PlusButtonIcon.png", PlusButtonIcon_png, PlusButtonIcon_png_size, NULL, 0},
{"settings_click_2.mp3", settings_click_2_mp3, settings_click_2_mp3_size, NULL, 0},
{"switchIconBase.png", switchIconBase_png, switchIconBase_png_size, NULL, 0},
{"switchIconBaseHighlighted.png", switchIconBaseHighlighted_png, switchIconBaseHighlighted_png_size, NULL, 0},
{"switchIconOff.png", switchIconOff_png, switchIconOff_png_size, NULL, 0},
{"switchIconOn.png", switchIconOn_png, switchIconOn_png_size, NULL, 0},
{"TwitterIcon.png", TwitterIcon_png, TwitterIcon_png_size, NULL, 0},
{NULL, NULL, 0, NULL, 0}
static ResourceFile ResourceList[] = {
{"font.ttf", font_ttf, font_ttf_size, NULL, 0},
{"gameSettingsButton.png", gameSettingsButton_png, gameSettingsButton_png_size, NULL, 0},
{"gameSettingsButtonEx.png", gameSettingsButtonEx_png, gameSettingsButtonEx_png_size, NULL, 0},
{"gameSettingsButtonExHighlighted.png", gameSettingsButtonExHighlighted_png, gameSettingsButtonExHighlighted_png_size, NULL, 0},
{"gameSettingsButtonExSelected.png", gameSettingsButtonExSelected_png, gameSettingsButtonExSelected_png_size, NULL, 0},
{"gameSettingsButtonSelected.png", gameSettingsButtonSelected_png, gameSettingsButtonSelected_png_size, NULL, 0},
{"GithubIcon.png", GithubIcon_png, GithubIcon_png_size, NULL, 0},
{"HomeButtonIcon.png", HomeButtonIcon_png, HomeButtonIcon_png_size, NULL, 0},
{"PlusButtonIcon.png", PlusButtonIcon_png, PlusButtonIcon_png_size, NULL, 0},
{"settings_click_2.mp3", settings_click_2_mp3, settings_click_2_mp3_size, NULL, 0},
{"switchIconBase.png", switchIconBase_png, switchIconBase_png_size, NULL, 0},
{"switchIconBaseHighlighted.png", switchIconBaseHighlighted_png, switchIconBaseHighlighted_png_size, NULL, 0},
{"switchIconOff.png", switchIconOff_png, switchIconOff_png_size, NULL, 0},
{"switchIconOn.png", switchIconOn_png, switchIconOn_png_size, NULL, 0},
{"TwitterIcon.png", TwitterIcon_png, TwitterIcon_png_size, NULL, 0},
{NULL, NULL, 0, NULL, 0}
};
ResourceFile * getResourceList(){ return ResourceList; }
ResourceFile * getResourceList() {
return ResourceList;
}

View File

@ -181,7 +181,7 @@ bool ConfigSettings::Reset() {
this->SetDefault();
bChanged = true;
if (this->Save()) {
if (this->Save(true)) {
return true;
}
@ -197,8 +197,8 @@ int32_t ConfigSettings::getIdByName(std::string configID) {
return -1;
}
bool ConfigSettings::Save() {
if(!bChanged) {
bool ConfigSettings::Save(bool force) {
if(!force && !bChanged) {
DEBUG_FUNCTION_LINE("Nothing has changed, we can skip\n");
return true;
}

View File

@ -37,7 +37,7 @@ public:
//!Load Settings
bool Load();
//!Save Settings
bool Save();
bool Save(bool force);
//!Reset Settings
bool Reset();
@ -202,7 +202,7 @@ public:
int32_t getIdByName(std::string configID);
bool hasChanged(){
bool hasChanged() {
return bChanged;
}

View File

@ -14,6 +14,8 @@
#include "common/common.h"
#include "common/retain_vars.h"
#include "myutils/overlay_helper.h"
#include "myutils/mem_utils.h"
#include "myutils/texture_utils.h"
#include "kernel/syscalls.h"
void CallHook(wups_loader_hook_type_t hook_type) {
@ -23,13 +25,28 @@ void CallHook(wups_loader_hook_type_t hook_type) {
#ifdef __cplusplus
extern "C" {
#endif
// Part of libutils
extern uint32_t kern_read(const void *addr);
extern void kern_write(void *addr, uint32_t value);
// Part of libutils
extern uint32_t kern_read(const void *addr);
extern void kern_write(void *addr, uint32_t value);
#ifdef __cplusplus
}
#endif
bool HasHookCallHook(wups_loader_hook_type_t hook_type) {
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index];
for(int32_t j=0; j<plugin_data->number_used_hooks; j++) {
replacement_data_hook_t * hook_data = &plugin_data->hooks[j];
if(hook_data->type == hook_type) {
return true;
}
}
}
return false;
}
void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed) {
for(int32_t plugin_index=0; plugin_index<gbl_replacement_data.number_used_plugins; plugin_index++) {
replacement_data_plugin_t * plugin_data = &gbl_replacement_data.plugin_data[plugin_index];
@ -37,13 +54,13 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
continue;
}
#warning TODO: change the order of the wups_loader_hook_type_t enum before an offical release.
#warning TODO: change the order of the wups_loader_hook_type_t enum before an offical release.
//DEBUG_FUNCTION_LINE("Checking hook functions for %s.\n",plugin_data->plugin_name);
//DEBUG_FUNCTION_LINE("Found hooks: %d\n",plugin_data->number_used_hooks);
for(int32_t j=0; j<plugin_data->number_used_hooks; j++) {
replacement_data_hook_t * hook_data = &plugin_data->hooks[j];
if(hook_data->type == hook_type) {
DEBUG_FUNCTION_LINE("Calling hook of type %d for plugin %s\n",hook_data->type,plugin_data->plugin_name);
//DEBUG_FUNCTION_LINE("Calling hook of type %d for plugin %s\n",hook_data->type,plugin_data->plugin_name);
void * func_ptr = hook_data->func_pointer;
//TODO: Switch cases depending on arguments etc.
// Adding arguments!
@ -66,6 +83,8 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
} else if(hook_type == WUPS_LOADER_HOOK_INIT_OVERLAY) {
wups_loader_init_overlay_args_t args;
args.overlayfunction_ptr = &overlay_helper;
args.textureconvertfunction_ptr = &TextureUtils::convertImageToTexture;
args.drawtexturefunction_ptr = (void (*)(void*,void*,float,float,int32_t,int32_t,float)) &TextureUtils::drawTexture;
((void (*)(wups_loader_init_overlay_args_t))((uint32_t*)func_ptr) )(args);
} else if(hook_type == WUPS_LOADER_HOOK_INIT_PLUGIN) {
((void (*)(void))((uint32_t*)func_ptr) )();
@ -80,7 +99,7 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
if(gSDInitDone & WUPS_USB_MOUNTED) {
args.usb_mounted = true;
}
if(plugin_data->kernel_allowed && plugin_data->kernel_init_done){
if(plugin_data->kernel_allowed && plugin_data->kernel_init_done) {
args.kernel_access = true;
}
((void (*)(wups_loader_app_started_args_t))((uint32_t*)func_ptr) )(args);
@ -102,9 +121,9 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
status = WUPS_APP_STATUS_UNKNOWN;
}
((void (*)(wups_loader_app_status_t))((uint32_t*)func_ptr))(status);
} else if(hook_type == WUPS_LOADER_HOOK_INIT_KERNEL){
} else if(hook_type == WUPS_LOADER_HOOK_INIT_KERNEL) {
// Only call the hook if kernel is allowed.
if(plugin_data->kernel_allowed){
if(plugin_data->kernel_allowed) {
wups_loader_init_kernel_args_t args;
args.kern_read_ptr = &kern_read;
args.kern_write_ptr = &kern_write;
@ -112,6 +131,25 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
((void (*)(wups_loader_init_kernel_args_t))((uint32_t*)func_ptr) )(args);
plugin_data->kernel_init_done = true;
}
} else if(hook_type == WUPS_LOADER_HOOK_INIT_VID_MEM) {
wups_loader_init_vid_mem_args_t args;
args.vid_mem_alloc_ptr = &MemoryUtils::alloc;
args.vid_mem_free_ptr = &MemoryUtils::free;
((void (*)(wups_loader_init_vid_mem_args_t))((uint32_t*)func_ptr) )(args);
} else if(hook_type == WUPS_LOADER_HOOK_VID_DRC_DRAW) {
wups_loader_vid_buffer_t args;
args.color_buffer_ptr = &g_vid_main_cbuf;
args.tv_texture_ptr = &g_vid_tvTex;
args.drc_texture_ptr = &g_vid_drcTex;
args.sampler_ptr = &g_vid_sampler;
((void (*)(wups_loader_vid_buffer_t))((uint32_t*)func_ptr) )(args);
} else if(hook_type == WUPS_LOADER_HOOK_VID_TV_DRAW) {
wups_loader_vid_buffer_t args;
args.color_buffer_ptr = &g_vid_main_cbuf;
args.tv_texture_ptr = &g_vid_tvTex;
args.drc_texture_ptr = &g_vid_drcTex;
args.sampler_ptr = &g_vid_sampler;
((void (*)(wups_loader_vid_buffer_t))((uint32_t*)func_ptr) )(args);
} else {
DEBUG_FUNCTION_LINE("ERROR: HOOK TYPE WAS NOT IMPLEMENTED %08X \n",hook_type);
}

View File

@ -9,6 +9,7 @@ extern "C" {
#include <wups.h>
#include <stddef.h>
bool HasHookCallHook(wups_loader_hook_type_t hook_type);
void CallHook(wups_loader_hook_type_t hook_type);
void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed);