mirror of
https://github.com/Maschell/WiiUPluginLoader.git
synced 2024-11-17 13:49:18 +01:00
171 lines
5.9 KiB
C++
171 lines
5.9 KiB
C++
#include <utils/logger.h>
|
|
#include <malloc.h>
|
|
#include <wups.h>
|
|
#include "common/retain_vars.h"
|
|
#include "overlay_helper.h"
|
|
#include <dynamic_libs/gx2_functions.h>
|
|
|
|
uint32_t * getFromGX2Buffer(struct buffer_store store, uint32_t size) {
|
|
if(store.buffer != NULL) {
|
|
DEBUG_FUNCTION_LINE("We try to use the GX2 buffer. Needed space %08X (%d kb), available %08X (%d kb).\n",size,size/1024,store.buffer_size,store.buffer_size/1024);
|
|
if(store.buffer_size >= size) {
|
|
memset(store.buffer,0,store.buffer_size);
|
|
GX2Invalidate(GX2_INVALIDATE_CPU, store.buffer, store.buffer_size);
|
|
return (uint32_t*) store.buffer;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
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.
|
|
|
|
//TODO: Make sure this actually pauses the game (Hook on GX2VSync?) . Currently only tested from VPADRead which also pauses the game.
|
|
|
|
OSScreenInit();
|
|
|
|
uint32_t * screenbuffer0 = NULL;
|
|
uint32_t * screenbuffer1 = NULL;
|
|
|
|
bool allocated_tv = false;
|
|
bool allocated_drc = false;
|
|
|
|
if(screen == WUPS_OVERLAY_DRC_ONLY) {
|
|
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(1);
|
|
screenbuffer1 = getFromGX2Buffer(tv_store,screen_buf1_size);
|
|
if(screenbuffer1 == NULL) {
|
|
DEBUG_FUNCTION_LINE("We need to try to allocate buffer for the DRC.\n");
|
|
screenbuffer1 = (uint32_t*)memalign(0x100, screen_buf1_size);
|
|
if(screenbuffer1 != NULL) {
|
|
memset(screenbuffer1,0,screen_buf1_size);
|
|
DEBUG_FUNCTION_LINE("Successfully allocated DRC buffer!.\n");
|
|
allocated_drc = true;
|
|
}
|
|
}
|
|
} else if(screen == WUPS_OVERLAY_TV_ONLY) {
|
|
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(0);
|
|
screenbuffer0 = getFromGX2Buffer(tv_store,screen_buf0_size);
|
|
|
|
if(screenbuffer0 == NULL) {
|
|
DEBUG_FUNCTION_LINE("We need to try to allocate buffer for the TV.\n");
|
|
screenbuffer0 = (uint32_t*)memalign(0x100, screen_buf0_size);
|
|
if(screenbuffer0 != NULL) {
|
|
memset(screenbuffer0,0,screen_buf0_size);
|
|
DEBUG_FUNCTION_LINE("Successfully allocated TV buffer!.\n");
|
|
allocated_tv = true;
|
|
}
|
|
}
|
|
} else if( screen == WUPS_OVERLAY_DRC_AND_TV || screen == WUPS_OVERLAY_DRC_AND_TV_WITH_DRC_PRIO) {
|
|
// TV Buffer init.
|
|
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(0);
|
|
screenbuffer0 = getFromGX2Buffer(tv_store,screen_buf0_size);
|
|
if(screenbuffer0 == NULL) {
|
|
DEBUG_FUNCTION_LINE("We need to try to allocate buffer for the TV.\n");
|
|
screenbuffer0 = (uint32_t*)memalign(0x100, screen_buf0_size);
|
|
if(screenbuffer0 != NULL) {
|
|
memset(screenbuffer0,0,screen_buf0_size);
|
|
DEBUG_FUNCTION_LINE("Successfully allocated TV buffer!.\n");
|
|
allocated_tv = true;
|
|
}
|
|
}
|
|
|
|
// DRC Buffer init.
|
|
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(1);
|
|
|
|
// Doesn't fit in the GX2 DRC buffer, we don't need to check it.
|
|
DEBUG_FUNCTION_LINE("We need to try to allocate buffer for the DRC.\n");
|
|
screenbuffer1 = (uint32_t*)memalign(0x100, screen_buf1_size);
|
|
if(screenbuffer1 != NULL) {
|
|
DEBUG_FUNCTION_LINE("Successfully allocated DRC buffer!.\n");
|
|
allocated_drc = true;
|
|
}
|
|
|
|
if(screenbuffer1 == NULL) { // FAILED to allocate,
|
|
if(screen == WUPS_OVERLAY_DRC_AND_TV_WITH_DRC_PRIO) {
|
|
DEBUG_FUNCTION_LINE("Successfully allocated DRC buffer!.\n");
|
|
//but we can use the TV buffer from GX2.
|
|
if(!allocated_tv) { // Make sure it's not allocated
|
|
screenbuffer0 = NULL; // Bye bye
|
|
}
|
|
screenbuffer1 = getFromGX2Buffer(tv_store,screen_buf1_size); // Use it! Hopefully this works.
|
|
}
|
|
}
|
|
}
|
|
|
|
if(screenbuffer0 == NULL && screenbuffer1 == NULL) {
|
|
goto error_exit;
|
|
}
|
|
|
|
|
|
if(screenbuffer0 != NULL) {
|
|
OSScreenSetBufferEx(0, (void *)screenbuffer0);
|
|
}
|
|
if(screenbuffer1 != NULL) {
|
|
OSScreenSetBufferEx(1, (void *)screenbuffer1);
|
|
}
|
|
|
|
if(screenbuffer0 != NULL) {
|
|
OSScreenEnableEx(0, 1);
|
|
}
|
|
if(screenbuffer1 != NULL) {
|
|
OSScreenEnableEx(1, 1);
|
|
}
|
|
|
|
// Clear screens
|
|
if(screenbuffer0 != NULL) {
|
|
OSScreenClearBufferEx(0, 0);
|
|
}
|
|
if(screenbuffer1 != NULL) {
|
|
OSScreenClearBufferEx(1, 0);
|
|
}
|
|
|
|
// Flip buffers
|
|
if(screenbuffer0 != NULL) {
|
|
OSScreenFlipBuffersEx(0);
|
|
}
|
|
if(screenbuffer1 != NULL) {
|
|
OSScreenFlipBuffersEx(1);
|
|
}
|
|
|
|
wups_overlay_options_type_t real_screen_type;
|
|
|
|
if(screenbuffer0 != NULL) {
|
|
if(screenbuffer1 != NULL) {
|
|
real_screen_type = WUPS_OVERLAY_DRC_AND_TV;
|
|
} else {
|
|
real_screen_type = WUPS_OVERLAY_TV_ONLY;
|
|
}
|
|
} else if(screenbuffer1 != NULL) {
|
|
real_screen_type = WUPS_OVERLAY_DRC_ONLY;
|
|
} else {
|
|
real_screen_type = WUPS_OVERLAY_NONE;
|
|
}
|
|
|
|
// call the callback.
|
|
if(real_screen_type != WUPS_OVERLAY_NONE) {
|
|
callback(real_screen_type, args);
|
|
}
|
|
|
|
if(tv_store.buffer != NULL) {
|
|
GX2SetTVBuffer(tv_store.buffer,tv_store.buffer_size,tv_store.mode,tv_store.surface_format,tv_store.buffering_mode);
|
|
}
|
|
|
|
if(drc_store.buffer != NULL) {
|
|
GX2SetDRCBuffer(drc_store.buffer,drc_store.buffer_size,drc_store.mode,drc_store.surface_format,drc_store.buffering_mode);
|
|
}
|
|
|
|
error_exit:
|
|
if(allocated_tv) {
|
|
free(screenbuffer0);
|
|
screenbuffer0 = NULL;
|
|
}
|
|
|
|
if(allocated_drc) {
|
|
free(screenbuffer1);
|
|
screenbuffer1 = NULL;
|
|
}
|
|
|
|
return;
|
|
}
|