(3DS) add dynarec support when started from a .cia install
use libkhax for ninjhax 1.0
This commit is contained in:
parent
a99c3552a4
commit
c1d061e204
|
@ -0,0 +1,98 @@
|
|||
|
||||
#include "3ds.h"
|
||||
#include "libkhax/khax.h"
|
||||
|
||||
static int ninjhax_version = 0;
|
||||
|
||||
typedef s32 (*ctr_callback_type)(void);
|
||||
|
||||
static void ctr_enable_all_svc_kernel(void)
|
||||
{
|
||||
__asm__ volatile("cpsid aif");
|
||||
|
||||
u32* svc_access_control = *(*(u32***)0xFFFF9000 + 0x22) - 0x6;
|
||||
|
||||
svc_access_control[0]=0xFFFFFFFE;
|
||||
svc_access_control[1]=0xFFFFFFFF;
|
||||
svc_access_control[2]=0xFFFFFFFF;
|
||||
svc_access_control[3]=0x3FFFFFFF;
|
||||
}
|
||||
|
||||
|
||||
static void ctr_invalidate_ICache_kernel(void)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"cpsid aif\n\t"
|
||||
"mov r0, #0\n\t"
|
||||
"mcr p15, 0, r0, c7, c5, 0\n\t");
|
||||
}
|
||||
|
||||
static void ctr_flush_DCache_kernel(void)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"cpsid aif\n\t"
|
||||
"mov r0, #0\n\t"
|
||||
"mcr p15, 0, r0, c7, c10, 0\n\t");
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void ctr_enable_all_svc(void)
|
||||
{
|
||||
svcBackdoor((ctr_callback_type)ctr_enable_all_svc_kernel);
|
||||
}
|
||||
|
||||
void ctr_invalidate_ICache(void)
|
||||
{
|
||||
// __asm__ volatile("svc 0x2E\n\t");
|
||||
svcBackdoor((ctr_callback_type)ctr_invalidate_ICache_kernel);
|
||||
|
||||
}
|
||||
|
||||
void ctr_flush_DCache(void)
|
||||
{
|
||||
// __asm__ volatile("svc 0x4B\n\t");
|
||||
svcBackdoor((ctr_callback_type)ctr_flush_DCache_kernel);
|
||||
}
|
||||
|
||||
|
||||
void ctr_flush_invalidate_cache(void)
|
||||
{
|
||||
ctr_flush_DCache();
|
||||
ctr_invalidate_ICache();
|
||||
}
|
||||
|
||||
int ctr_svchack_init(void)
|
||||
{
|
||||
Handle tempHandle;
|
||||
Result res = srvGetServiceHandle(&tempHandle, "am:u");
|
||||
if(res == 0)
|
||||
{
|
||||
/* CFW */
|
||||
svcCloseHandle(tempHandle);
|
||||
ninjhax_version = 0;
|
||||
ctr_enable_all_svc();
|
||||
return 1;
|
||||
}
|
||||
else if(hbInit() == 0)
|
||||
{
|
||||
/* ninjhax 1.0 */
|
||||
ninjhax_version = 1;
|
||||
hbExit();
|
||||
khaxInit();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ninjhax 2.0 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctr_svchack_exit(void)
|
||||
{
|
||||
if (ninjhax_version == 1)
|
||||
khaxExit();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _3DS_UTILS_H
|
||||
#define _3DS_UTILS_H
|
||||
|
||||
void ctr_invalidate_ICache(void);
|
||||
void ctr_flush_DCache(void);
|
||||
|
||||
void ctr_flush_invalidate_cache(void);
|
||||
|
||||
int ctr_svchack_init(void);
|
||||
void ctr_svchack_exit(void);
|
||||
|
||||
#endif // _3DS_UTILS_H
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Myriachan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initialize and do the initial pwning of the ARM11 kernel.
|
||||
Result khaxInit();
|
||||
// Shut down libkhax
|
||||
Result khaxExit();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,339 @@
|
|||
#pragma once
|
||||
|
||||
#define KHAX_DEBUG
|
||||
//#define KHAX_DEBUG_DUMP_DATA
|
||||
|
||||
#ifdef KHAX_DEBUG
|
||||
#define KHAX_printf(...) printf(__VA_ARGS__), gspWaitForVBlank(), gfxFlushBuffers(), gfxSwapBuffers()
|
||||
#else
|
||||
#define KHAX_printf static_cast<void>
|
||||
#endif
|
||||
|
||||
// Shut up IntelliSense warnings when using MSVC as an IDE, even though MSVC will obviously never
|
||||
// actually compile this program.
|
||||
#ifdef _MSC_VER
|
||||
#undef ALIGN
|
||||
#define ALIGN(x) __declspec(align(x))
|
||||
#if _MSC_VER < 1900
|
||||
#define alignof __alignof
|
||||
#endif
|
||||
#define KHAX_ATTRIBUTE(...)
|
||||
#else
|
||||
#define KHAX_ATTRIBUTE(...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
#define KHAX_lengthof(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
namespace KHAX
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// This code uses offsetof illegally (i.e. on polymorphic classes).
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// General linked list node kernel object.
|
||||
struct KLinkedListNode
|
||||
{
|
||||
KLinkedListNode *next;
|
||||
KLinkedListNode *prev;
|
||||
void *data;
|
||||
};
|
||||
static_assert(sizeof(KLinkedListNode) == 0x00C, "KLinkedListNode isn't the expected size.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Base class of reference-counted kernel objects.
|
||||
class KAutoObject
|
||||
{
|
||||
public:
|
||||
u32 m_refCount; // +004
|
||||
|
||||
protected:
|
||||
virtual ~KAutoObject() {}
|
||||
};
|
||||
static_assert(sizeof(KAutoObject) == 0x008, "KAutoObject isn't the expected size.");
|
||||
static_assert(offsetof(KAutoObject, m_refCount) == 0x004, "KAutoObject isn't the expected layout.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Base class of synchronizable objects.
|
||||
class KSynchronizationObject : public KAutoObject
|
||||
{
|
||||
public:
|
||||
u32 m_threadSyncCount; // +008
|
||||
KLinkedListNode *m_threadSyncFirst; // +00C
|
||||
KLinkedListNode *m_threadSyncLast; // +010
|
||||
};
|
||||
static_assert(sizeof(KSynchronizationObject) == 0x014, "KSynchronizationObject isn't the expected size.");
|
||||
static_assert(offsetof(KSynchronizationObject, m_threadSyncCount) == 0x008,
|
||||
"KSynchronizationObject isn't the expected layout.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
struct KDebugThread;
|
||||
struct KThreadLocalPage;
|
||||
class KCodeSet;
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Unofficial name
|
||||
typedef u8 KSVCACL[0x80 / 8];
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// ARM VFP register
|
||||
union KHAX_ATTRIBUTE(__attribute__((__aligned__(4))) __attribute__((__packed__))) VFPRegister
|
||||
{
|
||||
float m_single[2];
|
||||
double m_double;
|
||||
};
|
||||
static_assert(alignof(VFPRegister) == 0x004,
|
||||
"VFPRegister isn't the expected alignment.");
|
||||
static_assert(sizeof(VFPRegister) == 0x008,
|
||||
"VFPRegister isn't the expected size.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// SVC-mode register save area.
|
||||
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
|
||||
struct SVCRegisterState
|
||||
{
|
||||
u32 m_r4; // +000
|
||||
u32 m_r5; // +004
|
||||
u32 m_r6; // +008
|
||||
u32 m_r7; // +00C
|
||||
u32 m_r8; // +010
|
||||
u32 m_r9; // +014
|
||||
u32 m_sl; // +018
|
||||
u32 m_fp; // +01C
|
||||
u32 m_sp; // +020
|
||||
u32 m_lr; // +024
|
||||
};
|
||||
static_assert(sizeof(SVCRegisterState) == 0x028,
|
||||
"SVCRegisterState isn't the expected size.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// SVC-mode thread state structure. This is the last part of the per-
|
||||
// thread page allocated in 0xFF4XX000.
|
||||
// http://3dbrew.org/wiki/Memory_layout#0xFF4XX000
|
||||
struct SVCThreadArea
|
||||
{
|
||||
KSVCACL m_svcAccessControl; // +000
|
||||
u32 m_unknown010; // +010
|
||||
u32 m_unknown014; // +014
|
||||
SVCRegisterState m_svcRegisterState; // +018
|
||||
VFPRegister m_vfpRegisters[16]; // +040
|
||||
u32 m_unknown0C4; // +0C0
|
||||
u32 m_fpexc; // +0C4
|
||||
};
|
||||
static_assert(offsetof(SVCThreadArea, m_svcRegisterState) == 0x018,
|
||||
"ThreadSVCArea isn't the expected layout.");
|
||||
static_assert(sizeof(SVCThreadArea) == 0x0C8,
|
||||
"ThreadSVCArea isn't the expected size.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Kernel's internal structure of a thread object.
|
||||
class KThread : public KSynchronizationObject
|
||||
{
|
||||
public:
|
||||
u32 m_unknown014; // +014
|
||||
u32 m_unknown018; // +018
|
||||
u32 m_unknown01C; // +01C
|
||||
u32 m_unknown020; // +020
|
||||
u32 m_unknown024; // +024
|
||||
u32 m_unknown028; // +028
|
||||
u32 m_unknown02C; // +02C
|
||||
u32 m_unknown030; // +030
|
||||
u32 m_unknown034; // +034
|
||||
KDebugThread *m_debugThread; // +038
|
||||
s32 m_threadPriority; // +03C
|
||||
void *m_waitingOnObject; // +040
|
||||
u32 m_unknown044; // +044
|
||||
KThread **m_schedulerUnknown048; // +048
|
||||
void *m_arbitrationAddress; // +04C
|
||||
u32 m_unknown050; // +050
|
||||
u32 m_unknown054; // +054
|
||||
u32 m_unknown058; // +058
|
||||
KLinkedListNode *m_waitingOnList; // +05C
|
||||
u32 m_unknownListCount; // +060
|
||||
KLinkedListNode *m_unknownListHead; // +064
|
||||
KLinkedListNode *m_unknownListTail; // +068
|
||||
s32 m_threadPriority2; // +06C
|
||||
s32 m_creatingProcessor; // +070
|
||||
u32 m_unknown074; // +074
|
||||
u32 m_unknown078; // +078
|
||||
u16 m_unknown07C; // +07C
|
||||
u8 m_threadType; // +07E
|
||||
u8 m_padding07F; // +07F
|
||||
void *m_process; // +080
|
||||
u32 m_threadID; // +084
|
||||
SVCRegisterState *m_svcRegisterState; // +088
|
||||
void *m_svcPageEnd; // +08C
|
||||
s32 m_idealProcessor; // +090
|
||||
void *m_tlsUserMode; // +094
|
||||
void *m_tlsKernelMode; // +098
|
||||
u32 m_unknown09C; // +09C
|
||||
KThread *m_prev; // +0A0
|
||||
KThread *m_next; // +0A4
|
||||
KThread **m_temporaryLinkedList; // +0A8
|
||||
u32 m_unknown0AC; // +0B0
|
||||
};
|
||||
static_assert(sizeof(KThread) == 0x0B0,
|
||||
"KThread isn't the expected size.");
|
||||
static_assert(offsetof(KThread, m_svcRegisterState) == 0x088,
|
||||
"KThread isn't the expected layout.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Kernel's internal structure of a process object.
|
||||
// Version 1.0.0(?) - 7.2.0
|
||||
class KProcess_1_0_0_Old : public KSynchronizationObject
|
||||
{
|
||||
public:
|
||||
u32 m_unknown014; // +014
|
||||
u32 m_unknown018; // +018
|
||||
KThread *volatile m_interactingThread; // +01C
|
||||
u16 m_unknown020; // +020
|
||||
u16 m_unknown022; // +022
|
||||
u32 m_unknown024; // +024
|
||||
u32 m_unknown028; // +028
|
||||
u32 m_memoryBlockCount; // +02C
|
||||
KLinkedListNode *m_memoryBlockFirst; // +030
|
||||
KLinkedListNode *m_memoryBlockLast; // +034
|
||||
u32 m_unknown038; // +038
|
||||
u32 m_unknown03C; // +03C
|
||||
void *m_translationTableBase; // +040
|
||||
u8 m_contextID; // +044
|
||||
u32 m_unknown048; // +048
|
||||
u32 m_unknown04C; // +04C
|
||||
u32 m_mmuTableSize; // +050
|
||||
void *m_mmuTableAddress; // +054
|
||||
u32 m_threadContextPagesSize; // +058
|
||||
u32 m_threadLocalPageCount; // +05C
|
||||
KLinkedListNode *m_threadLocalPageFirst; // +060
|
||||
KLinkedListNode *m_threadLocalPageLast; // +064
|
||||
u32 m_unknown068; // +068
|
||||
s32 m_idealProcessor; // +06C
|
||||
u32 m_unknown070; // +070
|
||||
void *m_resourceLimits; // +074
|
||||
u8 m_unknown078; // +078
|
||||
u8 m_affinityMask; // +079
|
||||
u32 m_threadCount; // +07C
|
||||
KSVCACL m_svcAccessControl; // +080
|
||||
u32 m_interruptFlags[0x80 / 32]; // +090
|
||||
u32 m_kernelFlags; // +0A0
|
||||
u16 m_handleTableSize; // +0A4
|
||||
u16 m_kernelReleaseVersion; // +0A6
|
||||
KCodeSet *m_codeSet; // +0A8
|
||||
u32 m_processID; // +0AC
|
||||
u32 m_kernelFlags2; // +0B0
|
||||
u32 m_unknown0B4; // +0B4
|
||||
KThread *m_mainThread; // +0B8
|
||||
//...more...
|
||||
};
|
||||
static_assert(offsetof(KProcess_1_0_0_Old, m_svcAccessControl) == 0x080,
|
||||
"KProcess_1_0_0_Old isn't the expected layout.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Kernel's internal structure of a process object.
|
||||
// Old 3DS Version 8.0.0 - 9.5.0...
|
||||
class KProcess_8_0_0_Old : public KSynchronizationObject
|
||||
{
|
||||
public:
|
||||
u32 m_unknown014; // +014
|
||||
u32 m_unknown018; // +018
|
||||
KThread *volatile m_interactingThread; // +01C
|
||||
u16 m_unknown020; // +020
|
||||
u16 m_unknown022; // +022
|
||||
u32 m_unknown024; // +024
|
||||
u32 m_unknown028; // +028
|
||||
u32 m_memoryBlockCount; // +02C
|
||||
KLinkedListNode *m_memoryBlockFirst; // +030
|
||||
KLinkedListNode *m_memoryBlockLast; // +034
|
||||
u32 m_unknown038; // +038
|
||||
u32 m_unknown03C; // +03C
|
||||
void *m_translationTableBase; // +040
|
||||
u8 m_contextID; // +044
|
||||
u32 m_unknown048; // +048
|
||||
void *m_userVirtualMemoryEnd; // +04C
|
||||
void *m_userLinearVirtualBase; // +050
|
||||
u32 m_unknown054; // +054
|
||||
u32 m_mmuTableSize; // +058
|
||||
void *m_mmuTableAddress; // +05C
|
||||
u32 m_threadContextPagesSize; // +060
|
||||
u32 m_threadLocalPageCount; // +064
|
||||
KLinkedListNode *m_threadLocalPageFirst; // +068
|
||||
KLinkedListNode *m_threadLocalPageLast; // +06C
|
||||
u32 m_unknown070; // +070
|
||||
s32 m_idealProcessor; // +074
|
||||
u32 m_unknown078; // +078
|
||||
void *m_resourceLimits; // +07C
|
||||
u32 m_unknown080; // +080
|
||||
u32 m_threadCount; // +084
|
||||
u8 m_svcAccessControl[0x80 / 8]; // +088
|
||||
u32 m_interruptFlags[0x80 / 32]; // +098
|
||||
u32 m_kernelFlags; // +0A8
|
||||
u16 m_handleTableSize; // +0AC
|
||||
u16 m_kernelReleaseVersion; // +0AE
|
||||
KCodeSet *m_codeSet; // +0B0
|
||||
u32 m_processID; // +0B4
|
||||
u32 m_unknown0B8; // +0B8
|
||||
u32 m_unknown0BC; // +0BC
|
||||
KThread *m_mainThread; // +0C0
|
||||
//...more...
|
||||
};
|
||||
static_assert(offsetof(KProcess_8_0_0_Old, m_svcAccessControl) == 0x088,
|
||||
"KProcess_8_0_0_Old isn't the expected layout.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Kernel's internal structure of a process object.
|
||||
// New 3DS Version 8.0.0 - 9.5.0...
|
||||
class KProcess_8_0_0_New : public KSynchronizationObject
|
||||
{
|
||||
public:
|
||||
u32 m_unknown014; // +014
|
||||
u32 m_unknown018; // +018
|
||||
KThread *volatile m_interactingThread; // +01C
|
||||
u16 m_unknown020; // +020
|
||||
u16 m_unknown022; // +022
|
||||
u32 m_unknown024; // +024
|
||||
u32 m_unknown028; // +028
|
||||
u32 m_unknown02C; // +02C new to New 3DS
|
||||
u32 m_unknown030; // +030 new to New 3DS
|
||||
u32 m_memoryBlockCount; // +034
|
||||
KLinkedListNode *m_memoryBlockFirst; // +038
|
||||
KLinkedListNode *m_memoryBlockLast; // +03C
|
||||
u32 m_unknown040; // +040
|
||||
u32 m_unknown044; // +044
|
||||
void *m_translationTableBase; // +048
|
||||
u8 m_contextID; // +04C
|
||||
u32 m_unknown050; // +050
|
||||
void *m_userVirtualMemoryEnd; // +054
|
||||
void *m_userLinearVirtualBase; // +058
|
||||
u32 m_unknown05C; // +05C
|
||||
u32 m_mmuTableSize; // +060
|
||||
void *m_mmuTableAddress; // +064
|
||||
u32 m_threadContextPagesSize; // +068
|
||||
u32 m_threadLocalPageCount; // +06C
|
||||
KLinkedListNode *m_threadLocalPageFirst; // +070
|
||||
KLinkedListNode *m_threadLocalPageLast; // +074
|
||||
u32 m_unknown078; // +078
|
||||
s32 m_idealProcessor; // +07C
|
||||
u32 m_unknown080; // +080
|
||||
void *m_resourceLimits; // +084
|
||||
u32 m_unknown088; // +088
|
||||
u32 m_threadCount; // +08C
|
||||
u8 m_svcAccessControl[0x80 / 8]; // +090
|
||||
u32 m_interruptFlags[0x80 / 32]; // +0A0
|
||||
u32 m_kernelFlags; // +0B0
|
||||
u16 m_handleTableSize; // +0B4
|
||||
u16 m_kernelReleaseVersion; // +0B6
|
||||
KCodeSet *m_codeSet; // +0B8
|
||||
u32 m_processID; // +0BC
|
||||
u32 m_unknown0C0; // +0C0
|
||||
u32 m_unknown0C4; // +0C4
|
||||
KThread *m_mainThread; // +0C8
|
||||
//...more...
|
||||
};
|
||||
static_assert(offsetof(KProcess_8_0_0_New, m_svcAccessControl) == 0x090,
|
||||
"KProcess_8_0_0_New isn't the expected layout.");
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// Done using illegal offsetof
|
||||
#pragma GCC diagnostic pop
|
||||
}
|
20
Makefile
20
Makefile
|
@ -209,7 +209,7 @@ else ifeq ($(platform), ctr)
|
|||
CFLAGS += -Wall -mword-relocations
|
||||
CFLAGS += -fomit-frame-pointer -ffast-math
|
||||
CPU_ARCH := arm
|
||||
# dynarec currently requires ninjahax to work
|
||||
# dynarec unavailable on ninjhax 2.0
|
||||
HAVE_DYNAREC = 1
|
||||
STATIC_LINKING = 1
|
||||
|
||||
|
@ -322,6 +322,7 @@ ifeq ($(CPU_ARCH), arm)
|
|||
DEFINES += -DARM_ARCH
|
||||
endif
|
||||
|
||||
|
||||
WARNINGS_DEFINES =
|
||||
CODE_DEFINES =
|
||||
|
||||
|
@ -334,6 +335,23 @@ ifeq ($(FRONTEND_SUPPORTS_RGB565), 1)
|
|||
endif
|
||||
|
||||
|
||||
ifeq ($(platform), ctr)
|
||||
ifeq ($(HAVE_DYNAREC), 1)
|
||||
OBJECTS += 3ds/3ds_utils.o 3ds/libkhax/khaxinit.o
|
||||
|
||||
ifeq ($(strip $(CTRULIB)),)
|
||||
$(error "Please set CTRULIB in your environment. export CTRULIB=<path to>ctrulib")
|
||||
endif
|
||||
|
||||
CFLAGS += -I$(CTRULIB)/include
|
||||
|
||||
3ds/libkhax/khaxinit.o: 3ds/libkhax/khaxinit.cpp
|
||||
$(CXX) $(INCFLAGS) $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 $(OPTIMIZE) -c -o $@ $<
|
||||
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(platform), theos_ios)
|
||||
COMMON_FLAGS := -DIOS $(COMMON_DEFINES) $(INCFLAGS) -I$(THEOS_INCLUDE_PATH) -Wno-error
|
||||
$(LIBRARY_NAME)_CFLAGS += $(COMMON_FLAGS) $(CFLAGS)
|
||||
|
|
|
@ -234,8 +234,8 @@ extern u8 bit_count[256];
|
|||
#if defined(PSP_BUILD)
|
||||
#define translate_invalidate_dcache() sceKernelDcacheWritebackAll()
|
||||
#elif defined(_3DS)
|
||||
int32_t HB_FlushInvalidateCache();
|
||||
#define translate_invalidate_dcache() HB_FlushInvalidateCache()
|
||||
#include "3ds/3ds_utils.h"
|
||||
#define translate_invalidate_dcache() ctr_flush_invalidate_cache()
|
||||
#define invalidate_icache_region(addr, size) (void)0
|
||||
#elif defined(ARM_ARCH)
|
||||
static int sys_cacheflush(void *addr, unsigned long size)
|
||||
|
|
35
libretro.c
35
libretro.c
|
@ -12,11 +12,11 @@
|
|||
void* linearMemAlign(size_t size, size_t alignment);
|
||||
void linearFree(void* mem);
|
||||
#if defined(HAVE_DYNAREC)
|
||||
int32_t hbInit(void);
|
||||
void hbExit(void);
|
||||
int32_t HB_FlushInvalidateCache(void);
|
||||
int32_t HB_ReprotectMemory(void* addr, uint32_t pages, uint32_t mode, uint32_t* reprotectedPages);
|
||||
int hb_service_available;
|
||||
#include "3ds/3ds_utils.h"
|
||||
#define MEMOP_PROT 6
|
||||
int32_t svcDuplicateHandle(uint32_t* out, uint32_t original);
|
||||
int32_t svcControlProcessMemory(uint32_t process, void* addr0, void* addr1, uint32_t size, uint32_t type, uint32_t perm);
|
||||
int ctr_has_full_svc_access;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -117,16 +117,19 @@ void retro_init(void)
|
|||
init_gamepak_buffer();
|
||||
init_sound(1);
|
||||
#if defined(_3DS) && defined(HAVE_DYNAREC)
|
||||
hb_service_available = !hbInit();
|
||||
if (hb_service_available)
|
||||
ctr_has_full_svc_access = ctr_svchack_init();
|
||||
if (ctr_has_full_svc_access)
|
||||
{
|
||||
HB_ReprotectMemory(rom_translation_cache,
|
||||
ROM_TRANSLATION_CACHE_SIZE / 0x1000, 0b111, NULL);
|
||||
HB_ReprotectMemory(ram_translation_cache,
|
||||
RAM_TRANSLATION_CACHE_SIZE / 0x1000, 0b111, NULL);
|
||||
HB_ReprotectMemory(bios_translation_cache,
|
||||
BIOS_TRANSLATION_CACHE_SIZE / 0x1000, 0b111, NULL);
|
||||
HB_FlushInvalidateCache();
|
||||
uint32_t currentHandle;
|
||||
svcDuplicateHandle(¤tHandle, 0xFFFF8001);
|
||||
svcControlProcessMemory(currentHandle, rom_translation_cache, 0x0,
|
||||
ROM_TRANSLATION_CACHE_SIZE, MEMOP_PROT, 0b111);
|
||||
svcControlProcessMemory(currentHandle, ram_translation_cache, 0x0,
|
||||
RAM_TRANSLATION_CACHE_SIZE, MEMOP_PROT, 0b111);
|
||||
svcControlProcessMemory(currentHandle, bios_translation_cache, 0x0,
|
||||
BIOS_TRANSLATION_CACHE_SIZE, MEMOP_PROT, 0b111);
|
||||
|
||||
ctr_flush_invalidate_cache();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -149,7 +152,7 @@ void retro_deinit(void)
|
|||
munmap(bios_translation_cache, BIOS_TRANSLATION_CACHE_SIZE);
|
||||
#endif
|
||||
#if defined(_3DS) && defined(HAVE_DYNAREC)
|
||||
hbExit();
|
||||
ctr_svchack_exit();
|
||||
#endif
|
||||
#ifdef _3DS
|
||||
linearFree(gba_screen_pixels);
|
||||
|
@ -315,7 +318,7 @@ bool retro_load_game(const struct retro_game_info* info)
|
|||
ram_translation_ptr = ram_translation_cache;
|
||||
bios_translation_ptr = bios_translation_cache;
|
||||
#elif defined(_3DS)
|
||||
if(!hb_service_available)
|
||||
if(!ctr_has_full_svc_access)
|
||||
dynarec_enable = 0;
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue