Compare commits

...

25 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
Maschell
ad759ff269 Call the callbacks when loading from SD 2019-02-07 13:01:45 +01:00
Maschell
8eaf9cc026 Remove docker image caching, use devkitpro/dekitarm image from docker hub instead of an own installation 2018-09-22 20:37:36 +02:00
39 changed files with 1066 additions and 306 deletions

View File

@ -1,24 +1,10 @@
sudo: required
before_cache:
# Save tagged docker images see https://github.com/travis-ci/travis-ci/issues/5358#issuecomment-248915326
- >
mkdir -p $HOME/docker && docker images -a --filter='dangling=false' --format '{{.Repository}}:{{.Tag}} {{.ID}}'
| grep 'wups-loader-builder'
| xargs -n 2 -t sh -c 'test -e $HOME/docker/$1.tar.gz || docker save $0 | gzip -2 > $HOME/docker/$1.tar.gz'
cache:
bundler: true
directories:
- $HOME/docker
branches:
only:
- master
services:
- docker
before_install:
# Load cached docker images
- if [[ -d $HOME/docker ]]; then ls $HOME/docker/*.tar.gz | xargs -I {file} sh -c "zcat {file} | docker load"; fi
addons:
apt:
packages:
@ -55,5 +41,3 @@ deploy:
file: WiiUPluginLoader_$versiontag.zip
on:
repo: Maschell/WiiUPluginLoader
tags: false
all_branches: true

View File

@ -4,8 +4,8 @@ FROM wups/core:latest
RUN rm -rf $DEVKITPRO/portlibs
# Install devkitARM. Needed to build mocha.
RUN yes | sudo dkp-pacman -Syu devkitARM --needed
ENV DEVKITARM=${DEVKITPRO}/devkitARM
COPY --from=devkitpro/devkitarm $DEVKITARM $DEVKITARM
# Get dependencies
COPY --from=wiiulegacy/dynamic_libs:0.1 /artifacts $DEVKITPRO/portlibs

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.
- [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.

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

@ -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

@ -28,8 +28,7 @@ DefaultGuiSelectBox::DefaultGuiSelectBox(std::string caption, GuiFrame *parent)
,valueImageData(Resources::GetImageData("gameSettingsButtonEx.png"))
,valueSelectedImageData(Resources::GetImageData("gameSettingsButtonExSelected.png"))
,valueHighlightedImageData(Resources::GetImageData("gameSettingsButtonExHighlighted.png"))
,buttonClickSound(Resources::GetSound("settings_click_2.mp3"))
{
,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

@ -28,8 +28,7 @@ DefaultGuiSwitch::DefaultGuiSwitch(bool checked)
,switchOn_imgdata(Resources::GetImageData("switchIconOn.png"))
,switchOn_img(switchOn_imgdata)
,switchOff_imgdata(Resources::GetImageData("switchIconOff.png"))
,switchOff_img(switchOff_imgdata)
{
,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

@ -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

@ -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

@ -66,7 +66,8 @@ static void KernelWriteSRs(sr_table_t * table) {
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 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++;

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,7 +557,6 @@ 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");
}
@ -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,7 +46,10 @@ 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[] = {
@ -57,6 +62,40 @@ const memory_values_t mem_vals_plugins[] = {
{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}
};
// Values needs to be aligned to 0x20000 and size needs to be a multiple of 0x20000
const memory_values_t mem_vals_heap[] = {
// 5.5.2 EUR
@ -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;
}
@ -82,19 +80,19 @@ bool ConfigInformation::loadValuesFromSD() {
if(prevValue.compare(loadedValue) != 0) {
//DEBUG_FUNCTION_LINE("Call loadValue\n");
curItem->loadValue(loadedValue);
// calling the callback here is _NOT_ needed. It will be called when the menu is closed.
curItem->callCallback();
}
}
}
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() {

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++;
@ -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),
};

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

@ -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

@ -54,8 +54,7 @@ extern const uint32_t switchIconOn_png_size;
extern const uint8_t TwitterIcon_png[];
extern const uint32_t TwitterIcon_png_size;
static ResourceFile ResourceList[] =
{
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},
@ -74,5 +73,7 @@ static ResourceFile ResourceList[] =
{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();

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) {
@ -30,6 +32,21 @@ extern "C" {
}
#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];
@ -43,7 +60,7 @@ void CallHookEx(wups_loader_hook_type_t hook_type, int32_t plugin_index_needed)
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) )();
@ -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);