(CTR) Stylistic cleanups
This commit is contained in:
parent
dc24530382
commit
860f94e914
|
@ -24,4 +24,4 @@ void dump_result_value(Result val);
|
||||||
#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
|
#define PRINTFPOS_STR(X,Y) "\x1b["X";"Y"H"
|
||||||
#define PRINTF_LINE(X) "\x1b["X";0H"
|
#define PRINTF_LINE(X) "\x1b["X";0H"
|
||||||
|
|
||||||
#endif //_CTR_DEBUG_H__
|
#endif /* _CTR_DEBUG_H__ */
|
||||||
|
|
|
@ -88,7 +88,9 @@ struct MemPool
|
||||||
last = nullptr;
|
last = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//void Dump(const char* title);
|
#if 0
|
||||||
|
void Dump(const char* title);
|
||||||
|
#endif
|
||||||
u32 GetFreeSpace();
|
u32 GetFreeSpace();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,25 +161,25 @@ static bool linearInit(void)
|
||||||
|
|
||||||
void* linearMemAlign(size_t size, size_t alignment)
|
void* linearMemAlign(size_t size, size_t alignment)
|
||||||
{
|
{
|
||||||
// Enforce minimum alignment
|
int shift;
|
||||||
|
/* Enforce minimum alignment */
|
||||||
if (alignment < 16)
|
if (alignment < 16)
|
||||||
alignment = 16;
|
alignment = 16;
|
||||||
|
|
||||||
// Convert alignment to shift amount
|
/* Convert alignment to shift amount */
|
||||||
int shift;
|
|
||||||
for (shift = 4; shift < 32; shift ++)
|
for (shift = 4; shift < 32; shift ++)
|
||||||
{
|
{
|
||||||
if ((1U<<shift) == alignment)
|
if ((1U<<shift) == alignment)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (shift == 32) // Invalid alignment
|
if (shift == 32) /* Invalid alignment */
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Initialize the pool if it is not ready
|
/* Initialize the pool if it is not ready */
|
||||||
if (!sLinearPool.Ready() && !linearInit())
|
if (!sLinearPool.Ready() && !linearInit())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Allocate the chunk
|
/* Allocate the chunk */
|
||||||
MemChunk chunk;
|
MemChunk chunk;
|
||||||
if (!sLinearPool.Allocate(chunk, size, shift))
|
if (!sLinearPool.Allocate(chunk, size, shift))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -211,23 +213,24 @@ void* linearAlloc(size_t size)
|
||||||
|
|
||||||
void* linearRealloc(void* mem, size_t size)
|
void* linearRealloc(void* mem, size_t size)
|
||||||
{
|
{
|
||||||
// TODO
|
/* TODO */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void linearFree(void* mem)
|
void linearFree(void* mem)
|
||||||
{
|
{
|
||||||
auto node = getNode(mem);
|
auto node = getNode(mem);
|
||||||
if (!node) return;
|
if (!node)
|
||||||
|
return;
|
||||||
|
|
||||||
// Free the chunk
|
/* Free the chunk */
|
||||||
sLinearPool.Deallocate(node->chunk);
|
sLinearPool.Deallocate(node->chunk);
|
||||||
|
|
||||||
// Free the node
|
/* Free the node */
|
||||||
delNode(node);
|
delNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 linearSpaceFree()
|
u32 linearSpaceFree(void)
|
||||||
{
|
{
|
||||||
return sLinearPool.GetFreeSpace();
|
return sLinearPool.GetFreeSpace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ u32 ctr_get_linear_unused(void);
|
||||||
u32 ctr_get_stack_free(void)
|
u32 ctr_get_stack_free(void)
|
||||||
{
|
{
|
||||||
extern u32 __stack_bottom;
|
extern u32 __stack_bottom;
|
||||||
|
|
||||||
uint32_t* stack_bottom_current = (u32*)__stack_bottom;
|
uint32_t* stack_bottom_current = (u32*)__stack_bottom;
|
||||||
|
|
||||||
while(*stack_bottom_current++ == 0xFCFCFCFC);
|
while(*stack_bottom_current++ == 0xFCFCFCFC);
|
||||||
stack_bottom_current--;
|
stack_bottom_current--;
|
||||||
|
|
||||||
|
@ -110,12 +110,11 @@ void ctr_request_free_pages(u32 pages)
|
||||||
void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
|
void* _sbrk_r(struct _reent *ptr, ptrdiff_t incr)
|
||||||
{
|
{
|
||||||
static u32 sbrk_top = 0;
|
static u32 sbrk_top = 0;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
if (!sbrk_top)
|
if (!sbrk_top)
|
||||||
sbrk_top = __heapBase;
|
sbrk_top = __heapBase;
|
||||||
|
|
||||||
u32 tmp;
|
|
||||||
|
|
||||||
int diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
|
int diff = ((sbrk_top + incr + 0xFFF) & ~0xFFF)
|
||||||
- (__heapBase + __heap_size);
|
- (__heapBase + __heap_size);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ extern void* __service_ptr;
|
||||||
typedef u32(*backdoor_fn)(u32 arg0, u32 arg1);
|
typedef u32(*backdoor_fn)(u32 arg0, u32 arg1);
|
||||||
|
|
||||||
__attribute((naked))
|
__attribute((naked))
|
||||||
static u32 svc_7b(backdoor_fn entry_fn, ...) // can pass up to two arguments to entry_fn(...)
|
static u32 svc_7b(backdoor_fn entry_fn, ...) /* can pass up to two arguments to entry_fn(...) */
|
||||||
{
|
{
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
"push {r0, r1, r2} \n\t"
|
"push {r0, r1, r2} \n\t"
|
||||||
|
@ -161,19 +161,17 @@ static void target_thread_entry(mch2_thread_args_t* args)
|
||||||
static u32 get_first_free_basemem_page(bool isNew3DS)
|
static u32 get_first_free_basemem_page(bool isNew3DS)
|
||||||
{
|
{
|
||||||
s64 v1;
|
s64 v1;
|
||||||
int memused_base;
|
int memused_base_linear; /* guessed */
|
||||||
int memused_base_linear; // guessed
|
int memused_base = osGetMemRegionUsed(MEMREGION_BASE);
|
||||||
|
|
||||||
memused_base = osGetMemRegionUsed(MEMREGION_BASE);
|
|
||||||
|
|
||||||
svcGetSystemInfo(&v1, 2, 0);
|
svcGetSystemInfo(&v1, 2, 0);
|
||||||
memused_base_linear = 0x6C000 + v1 +
|
memused_base_linear = 0x6C000 + v1 +
|
||||||
(osGetKernelVersion() > SYSTEM_VERSION(2, 49, 0) ? (isNew3DS ? 0x2000 : 0x1000) : 0x0);
|
(osGetKernelVersion() > SYSTEM_VERSION(2, 49, 0) ? (isNew3DS ? 0x2000 : 0x1000) : 0x0);
|
||||||
|
|
||||||
return (osGetKernelVersion() > SYSTEM_VERSION(2, 40, 0) ? 0xE0000000 : 0xF0000000) // kernel FCRAM mapping
|
return (osGetKernelVersion() > SYSTEM_VERSION(2, 40, 0) ? 0xE0000000 : 0xF0000000) /* kernel FCRAM mapping */
|
||||||
+ (isNew3DS ? 0x10000000 : 0x08000000) // FCRAM size
|
+ (isNew3DS ? 0x10000000 : 0x08000000) /* FCRAM size */
|
||||||
- (memused_base - memused_base_linear) // memory usage for pages allocated without the MEMOP_LINEAR flag
|
- (memused_base - memused_base_linear) /* memory usage for pages allocated without the MEMOP_LINEAR flag */
|
||||||
- 0x1000; // skip to the start addr of the next free page
|
- 0x1000; /* skip to the start addr of the next free page */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +278,7 @@ static void do_memchunkhax2(void)
|
||||||
|
|
||||||
u32 alloc_address_kaddr = osConvertVirtToPhys((void*)linear_address) + mch2.kernel_fcram_mapping_offset;
|
u32 alloc_address_kaddr = osConvertVirtToPhys((void*)linear_address) + mch2.kernel_fcram_mapping_offset;
|
||||||
|
|
||||||
mch2.thread_page_kva = get_first_free_basemem_page(mch2.isNew3DS) - 0x10000; // skip down 16 pages
|
mch2.thread_page_kva = get_first_free_basemem_page(mch2.isNew3DS) - 0x10000; /* skip down 16 pages */
|
||||||
((u32*)linear_buffer)[0] = 1;
|
((u32*)linear_buffer)[0] = 1;
|
||||||
((u32*)linear_buffer)[1] = mch2.thread_page_kva;
|
((u32*)linear_buffer)[1] = mch2.thread_page_kva;
|
||||||
((u32*)linear_buffer)[2] = alloc_address_kaddr + (((mch2.alloc_size >> 12) - 3) << 13) + (skip_pages << 12);
|
((u32*)linear_buffer)[2] = alloc_address_kaddr + (((mch2.alloc_size >> 12) - 3) << 13) + (skip_pages << 12);
|
||||||
|
@ -404,8 +402,9 @@ static void gspwn(u32 dst, u32 src, u32 size, u8* flush_buffer)
|
||||||
* *(u32*)val1 = 0x0;
|
* *(u32*)val1 = 0x0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// X-X--X-X
|
/* X-X--X-X
|
||||||
// X-XXXX-X
|
* X-XXXX-X
|
||||||
|
*/
|
||||||
|
|
||||||
static void memchunkhax1_write_pair(u32 val1, u32 val2)
|
static void memchunkhax1_write_pair(u32 val1, u32 val2)
|
||||||
{
|
{
|
||||||
|
@ -458,23 +457,24 @@ static void do_memchunkhax1(void)
|
||||||
{
|
{
|
||||||
u32 saved_vram_value = *(u32*)0x1F000008;
|
u32 saved_vram_value = *(u32*)0x1F000008;
|
||||||
|
|
||||||
// 0x1F000000 contains the enable bit for svc 0x7B
|
/* 0x1F000000 contains the enable bit for svc 0x7B */
|
||||||
memchunkhax1_write_pair(get_thread_page() + THREAD_PAGE_ACL_OFFSET + SVC_ACL_OFFSET(0x7B), 0x1F000000);
|
memchunkhax1_write_pair(get_thread_page() + THREAD_PAGE_ACL_OFFSET + SVC_ACL_OFFSET(0x7B), 0x1F000000);
|
||||||
|
|
||||||
write_kaddr(0x1F000008, saved_vram_value);
|
write_kaddr(0x1F000008, saved_vram_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result get_luma_version(u32 *major, u32 *minor) {
|
Result get_luma_version(u32 *major, u32 *minor)
|
||||||
s64 out;
|
{
|
||||||
u32 version;
|
s64 out;
|
||||||
|
u32 version;
|
||||||
|
|
||||||
if (R_FAILED(svcGetSystemInfo(&out, 0x10000, 0)))
|
if (R_FAILED(svcGetSystemInfo(&out, 0x10000, 0)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
version = (u32)out;
|
version = (u32)out;
|
||||||
*major = GET_VERSION_MAJOR(version);
|
*major = GET_VERSION_MAJOR(version);
|
||||||
*minor = GET_VERSION_MINOR(version);
|
*minor = GET_VERSION_MINOR(version);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result svchax_init(bool patch_srv)
|
Result svchax_init(bool patch_srv)
|
||||||
|
|
|
@ -9,76 +9,89 @@ extern const loaderFuncs_s loader_Ninjhax1;
|
||||||
extern const loaderFuncs_s loader_Ninjhax2;
|
extern const loaderFuncs_s loader_Ninjhax2;
|
||||||
extern const loaderFuncs_s loader_Rosalina;
|
extern const loaderFuncs_s loader_Rosalina;
|
||||||
|
|
||||||
static void (*launch_3dsx)(const char* path, argData_s* args, executableMetadata_s* em);
|
static void (*launch_3dsx)(const char* path,
|
||||||
|
argData_s* args, executableMetadata_s* em);
|
||||||
|
|
||||||
static int exec_3dsx_actual(const char* path, const char** args, bool appendPath){
|
static int exec_3dsx_actual(const char* path,
|
||||||
struct stat sBuff;
|
const char** args, bool appendPath)
|
||||||
argData_s newProgramArgs;
|
{
|
||||||
unsigned int argChars = 0;
|
struct stat sBuff;
|
||||||
unsigned int argNum = 0;
|
argData_s newProgramArgs;
|
||||||
bool fileExists;
|
unsigned int argChars = 0;
|
||||||
bool inited;
|
unsigned int argNum = 0;
|
||||||
|
bool fileExists;
|
||||||
|
bool inited;
|
||||||
|
|
||||||
if (!path || path[0] == '\0')
|
if (!path || path[0] == '\0')
|
||||||
{
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileExists = stat(path, &sBuff) == 0;
|
fileExists = stat(path, &sBuff) == 0;
|
||||||
if(!fileExists){
|
if (!fileExists)
|
||||||
errno = ENOENT;
|
{
|
||||||
return -1;
|
errno = ENOENT;
|
||||||
}
|
return -1;
|
||||||
else if(S_ISDIR(sBuff.st_mode)){
|
}
|
||||||
errno = EINVAL;
|
else if (S_ISDIR(sBuff.st_mode))
|
||||||
return -1;
|
{
|
||||||
}
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//args the string functions write to the passed string, this will cause a write to read only memory sot the string must be cloned
|
/* args the string functions write to the passed string,
|
||||||
memset(newProgramArgs.buf, '\0', sizeof(newProgramArgs.buf));
|
* this will cause a write to read only memory,
|
||||||
newProgramArgs.dst = (char*)&newProgramArgs.buf[1];
|
* so the string must be cloned */
|
||||||
if(appendPath){
|
memset(newProgramArgs.buf, '\0', sizeof(newProgramArgs.buf));
|
||||||
strcpy(newProgramArgs.dst, path);
|
newProgramArgs.dst = (char*)&newProgramArgs.buf[1];
|
||||||
newProgramArgs.dst += strlen(path) + 1;
|
if (appendPath)
|
||||||
newProgramArgs.buf[0]++;
|
{
|
||||||
|
strcpy(newProgramArgs.dst, path);
|
||||||
|
newProgramArgs.dst += strlen(path) + 1;
|
||||||
|
newProgramArgs.buf[0]++;
|
||||||
|
}
|
||||||
|
while(args[argNum] != NULL)
|
||||||
|
{
|
||||||
|
strcpy(newProgramArgs.dst, args[argNum]);
|
||||||
|
newProgramArgs.dst += strlen(args[argNum]) + 1;
|
||||||
|
newProgramArgs.buf[0]++;
|
||||||
|
argNum++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
inited = loader_Rosalina.init();
|
||||||
while(args[argNum] != NULL){
|
launch_3dsx = loader_Rosalina.launchFile;
|
||||||
strcpy(newProgramArgs.dst, args[argNum]);
|
|
||||||
newProgramArgs.dst += strlen(args[argNum]) + 1;
|
|
||||||
newProgramArgs.buf[0]++;
|
|
||||||
argNum++;
|
|
||||||
}
|
|
||||||
|
|
||||||
inited = loader_Rosalina.init();
|
if (!inited)
|
||||||
launch_3dsx = loader_Rosalina.launchFile;
|
{
|
||||||
|
inited = loader_Ninjhax2.init();
|
||||||
|
launch_3dsx = loader_Ninjhax2.launchFile;
|
||||||
|
}
|
||||||
|
|
||||||
if(!inited){
|
if (!inited)
|
||||||
inited = loader_Ninjhax2.init();
|
{
|
||||||
launch_3dsx = loader_Ninjhax2.launchFile;
|
inited = loader_Ninjhax1.init();
|
||||||
}
|
launch_3dsx = loader_Ninjhax1.launchFile;
|
||||||
|
}
|
||||||
|
|
||||||
if(!inited){
|
if (inited)
|
||||||
inited = loader_Ninjhax1.init();
|
{
|
||||||
launch_3dsx = loader_Ninjhax1.launchFile;
|
osSetSpeedupEnable(false);
|
||||||
}
|
launch_3dsx(path, &newProgramArgs, NULL);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if(inited){
|
/* should never be reached */
|
||||||
osSetSpeedupEnable(false);
|
errno = ENOTSUP;
|
||||||
launch_3dsx(path, &newProgramArgs, NULL);
|
return -1;
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//should never be reached
|
|
||||||
errno = ENOTSUP;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int exec_3dsx(const char* path, const char** args){
|
int exec_3dsx(const char* path, const char** args)
|
||||||
return exec_3dsx_actual(path, args, true/*appendPath*/);
|
{
|
||||||
|
return exec_3dsx_actual(path, args, true/*appendPath*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
int exec_3dsx_no_path_in_args(const char* path, const char** args){
|
int exec_3dsx_no_path_in_args(const char* path, const char** args)
|
||||||
return exec_3dsx_actual(path, args, false/*appendPath*/);
|
{
|
||||||
|
return exec_3dsx_actual(path, args, false/*appendPath*/);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#ifndef EXEC_3DSX_H
|
#ifndef EXEC_3DSX_H
|
||||||
#define EXEC_3DSX_H
|
#define EXEC_3DSX_H
|
||||||
|
|
||||||
//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program
|
/* since 3dsx programs are not guaranteed access to the OS,
|
||||||
//your program must have no extra threads running when this is called, these limits do not apply to exec_cia
|
* the 3dsx bootloader run by the exploit must run the next program
|
||||||
|
*
|
||||||
|
* your program must have no extra threads running when this is called,
|
||||||
|
* these limits do not apply to exec_cia
|
||||||
|
*/
|
||||||
int exec_3dsx_no_path_in_args(const char* path, const char** args);
|
int exec_3dsx_no_path_in_args(const char* path, const char** args);
|
||||||
|
|
||||||
int exec_3dsx(const char* path, const char** args);
|
int exec_3dsx(const char* path, const char** args);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,188 +13,204 @@ typedef struct{
|
||||||
|
|
||||||
char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
|
char argvHmac[0x20] = {0x1d, 0x78, 0xff, 0xb9, 0xc5, 0xbc, 0x78, 0xb7, 0xac, 0x29, 0x1d, 0x3e, 0x16, 0xd0, 0xcf, 0x53, 0xef, 0x12, 0x58, 0x83, 0xb6, 0x9e, 0x2f, 0x79, 0x47, 0xf9, 0x35, 0x61, 0xeb, 0x50, 0xd7, 0x67};
|
||||||
|
|
||||||
static void errorAndQuit(const char* errorStr){
|
static void errorAndQuit(const char* errorStr)
|
||||||
errorConf error;
|
{
|
||||||
|
errorConf error;
|
||||||
|
|
||||||
errorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN);
|
errorInit(&error, ERROR_TEXT, CFG_LANGUAGE_EN);
|
||||||
errorText(&error, errorStr);
|
errorText(&error, errorStr);
|
||||||
errorDisp(&error);
|
errorDisp(&error);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isCiaInstalled(u64 titleId, u16 version){
|
static int isCiaInstalled(u64 titleId, u16 version)
|
||||||
u32 titlesToRetrieve;
|
{
|
||||||
u32 titlesRetrieved;
|
u32 titlesToRetrieve;
|
||||||
u64* titleIds;
|
u32 titlesRetrieved;
|
||||||
bool titleExists = false;
|
u64* titleIds;
|
||||||
AM_TitleEntry titleInfo;
|
bool titleExists = false;
|
||||||
Result failed;
|
AM_TitleEntry titleInfo;
|
||||||
|
Result failed;
|
||||||
|
|
||||||
failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
|
failed = AM_GetTitleCount(MEDIATYPE_SD, &titlesToRetrieve);
|
||||||
if(R_FAILED(failed))
|
if (R_FAILED(failed))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
titleIds = malloc(titlesToRetrieve * sizeof(uint64_t));
|
titleIds = malloc(titlesToRetrieve * sizeof(uint64_t));
|
||||||
if (!titleIds)
|
if (!titleIds)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
failed = AM_GetTitleList(&titlesRetrieved, MEDIATYPE_SD, titlesToRetrieve, titleIds);
|
failed = AM_GetTitleList(&titlesRetrieved, MEDIATYPE_SD, titlesToRetrieve, titleIds);
|
||||||
if(R_FAILED(failed))
|
if (R_FAILED(failed))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++){
|
for(u32 titlesToCheck = 0; titlesToCheck < titlesRetrieved; titlesToCheck++)
|
||||||
if(titleIds[titlesToCheck] == titleId){
|
{
|
||||||
titleExists = true;
|
if (titleIds[titlesToCheck] == titleId)
|
||||||
break;
|
{
|
||||||
}
|
titleExists = true;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(titleIds);
|
free(titleIds);
|
||||||
|
|
||||||
if(titleExists){
|
if (titleExists)
|
||||||
failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo);
|
{
|
||||||
if(R_FAILED(failed))
|
failed = AM_GetTitleInfo(MEDIATYPE_SD, 1 /*titleCount*/, &titleId, &titleInfo);
|
||||||
return -1;
|
if (R_FAILED(failed))
|
||||||
|
return -1;
|
||||||
|
|
||||||
if(titleInfo.version == version)
|
if (titleInfo.version == version)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int installCia(Handle ciaFile){
|
static int installCia(Handle ciaFile)
|
||||||
Result failed;
|
{
|
||||||
Handle outputHandle;
|
Result failed;
|
||||||
u64 fileSize;
|
Handle outputHandle;
|
||||||
u64 fileOffset = 0;
|
u64 fileSize;
|
||||||
u32 bytesRead;
|
u64 fileOffset = 0;
|
||||||
u32 bytesWritten;
|
u32 bytesRead;
|
||||||
u8 transferBuffer[FILE_CHUNK_SIZE];
|
u32 bytesWritten;
|
||||||
|
u8 transferBuffer[FILE_CHUNK_SIZE];
|
||||||
|
|
||||||
failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
|
failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle);
|
||||||
if(R_FAILED(failed))
|
if (R_FAILED(failed))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
failed = FSFILE_GetSize(ciaFile, &fileSize);
|
failed = FSFILE_GetSize(ciaFile, &fileSize);
|
||||||
if(R_FAILED(failed))
|
if (R_FAILED(failed))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
while(fileOffset < fileSize){
|
while(fileOffset < fileSize)
|
||||||
u64 bytesRemaining = fileSize - fileOffset;
|
{
|
||||||
failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE);
|
u64 bytesRemaining = fileSize - fileOffset;
|
||||||
if(R_FAILED(failed)){
|
failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE);
|
||||||
AM_CancelCIAInstall(outputHandle);
|
if (R_FAILED(failed))
|
||||||
return -1;
|
{
|
||||||
}
|
AM_CancelCIAInstall(outputHandle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0);
|
failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0);
|
||||||
if(R_FAILED(failed)){
|
if (R_FAILED(failed))
|
||||||
AM_CancelCIAInstall(outputHandle);
|
{
|
||||||
if(R_DESCRIPTION(failed) == RD_ALREADY_EXISTS)
|
AM_CancelCIAInstall(outputHandle);
|
||||||
return 1;
|
if (R_DESCRIPTION(failed) == RD_ALREADY_EXISTS)
|
||||||
return -1;
|
return 1;
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if(bytesWritten != bytesRead){
|
if (bytesWritten != bytesRead)
|
||||||
AM_CancelCIAInstall(outputHandle);
|
{
|
||||||
return -1;
|
AM_CancelCIAInstall(outputHandle);
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
fileOffset += bytesWritten;
|
fileOffset += bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
failed = AM_FinishCiaInstall(outputHandle);
|
failed = AM_FinishCiaInstall(outputHandle);
|
||||||
if(R_FAILED(failed))
|
if (R_FAILED(failed))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exec_cia(const char* path, const char** args){
|
int exec_cia(const char* path, const char** args)
|
||||||
struct stat sBuff;
|
{
|
||||||
bool fileExists;
|
struct stat sBuff;
|
||||||
bool inited;
|
bool fileExists;
|
||||||
|
bool inited;
|
||||||
|
|
||||||
if (!path || path[0] == '\0')
|
if (!path || path[0] == '\0')
|
||||||
{
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileExists = stat(path, &sBuff) == 0;
|
fileExists = stat(path, &sBuff) == 0;
|
||||||
if(!fileExists){
|
if (!fileExists)
|
||||||
errno = ENOENT;
|
{
|
||||||
return -1;
|
errno = ENOENT;
|
||||||
}
|
return -1;
|
||||||
else if(S_ISDIR(sBuff.st_mode)){
|
}
|
||||||
errno = EINVAL;
|
else if (S_ISDIR(sBuff.st_mode))
|
||||||
return -1;
|
{
|
||||||
}
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
|
inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit());
|
||||||
if(inited){
|
if (inited)
|
||||||
Result res;
|
{
|
||||||
AM_TitleEntry ciaInfo;
|
AM_TitleEntry ciaInfo;
|
||||||
FS_Archive ciaArchive;
|
FS_Archive ciaArchive;
|
||||||
Handle ciaFile;
|
Handle ciaFile;
|
||||||
int ciaInstalled;
|
int ciaInstalled;
|
||||||
ciaParam param;
|
ciaParam param;
|
||||||
int argsLength;
|
int argsLength;
|
||||||
|
/* open CIA file */
|
||||||
|
Result res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
|
||||||
|
|
||||||
//open cia file
|
if (R_FAILED(res))
|
||||||
res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""));
|
errorAndQuit("Cant open SD FS archive.");
|
||||||
if(R_FAILED(res))
|
|
||||||
errorAndQuit("Cant open SD FS archive.");
|
|
||||||
|
|
||||||
res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
|
res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0);
|
||||||
if(R_FAILED(res))
|
if (R_FAILED(res))
|
||||||
errorAndQuit("Cant open CIA file.");
|
errorAndQuit("Cant open CIA file.");
|
||||||
|
|
||||||
res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile);
|
res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile);
|
||||||
if(R_FAILED(res))
|
if (R_FAILED(res))
|
||||||
errorAndQuit("Cant get CIA file info.");
|
errorAndQuit("Cant get CIA file info.");
|
||||||
|
|
||||||
ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version);
|
ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version);
|
||||||
if(ciaInstalled == -1){
|
if (ciaInstalled == -1)
|
||||||
//error
|
{
|
||||||
errorAndQuit("Could not read title id list.");
|
/* error */
|
||||||
}
|
errorAndQuit("Could not read title ID list.");
|
||||||
else if(ciaInstalled == 0){
|
}
|
||||||
//not installed
|
else if (ciaInstalled == 0)
|
||||||
int error = installCia(ciaFile);
|
{
|
||||||
if(error == -1)
|
/* not installed */
|
||||||
errorAndQuit("Cant install CIA.");
|
int error = installCia(ciaFile);
|
||||||
}
|
if (error == -1)
|
||||||
|
errorAndQuit("Cant install CIA.");
|
||||||
|
}
|
||||||
|
|
||||||
FSFILE_Close(ciaFile);
|
FSFILE_Close(ciaFile);
|
||||||
FSUSER_CloseArchive(ciaArchive);
|
FSUSER_CloseArchive(ciaArchive);
|
||||||
|
|
||||||
param.argc = 0;
|
param.argc = 0;
|
||||||
argsLength = 0;
|
argsLength = 0;
|
||||||
char* argLocation = param.args;
|
char* argLocation = param.args;
|
||||||
while(args[param.argc] != NULL){
|
while(args[param.argc] != NULL)
|
||||||
strcpy(argLocation, args[param.argc]);
|
{
|
||||||
argLocation += strlen(args[param.argc]) + 1;
|
strcpy(argLocation, args[param.argc]);
|
||||||
argsLength += strlen(args[param.argc]) + 1;
|
argLocation += strlen(args[param.argc]) + 1;
|
||||||
param.argc++;
|
argsLength += strlen(args[param.argc]) + 1;
|
||||||
}
|
param.argc++;
|
||||||
|
}
|
||||||
|
|
||||||
res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1);
|
res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1);
|
||||||
if(R_FAILED(res))
|
if (R_FAILED(res))
|
||||||
errorAndQuit("CIA cant run, cant prepare.");
|
errorAndQuit("CIA cant run, cant prepare.");
|
||||||
|
|
||||||
res = APT_DoApplicationJump(¶m, sizeof(param.argc) + argsLength, argvHmac);
|
res = APT_DoApplicationJump(¶m, sizeof(param.argc) + argsLength, argvHmac);
|
||||||
if(R_FAILED(res))
|
if (R_FAILED(res))
|
||||||
errorAndQuit("CIA cant run, cant jump.");
|
errorAndQuit("CIA cant run, cant jump.");
|
||||||
|
|
||||||
//wait for application jump, for some reason its not instant
|
/* wait for application jump, for some reason its not instant */
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//should never be reached
|
/* should never be reached */
|
||||||
amExit();
|
amExit();
|
||||||
fsExit();
|
fsExit();
|
||||||
errno = ENOTSUP;
|
errno = ENOTSUP;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// C stdlib includes
|
/* C stdlib includes */
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
// 3DS includes
|
/* 3DS includes */
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
|
||||||
#define ENTRY_ARGBUFSIZE 0x400
|
#define ENTRY_ARGBUFSIZE 0x400
|
||||||
|
@ -73,7 +73,7 @@ typedef struct
|
||||||
u32 processAppCodeAddress;
|
u32 processAppCodeAddress;
|
||||||
u32 processHookTidLow, processHookTidHigh;
|
u32 processHookTidLow, processHookTidHigh;
|
||||||
u32 mediatype;
|
u32 mediatype;
|
||||||
bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...}
|
bool capabilities[0x10]; /* {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...} */
|
||||||
} memmap_header_t;
|
} memmap_header_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
|
@ -2,21 +2,21 @@
|
||||||
|
|
||||||
Handle launchOpenFile(const char* path)
|
Handle launchOpenFile(const char* path)
|
||||||
{
|
{
|
||||||
if (strncmp(path, "sdmc:/", 6) == 0)
|
Handle file;
|
||||||
path += 5;
|
if (strncmp(path, "sdmc:/", 6) == 0)
|
||||||
else if (*path != '/')
|
path += 5;
|
||||||
return 0;
|
else if (*path != '/')
|
||||||
|
return 0;
|
||||||
|
|
||||||
// Convert the executable path to UTF-16
|
/* Convert the executable path to UTF-16 */
|
||||||
static uint16_t __utf16path[PATH_MAX+1];
|
static uint16_t __utf16path[PATH_MAX+1];
|
||||||
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX);
|
ssize_t units = utf8_to_utf16(__utf16path, (const uint8_t*)path, PATH_MAX);
|
||||||
if (units < 0 || units >= PATH_MAX) return 0;
|
if (units < 0 || units >= PATH_MAX) return 0;
|
||||||
__utf16path[units] = 0;
|
__utf16path[units] = 0;
|
||||||
|
|
||||||
// Open the file directly
|
/* Open the file directly */
|
||||||
FS_Path apath = { PATH_EMPTY, 1, (u8*)"" };
|
FS_Path apath = { PATH_EMPTY, 1, (u8*)"" };
|
||||||
FS_Path fpath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
|
FS_Path fpath = { PATH_UTF16, (units+1)*2, (u8*)__utf16path };
|
||||||
Handle file;
|
Result res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, apath, fpath, FS_OPEN_READ, 0);
|
||||||
Result res = FSUSER_OpenFileDirectly(&file, ARCHIVE_SDMC, apath, fpath, FS_OPEN_READ, 0);
|
return R_SUCCEEDED(res) ? file : 0;
|
||||||
return R_SUCCEEDED(res) ? file : 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,15 +12,15 @@ enum
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
// Mandatory fields
|
/* Mandatory fields */
|
||||||
const char* name;
|
const char* name;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
bool (* init)(void);
|
bool (* init)(void);
|
||||||
void (* deinit)(void);
|
void (* deinit)(void);
|
||||||
void (* launchFile)(const char* path, argData_s* args, executableMetadata_s* em);
|
void (* launchFile)(const char* path, argData_s* args, executableMetadata_s* em);
|
||||||
|
|
||||||
// Optional fields
|
/* Optional fields */
|
||||||
void (* useTitle)(u64 tid, u8 mediatype);
|
void (* useTitle)(u64 tid, u8 mediatype);
|
||||||
} loaderFuncs_s;
|
} loaderFuncs_s;
|
||||||
|
|
||||||
Handle launchOpenFile(const char* path);
|
Handle launchOpenFile(const char* path);
|
||||||
|
|
|
@ -69,5 +69,7 @@ const loaderFuncs_s loader_Ninjhax2 =
|
||||||
.init = init,
|
.init = init,
|
||||||
.deinit = deinit,
|
.deinit = deinit,
|
||||||
.launchFile = launchFile,
|
.launchFile = launchFile,
|
||||||
//.useTitle = useTitle,
|
#if 0
|
||||||
|
.useTitle = useTitle,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ static Result HBLDR_SetTarget(const char* path)
|
||||||
u32 pathLen = strlen(path) + 1;
|
u32 pathLen = strlen(path) + 1;
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
u32* cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(2, 0, 2); //0x20002
|
cmdbuf[0] = IPC_MakeHeader(2, 0, 2); /* 0x20002 */
|
||||||
cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0);
|
cmdbuf[1] = IPC_Desc_StaticBuffer(pathLen, 0);
|
||||||
cmdbuf[2] = (u32)path;
|
cmdbuf[2] = (u32)path;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ static Result HBLDR_SetArgv(const void* buffer, u32 size)
|
||||||
{
|
{
|
||||||
u32* cmdbuf = getThreadCommandBuffer();
|
u32* cmdbuf = getThreadCommandBuffer();
|
||||||
|
|
||||||
cmdbuf[0] = IPC_MakeHeader(3, 0, 2); //0x30002
|
cmdbuf[0] = IPC_MakeHeader(3, 0, 2); /* 0x30002 */
|
||||||
cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1);
|
cmdbuf[1] = IPC_Desc_StaticBuffer(size, 1);
|
||||||
cmdbuf[2] = (u32)buffer;
|
cmdbuf[2] = (u32)buffer;
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
void GPU_Init(Handle *gsphandle)
|
void GPU_Init(Handle *gsphandle)
|
||||||
{
|
{
|
||||||
gpuCmdBuf=NULL;
|
gpuCmdBuf = NULL;
|
||||||
gpuCmdBufSize=0;
|
gpuCmdBufSize = 0;
|
||||||
gpuCmdBufOffset=0;
|
gpuCmdBufOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize)
|
void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize)
|
||||||
|
@ -27,16 +27,18 @@ void GPU_Reset(u32* gxbuf, u32* gpuBuf, u32 gpuBufSize)
|
||||||
|
|
||||||
void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numreg)
|
void GPU_SetFloatUniform(GPU_SHADER_TYPE type, u32 startreg, u32* data, u32 numreg)
|
||||||
{
|
{
|
||||||
if(!data)return;
|
if(!data)
|
||||||
|
return;
|
||||||
|
|
||||||
int regOffset=(type==GPU_GEOMETRY_SHADER)?(-0x30):(0x0);
|
int regOffset = (type == GPU_GEOMETRY_SHADER) ? (-0x30) : (0x0);
|
||||||
|
|
||||||
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+regOffset, 0x80000000|startreg);
|
GPUCMD_AddWrite(GPUREG_VSH_FLOATUNIFORM_CONFIG+regOffset, 0x80000000|startreg);
|
||||||
GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+regOffset, data, numreg*4);
|
GPUCMD_AddWrites(GPUREG_VSH_FLOATUNIFORM_DATA+regOffset, data, numreg*4);
|
||||||
}
|
}
|
||||||
|
|
||||||
//takes PAs as arguments
|
/* takes PAs as arguments */
|
||||||
void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u32 h)
|
void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer,
|
||||||
|
u32 x, u32 y, u32 w, u32 h)
|
||||||
{
|
{
|
||||||
u32 param[0x4];
|
u32 param[0x4];
|
||||||
float fw=(float)w;
|
float fw=(float)w;
|
||||||
|
@ -53,9 +55,9 @@ void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u3
|
||||||
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 0x00000003);
|
GPUCMD_AddIncrementalWrites(GPUREG_DEPTHBUFFER_LOC, param, 0x00000003);
|
||||||
|
|
||||||
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, f116e);
|
GPUCMD_AddWrite(GPUREG_RENDERBUF_DIM, f116e);
|
||||||
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 0x00000003); //depth buffer format
|
GPUCMD_AddWrite(GPUREG_DEPTHBUFFER_FORMAT, 0x00000003); /* depth buffer format */
|
||||||
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0x00000002); //color buffer format
|
GPUCMD_AddWrite(GPUREG_COLORBUFFER_FORMAT, 0x00000002); /* color buffer format */
|
||||||
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); //?
|
GPUCMD_AddWrite(GPUREG_FRAMEBUFFER_BLOCK32, 0x00000000); /* ? */
|
||||||
|
|
||||||
param[0x0]=f32tof24(fw/2);
|
param[0x0]=f32tof24(fw/2);
|
||||||
param[0x1]=f32tof31(2.0f / fw) << 1;
|
param[0x1]=f32tof31(2.0f / fw) << 1;
|
||||||
|
@ -70,7 +72,7 @@ void GPU_SetViewport(u32* depthBuffer, u32* colorBuffer, u32 x, u32 y, u32 w, u3
|
||||||
param[0x2]=((h-1)<<16)|((w-1)&0xFFFF);
|
param[0x2]=((h-1)<<16)|((w-1)&0xFFFF);
|
||||||
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, param, 0x00000003);
|
GPUCMD_AddIncrementalWrites(GPUREG_SCISSORTEST_MODE, param, 0x00000003);
|
||||||
|
|
||||||
//enable depth buffer
|
/* enable depth buffer */
|
||||||
param[0x0]=0x0000000F;
|
param[0x0]=0x0000000F;
|
||||||
param[0x1]=0x0000000F;
|
param[0x1]=0x0000000F;
|
||||||
param[0x2]=0x00000002;
|
param[0x2]=0x00000002;
|
||||||
|
@ -136,8 +138,8 @@ void GPU_SetBlendingColor(u8 r, u8 g, u8 b, u8 a)
|
||||||
|
|
||||||
void GPU_SetTextureEnable(GPU_TEXUNIT units)
|
void GPU_SetTextureEnable(GPU_TEXUNIT units)
|
||||||
{
|
{
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_SH_OUTATTR_CLOCK, 0x2, units<<8); // enables texcoord outputs
|
GPUCMD_AddMaskedWrite(GPUREG_SH_OUTATTR_CLOCK, 0x2, units<<8); /* enables texcoord outputs */
|
||||||
GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, 0x00011000|units); // enables texture units
|
GPUCMD_AddWrite(GPUREG_TEXUNIT_CONFIG, 0x00011000|units); /* enables texture units */
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 param, GPU_TEXCOLOR colorType)
|
void GPU_SetTexture(GPU_TEXUNIT unit, u32* data, u16 width, u16 height, u32 param, GPU_TEXCOLOR colorType)
|
||||||
|
@ -250,24 +252,24 @@ void GPU_SetTexEnv(u8 id, u16 rgbSources, u16 alphaSources, u16 rgbOperands, u16
|
||||||
param[0x1]=(alphaOperands<<12)|(rgbOperands);
|
param[0x1]=(alphaOperands<<12)|(rgbOperands);
|
||||||
param[0x2]=(alphaCombine<<16)|(rgbCombine);
|
param[0x2]=(alphaCombine<<16)|(rgbCombine);
|
||||||
param[0x3]=constantColor;
|
param[0x3]=constantColor;
|
||||||
param[0x4]=0x00000000; // ?
|
param[0x4]=0x00000000; /* ? */
|
||||||
|
|
||||||
GPUCMD_AddIncrementalWrites(GPUREG_0000|GPU_TEVID[id], param, 0x00000005);
|
GPUCMD_AddIncrementalWrites(GPUREG_0000|GPU_TEVID[id], param, 0x00000005);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count)
|
void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count)
|
||||||
{
|
{
|
||||||
//set primitive type
|
/* set primitive type */
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
|
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
|
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
|
||||||
//index buffer address register should be cleared (except bit 31) before drawing
|
/* index buffer address register should be cleared (except bit 31) before drawing */
|
||||||
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000);
|
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000);
|
||||||
//pass number of vertices
|
/* pass number of vertices */
|
||||||
GPUCMD_AddWrite(GPUREG_NUMVERTICES, count);
|
GPUCMD_AddWrite(GPUREG_NUMVERTICES, count);
|
||||||
//set first vertex
|
/* set first vertex */
|
||||||
GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, first);
|
GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, first);
|
||||||
|
|
||||||
//all the following except 0x000F022E might be useless
|
/* all the following except 0x000F022E might be useless */
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG2, 0x1, 0x00000001);
|
GPUCMD_AddMaskedWrite(GPUREG_GEOSTAGE_CONFIG2, 0x1, 0x00000001);
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000000);
|
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000000);
|
||||||
GPUCMD_AddWrite(GPUREG_DRAWARRAYS, 0x00000001);
|
GPUCMD_AddWrite(GPUREG_DRAWARRAYS, 0x00000001);
|
||||||
|
@ -278,12 +280,12 @@ void GPU_DrawArray(GPU_Primitive_t primitive, u32 first, u32 count)
|
||||||
|
|
||||||
void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n)
|
void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n)
|
||||||
{
|
{
|
||||||
//set primitive type
|
/* set primitive type */
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
|
GPUCMD_AddMaskedWrite(GPUREG_PRIMITIVE_CONFIG, 0x2, primitive);
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
|
GPUCMD_AddMaskedWrite(GPUREG_RESTART_PRIMITIVE, 0x2, 0x00000001);
|
||||||
//index buffer (TODO : support multiple types)
|
/* index buffer (TODO : support multiple types) */
|
||||||
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000|((u32)indexArray));
|
GPUCMD_AddWrite(GPUREG_INDEXBUFFER_CONFIG, 0x80000000|((u32)indexArray));
|
||||||
//pass number of vertices
|
/* pass number of vertices */
|
||||||
GPUCMD_AddWrite(GPUREG_NUMVERTICES, n);
|
GPUCMD_AddWrite(GPUREG_NUMVERTICES, n);
|
||||||
|
|
||||||
GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0x00000000);
|
GPUCMD_AddWrite(GPUREG_VERTEX_OFFSET, 0x00000000);
|
||||||
|
@ -296,7 +298,7 @@ void GPU_DrawElements(GPU_Primitive_t primitive, u32* indexArray, u32 n)
|
||||||
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000001);
|
GPUCMD_AddMaskedWrite(GPUREG_START_DRAW_FUNC0, 0x1, 0x00000001);
|
||||||
GPUCMD_AddWrite(GPUREG_VTX_FUNC, 0x00000001);
|
GPUCMD_AddWrite(GPUREG_VTX_FUNC, 0x00000001);
|
||||||
|
|
||||||
// CHECKME: does this one also require GPUREG_FRAMEBUFFER_FLUSH at the end?
|
/* CHECKME: does this one also require GPUREG_FRAMEBUFFER_FLUSH at the end? */
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_FinishDrawing()
|
void GPU_FinishDrawing()
|
||||||
|
@ -315,7 +317,7 @@ void GPU_Finalize(void)
|
||||||
GPUCMD_Split(NULL, NULL);
|
GPUCMD_Split(NULL, NULL);
|
||||||
#else
|
#else
|
||||||
GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678);
|
GPUCMD_AddWrite(GPUREG_FINALIZE, 0x12345678);
|
||||||
//not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now
|
/* not the cleanest way of guaranteeing 0x10-byte size but whatever good enough for now */
|
||||||
GPUCMD_AddWrite(GPUREG_FINALIZE,0x12345678);
|
GPUCMD_AddWrite(GPUREG_FINALIZE,0x12345678);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue