iOS support. Work in progress
This commit is contained in:
parent
b027a6b9a1
commit
77e7c25e9c
|
@ -25,7 +25,7 @@
|
|||
#else /* #ifdef _WIN32 */
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT
|
||||
#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) || defined(__APPLE__)
|
||||
#include <sys/time.h>
|
||||
#endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */
|
||||
#include <sys/param.h>
|
||||
|
|
|
@ -33,7 +33,11 @@ constexpr size_t CodeSize = 4096 * 8; //32 kb, 8 pages
|
|||
#if defined(__unix__) || defined(__SWITCH__)
|
||||
alignas(4096) static u8 DynCode[CodeSize] __attribute__((section(".text")));
|
||||
#elif defined(__APPLE__)
|
||||
#if defined(TARGET_IPHONE) || defined(TARGET_ARM_MAC)
|
||||
static u8 *DynCode;
|
||||
#else
|
||||
alignas(4096) static u8 DynCode[CodeSize] __attribute__((section("__TEXT, .text")));
|
||||
#endif
|
||||
#else
|
||||
#error "Unsupported platform for arm64 DSP dynarec"
|
||||
#endif
|
||||
|
@ -41,6 +45,18 @@ alignas(4096) static u8 DynCode[CodeSize] __attribute__((section("__TEXT, .text"
|
|||
static u8 *pCodeBuffer;
|
||||
static ptrdiff_t rx_offset;
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
#include "stdclass.h"
|
||||
|
||||
static void JITWriteProtect(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
mem_region_set_exec(pCodeBuffer, CodeSize);
|
||||
else
|
||||
mem_region_unlock(pCodeBuffer, CodeSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
class DSPAssembler : public MacroAssembler
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -49,7 +49,7 @@ u8* icPtr;
|
|||
u8* ICache;
|
||||
void (*EntryPoints[ARAM_SIZE_MAX / 4])();
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(TARGET_IPHONE) || defined(TARGET_ARM_MAC)
|
||||
static u8 *ARM7_TCB;
|
||||
#elif defined(__unix__) || defined(__SWITCH__)
|
||||
alignas(4096) static u8 ARM7_TCB[ICacheSize] __attribute__((section(".text")));
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
using namespace vixl::aarch64;
|
||||
//#include <aarch32/disasm-aarch32.h>
|
||||
#include "rec-ARM64/arm64_unwind.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
namespace aicaarm {
|
||||
|
||||
|
@ -39,6 +40,16 @@ class Arm7Compiler;
|
|||
|
||||
static Arm64UnwindInfo unwinder;
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
static void JITWriteProtect(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
mem_region_set_exec(recompiler::ICache, recompiler::ICacheSize);
|
||||
else
|
||||
mem_region_unlock(recompiler::ICache, recompiler::ICacheSize);
|
||||
}
|
||||
#endif
|
||||
|
||||
class AArch64ArmRegAlloc : public ArmRegAlloc<MAX_REGS, AArch64ArmRegAlloc>
|
||||
{
|
||||
Arm7Compiler& assembler;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#if FEAT_SHREC != DYNAREC_NONE
|
||||
|
||||
#if defined(_WIN32) || FEAT_SHREC != DYNAREC_JIT
|
||||
#if defined(_WIN32) || FEAT_SHREC != DYNAREC_JIT || defined(TARGET_IPHONE) || defined(TARGET_ARM_MAC)
|
||||
static u8 *SH4_TCB;
|
||||
#else
|
||||
static u8 SH4_TCB[CODE_SIZE + TEMP_CODE_SIZE + 4096]
|
||||
|
|
|
@ -122,11 +122,7 @@ double os_GetSeconds()
|
|||
return a.tv_sec-tvs_base+a.tv_usec/1000000.0;
|
||||
}
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
void os_DebugBreak() {
|
||||
__asm__("trap");
|
||||
}
|
||||
#elif !defined(__unix__)
|
||||
#if !defined(__unix__)
|
||||
void os_DebugBreak()
|
||||
{
|
||||
__builtin_trap();
|
||||
|
|
|
@ -70,10 +70,14 @@ bool mem_region_unlock(void *start, size_t len)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mem_region_set_exec(void *start, size_t len)
|
||||
bool mem_region_set_exec(void *start, size_t len)
|
||||
{
|
||||
size_t inpage = (uintptr_t)start & PAGE_MASK;
|
||||
if (mprotect((u8*)start - inpage, len + inpage, PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||
int protFlags = PROT_READ | PROT_EXEC;
|
||||
#ifndef TARGET_IPHONE
|
||||
protFlags |= PROT_WRITE;
|
||||
#endif
|
||||
if (mprotect((u8*)start - inpage, len + inpage, protFlags))
|
||||
{
|
||||
WARN_LOG(VMEM, "mem_region_set_exec: mprotect failed. errno %d", errno);
|
||||
return false;
|
||||
|
@ -239,32 +243,40 @@ void vmem_platform_create_mappings(const vmem_mapping *vmem_maps, unsigned numma
|
|||
}
|
||||
|
||||
// Prepares the code region for JIT operations, thus marking it as RWX
|
||||
bool vmem_platform_prepare_jit_block(void *code_area, unsigned size, void **code_area_rwx) {
|
||||
// Try to map is as RWX, this fails apparently on OSX (and perhaps other systems?)
|
||||
if (!mem_region_set_exec(code_area, size))
|
||||
{
|
||||
bool vmem_platform_prepare_jit_block(void *code_area, unsigned size, void **code_area_rwx)
|
||||
{
|
||||
// Try to map is as RWX, this fails apparently on OSX (and perhaps other systems?)
|
||||
if (code_area != nullptr && mem_region_set_exec(code_area, size))
|
||||
{
|
||||
// Pointer location should be same:
|
||||
*code_area_rwx = code_area;
|
||||
return true;
|
||||
}
|
||||
#ifndef TARGET_ARM_MAC
|
||||
void *ret_ptr = MAP_FAILED;
|
||||
if (code_area != nullptr)
|
||||
{
|
||||
// Well it failed, use another approach, unmap the memory area and remap it back.
|
||||
// Seems it works well on Darwin according to reicast code :P
|
||||
#ifndef __ARM_MAC__
|
||||
munmap(code_area, size);
|
||||
void *ret_ptr = mmap(code_area, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||
// Ensure it's the area we requested
|
||||
if (ret_ptr != code_area)
|
||||
return false; // Couldn't remap it? Perhaps RWX is disabled? This should never happen in any supported Unix platform.
|
||||
#else
|
||||
// MAP_JIT and toggleable write protection is required on Apple Silicon
|
||||
// Cannot use MAP_FIXED with MAP_JIT
|
||||
void *ret_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON | MAP_JIT, -1, 0);
|
||||
if ( ret_ptr == MAP_FAILED )
|
||||
return false;
|
||||
*code_area_rwx = ret_ptr;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Pointer location should be same:
|
||||
*code_area_rwx = code_area;
|
||||
return true;
|
||||
munmap(code_area, size);
|
||||
ret_ptr = mmap(code_area, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||
}
|
||||
if (ret_ptr == MAP_FAILED)
|
||||
{
|
||||
// mmap at the requested code_area location failed, so let the OS pick one for us
|
||||
ret_ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (ret_ptr == MAP_FAILED)
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// MAP_JIT and toggleable write protection is required on Apple Silicon
|
||||
// Cannot use MAP_FIXED with MAP_JIT
|
||||
void *ret_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON | MAP_JIT, -1, 0);
|
||||
if ( ret_ptr == MAP_FAILED )
|
||||
return false;
|
||||
#endif
|
||||
*code_area_rwx = ret_ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use two addr spaces: need to remap something twice, therefore use allocate_shared_filemem()
|
||||
|
|
|
@ -86,7 +86,7 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
#if HOST_CPU != CPU_X64 && HOST_CPU != CPU_ARM64 && (HOST_CPU != CPU_X86 || defined(_WIN32))
|
||||
#if HOST_CPU != CPU_X64 && HOST_CPU != CPU_ARM64 && (HOST_CPU != CPU_X86 || defined(_WIN32)) || defined(TARGET_IPHONE)
|
||||
inline void UnwindInfo::start(void *address) {
|
||||
}
|
||||
inline void UnwindInfo::pushReg(u32 offset, int reg) {
|
||||
|
|
|
@ -91,6 +91,16 @@ void ngen_mainloop(void* v_cntx)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_IPHONE
|
||||
static void JITWriteProtect(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
mem_region_set_exec(CodeCache, CODE_SIZE + TEMP_CODE_SIZE);
|
||||
else
|
||||
mem_region_unlock(CodeCache, CODE_SIZE + TEMP_CODE_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ngen_init()
|
||||
{
|
||||
INFO_LOG(DYNAREC, "Initializing the ARM64 dynarec");
|
||||
|
|
|
@ -718,7 +718,7 @@ bool render_output_framebuffer()
|
|||
glViewport(-fx, 0, screen_width + fx * 2, screen_height);
|
||||
if (gl.ofbo.tex == 0)
|
||||
return false;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.origFbo);
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
drawQuad(gl.ofbo.tex, config::Rotate90);
|
||||
|
@ -729,13 +729,13 @@ bool render_output_framebuffer()
|
|||
if (gl.ofbo.fbo == 0)
|
||||
return false;
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, gl.ofbo.fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gl.ofbo.origFbo);
|
||||
glcache.ClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glBlitFramebuffer(fx, 0, gl.ofbo.width - fx, gl.ofbo.height,
|
||||
sx, 0, screen_width - sx, screen_height,
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.origFbo);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -68,13 +68,9 @@ const char *PixelCompatShader = R"(
|
|||
)";
|
||||
|
||||
static const char* GouraudSource = R"(
|
||||
#if TARGET_GL == GL3 || TARGET_GL == GLES3
|
||||
#if pp_Gouraud == 0
|
||||
#if (TARGET_GL == GL3 || TARGET_GL == GLES3) && pp_Gouraud == 0
|
||||
#define INTERPOLATION flat
|
||||
#else
|
||||
#define INTERPOLATION smooth
|
||||
#endif
|
||||
#else
|
||||
#define INTERPOLATION
|
||||
#endif
|
||||
)";
|
||||
|
@ -1052,7 +1048,7 @@ void OSD_DRAW(bool clear_screen)
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
glcache.BindTexture(GL_TEXTURE_2D, gl.OSD_SHADER.osd_tex);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.origFbo);
|
||||
|
||||
const std::vector<OSDVertex>& osdVertices = GetOSDVertices();
|
||||
glBufferData(GL_ARRAY_BUFFER, osdVertices.size() * sizeof(OSDVertex), osdVertices.data(), GL_STREAM_DRAW); glCheck();
|
||||
|
@ -1119,8 +1115,6 @@ static void upload_vertex_indices()
|
|||
|
||||
bool RenderFrame(int width, int height)
|
||||
{
|
||||
create_modvol_shader();
|
||||
|
||||
bool is_rtt = pvrrc.isRTT;
|
||||
|
||||
float vtx_min_fZ = 0.f; //pvrrc.fZ_min;
|
||||
|
|
|
@ -120,6 +120,7 @@ struct gl_ctx
|
|||
GLuint fbo;
|
||||
int width;
|
||||
int height;
|
||||
GLuint origFbo;
|
||||
} ofbo;
|
||||
|
||||
const char *gl_version;
|
||||
|
|
|
@ -225,12 +225,20 @@ GLuint BindRTT(bool withDepthBuffer)
|
|||
// glRenderbufferStorage will fix this and will allocate a depth buffer
|
||||
if (gl.is_gles)
|
||||
{
|
||||
#if defined(GL_DEPTH24_STENCIL8_OES) && defined(GL_DEPTH_COMPONENT24_OES)
|
||||
if (gl.GL_OES_packed_depth_stencil_supported)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbw2, fbh2);
|
||||
else if (gl.GL_OES_depth24_supported)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbw2, fbh2);
|
||||
else
|
||||
#if defined(GL_DEPTH24_STENCIL8)
|
||||
if (gl.gl_major >= 3)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbw2, fbh2);
|
||||
else
|
||||
#endif
|
||||
#if defined(GL_DEPTH24_STENCIL8_OES)
|
||||
if (gl.GL_OES_packed_depth_stencil_supported)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbw2, fbh2);
|
||||
else
|
||||
#endif
|
||||
#if defined(GL_DEPTH_COMPONENT24_OES)
|
||||
if (gl.GL_OES_depth24_supported)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbw2, fbh2);
|
||||
else
|
||||
#endif
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, fbw2, fbh2);
|
||||
}
|
||||
|
@ -242,7 +250,7 @@ GLuint BindRTT(bool withDepthBuffer)
|
|||
// Attach the depth buffer we just created to our FBO.
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gl.rtt.depthb);
|
||||
|
||||
if (!gl.is_gles || gl.GL_OES_packed_depth_stencil_supported)
|
||||
if (!gl.is_gles || gl.gl_major >= 3 || gl.GL_OES_packed_depth_stencil_supported)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gl.rtt.depthb);
|
||||
}
|
||||
|
||||
|
@ -476,6 +484,9 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
gl.ofbo.width = width;
|
||||
gl.ofbo.height = height;
|
||||
}
|
||||
gl.ofbo.origFbo = 0;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *)&gl.ofbo.origFbo);
|
||||
|
||||
if (gl.ofbo.fbo == 0)
|
||||
{
|
||||
// Create the depth+stencil renderbuffer
|
||||
|
@ -484,10 +495,18 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
|
||||
if (gl.is_gles)
|
||||
{
|
||||
#if defined(GL_DEPTH24_STENCIL8_OES) && defined(GL_DEPTH_COMPONENT24_OES)
|
||||
#if defined(GL_DEPTH24_STENCIL8)
|
||||
if (gl.gl_major >= 3)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
else
|
||||
#endif
|
||||
#if defined(GL_DEPTH24_STENCIL8_OES)
|
||||
if (gl.GL_OES_packed_depth_stencil_supported)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
|
||||
else if (gl.GL_OES_depth24_supported)
|
||||
else
|
||||
#endif
|
||||
#if defined(GL_DEPTH_COMPONENT24_OES)
|
||||
if (gl.GL_OES_depth24_supported)
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, width, height);
|
||||
else
|
||||
#endif
|
||||
|
@ -527,7 +546,7 @@ GLuint init_output_framebuffer(int width, int height)
|
|||
// Attach the depth buffer to our FBO.
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, gl.ofbo.depthb);
|
||||
|
||||
if (!gl.is_gles || gl.GL_OES_packed_depth_stencil_supported)
|
||||
if (!gl.is_gles || gl.gl_major >= 3 || gl.GL_OES_packed_depth_stencil_supported)
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gl.ofbo.depthb);
|
||||
|
||||
// Attach the texture/renderbuffer to the FBO
|
||||
|
|
|
@ -488,7 +488,9 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
|||
|
||||
void ImGui_ImplOpenGL3_DrawBackground()
|
||||
{
|
||||
#ifndef TARGET_IPHONE
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
glcache.ClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
|
@ -54,9 +54,6 @@ static bool inited = false;
|
|||
float scaling = 1;
|
||||
GuiState gui_state = GuiState::Main;
|
||||
static bool commandLineStart;
|
||||
#ifdef __ANDROID__
|
||||
static bool touch_up;
|
||||
#endif
|
||||
static u32 mouseButtons;
|
||||
static int mouseX, mouseY;
|
||||
static float mouseWheel;
|
||||
|
@ -141,7 +138,7 @@ void gui_init()
|
|||
ImGui::GetStyle().ItemSpacing = ImVec2(8, 8); // from 8,4
|
||||
ImGui::GetStyle().ItemInnerSpacing = ImVec2(4, 6); // from 4,4
|
||||
//ImGui::GetStyle().WindowRounding = 0;
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(TARGET_IPHONE)
|
||||
ImGui::GetStyle().TouchExtraPadding = ImVec2(1, 1); // from 0,0
|
||||
#endif
|
||||
|
||||
|
@ -163,7 +160,7 @@ void gui_init()
|
|||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__SWITCH__))
|
||||
#if !(defined(_WIN32) || defined(__APPLE__) || defined(__SWITCH__)) || defined(TARGET_IPHONE)
|
||||
scaling = std::max(1.f, screen_dpi / 100.f * 0.75f);
|
||||
#endif
|
||||
if (scaling > 1)
|
||||
|
@ -217,7 +214,7 @@ void gui_init()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
#elif __APPLE__
|
||||
#elif defined(__APPLE__) && !defined(TARGET_IPHONE)
|
||||
std::string fontDir = std::string("/System/Library/Fonts/");
|
||||
|
||||
extern std::string os_Locale();
|
||||
|
@ -258,7 +255,7 @@ void gui_init()
|
|||
io.Fonts->AddFontFromFileTTF("/system/fonts/NotoSansCJK-Regular.ttc", 17.f * scaling, &font_cfg, glyphRanges);
|
||||
}
|
||||
|
||||
// TODO Linux...
|
||||
// TODO Linux, iOS, ...
|
||||
#endif
|
||||
INFO_LOG(RENDERER, "Screen DPI is %d, size %d x %d. Scaling by %.2f", screen_dpi, screen_width, screen_height, scaling);
|
||||
|
||||
|
@ -332,7 +329,7 @@ static void ImGui_Impl_NewFrame()
|
|||
else
|
||||
io.MousePos = ImVec2(mouseX, mouseY);
|
||||
static bool delayTouch;
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(TARGET_IPHONE)
|
||||
// Delay touch by one frame to allow widgets to be hovered before click
|
||||
// This is required for widgets using ImGuiButtonFlags_AllowItemOverlap such as TabItem's
|
||||
if (!delayTouch && (mouseButtons & (1 << 0)) != 0 && !io.MouseDown[ImGuiMouseButton_Left])
|
||||
|
@ -1884,7 +1881,7 @@ static void gui_display_content()
|
|||
ImGui::Unindent(10 * scaling);
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
#ifndef __ANDROID__
|
||||
#if !defined(__ANDROID__) && !defined(TARGET_IPHONE)
|
||||
ImGui::SameLine(0, 32 * scaling);
|
||||
filter.Draw("Filter");
|
||||
#endif
|
||||
|
|
|
@ -10,15 +10,12 @@
|
|||
#ifdef __ANDROID__
|
||||
#include <sys/mman.h>
|
||||
#undef PAGE_MASK
|
||||
#define PAGE_MASK (PAGE_SIZE-1)
|
||||
#else
|
||||
#if defined(__APPLE__) && defined(__aarch64__)
|
||||
#elif defined(__APPLE__) && defined(__aarch64__)
|
||||
#define PAGE_SIZE 16384
|
||||
#else
|
||||
#define PAGE_SIZE 4096
|
||||
#endif
|
||||
#define PAGE_MASK (PAGE_SIZE-1)
|
||||
#endif
|
||||
|
||||
class cThread
|
||||
{
|
||||
|
@ -76,6 +73,7 @@ size_t get_last_slash_pos(const std::string& path);
|
|||
|
||||
bool mem_region_lock(void *start, std::size_t len);
|
||||
bool mem_region_unlock(void *start, std::size_t len);
|
||||
bool mem_region_set_exec(void *start, std::size_t len);
|
||||
|
||||
class VArray2 {
|
||||
public:
|
||||
|
|
14
core/types.h
14
core/types.h
|
@ -139,12 +139,18 @@ enum HollyInterruptID
|
|||
int darw_printf(const char* Text,...);
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_IPHONE
|
||||
#if defined(__APPLE__) && defined(__MACH__) && HOST_CPU == CPU_ARM64
|
||||
#define __ARM_MAC__
|
||||
#include "pthread.h"
|
||||
static void JITWriteProtect(bool enabled) { if (__builtin_available(macOS 11.0, *)) pthread_jit_write_protect_np(enabled); }
|
||||
#define TARGET_ARM_MAC
|
||||
#include "pthread.h"
|
||||
inline static void JITWriteProtect(bool enabled) {
|
||||
if (__builtin_available(macOS 11.0, *))
|
||||
pthread_jit_write_protect_np(enabled);
|
||||
}
|
||||
#else
|
||||
__forceinline static void JITWriteProtect(bool enabled) {}
|
||||
inline static void JITWriteProtect(bool enabled) {
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//includes from c++rt
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
*/
|
||||
#pragma once
|
||||
#if defined(__APPLE__)
|
||||
#if defined(TARGET_IPHONE) //apple-specific ogles2 headers
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#if defined(TARGET_IPHONE) //apple-specific ogles3 headers
|
||||
#include <OpenGLES/ES3/gl.h>
|
||||
#include <OpenGLES/ES3/glext.h>
|
||||
#else
|
||||
#include <OpenGL/gl3.h>
|
||||
#endif
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// AboutViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AboutViewController : UITableViewController {
|
||||
IBOutlet UILabel *versionLabel;
|
||||
}
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
|
||||
|
||||
@end
|
|
@ -1,83 +0,0 @@
|
|||
//
|
||||
// AboutViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "AboutViewController.h"
|
||||
#import "SWRevealViewController.h"
|
||||
|
||||
@interface AboutViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation AboutViewController
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.title = @"About";
|
||||
|
||||
versionLabel.text = [NSBundle mainBundle].infoDictionary[@"GitVersionString"];
|
||||
|
||||
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
|
||||
_sidebarButton.target = self.revealViewController;
|
||||
_sidebarButton.action = @selector(revealToggle:);
|
||||
|
||||
// Set the gesture
|
||||
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
|
||||
// Uncomment the following line to preserve selection between presentations.
|
||||
// self.clearsSelectionOnViewWillAppear = NO;
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSArray *developerTwitters = @[@"angelXwind"/*, @"LoungeKatt"*/]; //@LoungeKatt is private, so not linking it to the About dialog.
|
||||
NSArray *githubframeworks = @[@"John-Lluch/SWRevealViewController"];
|
||||
if (indexPath.section == 0 && indexPath.row == 0) //@reicastdc twitter
|
||||
{
|
||||
NSURL *twitterURL = [NSURL URLWithString:[NSString stringWithFormat:@"twitter://user?screen_name=reicastdc"]];
|
||||
if ([[UIApplication sharedApplication] canOpenURL:twitterURL])
|
||||
[[UIApplication sharedApplication] openURL:twitterURL];
|
||||
else
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://twitter.com/reicastdc"]]];
|
||||
} else if (indexPath.section == 0 && indexPath.row == 1) //reicast github
|
||||
{
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://github.com/reicast/reicast-emulator/"]]];
|
||||
} else if (indexPath.section == 1 && indexPath.row < developerTwitters.count) //developer twitter accounts
|
||||
{
|
||||
NSURL *twitterURL = [NSURL URLWithString:[NSString stringWithFormat:@"twitter://user?screen_name=%@", developerTwitters[indexPath.row]]];
|
||||
if ([[UIApplication sharedApplication] canOpenURL:twitterURL])
|
||||
[[UIApplication sharedApplication] openURL:twitterURL];
|
||||
else
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://twitter.com/%@", developerTwitters[indexPath.row]]]];
|
||||
} else if (indexPath.section == 2 && indexPath.row < githubframeworks.count) //third-party frameworks
|
||||
{
|
||||
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://github.com/%@", githubframeworks[indexPath.row]]]];
|
||||
}
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// AppDelegate.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Lounge Katt on 2/6/14.
|
||||
// Copyright (c) 2014 Lounge Katt. All rights reserved.
|
||||
//
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
//
|
||||
// AppDelegate.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Lounge Katt on 2/6/14.
|
||||
// Copyright (c) 2014 Lounge Katt. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
void emu_dc_term(void);
|
||||
void emu_gui_open(void);
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
|
@ -24,6 +24,7 @@
|
|||
{
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
emu_gui_open();
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||
|
@ -45,6 +46,7 @@
|
|||
- (void)applicationWillTerminate:(UIApplication *)application
|
||||
{
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
emu_dc_term();
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// BrowserTableViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface BrowserTableViewController : UITableViewController {
|
||||
NSArray *games;
|
||||
}
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
|
||||
|
||||
@end
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// BrowserTableViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "BrowserTableViewController.h"
|
||||
#import "SWRevealViewController.h"
|
||||
#import "EmulatorViewController.h"
|
||||
|
||||
@interface BrowserTableViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation BrowserTableViewController
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.title = @"Browser";
|
||||
|
||||
// versionLabel.text = [NSBundle mainBundle].infoDictionary[@"GitVersionString"];
|
||||
|
||||
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
|
||||
_sidebarButton.target = self.revealViewController;
|
||||
_sidebarButton.action = @selector(revealToggle:);
|
||||
|
||||
// Set the gesture
|
||||
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
// Uncomment the following line to preserve selection between presentations.
|
||||
// self.clearsSelectionOnViewWillAppear = NO;
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
// TODO: actual loading of games... and you know, the rest of the view controller.
|
||||
|
||||
@end
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// CloudVMUViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/5/23.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface CloudVMUViewController : UITableViewController
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
|
||||
|
||||
@end
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// CloudVMUViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/5/23.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "CloudVMUViewController.h"
|
||||
#import "SWRevealViewController.h"
|
||||
|
||||
@interface CloudVMUViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation CloudVMUViewController
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.title = @"Cloud VMU";
|
||||
|
||||
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
|
||||
_sidebarButton.target = self.revealViewController;
|
||||
_sidebarButton.action = @selector(revealToggle:);
|
||||
|
||||
// Set the gesture
|
||||
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
|
||||
|
||||
// Uncomment the following line to preserve selection between presentations.
|
||||
// self.clearsSelectionOnViewWillAppear = NO;
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
// TODO: write the rest of the view controller logic
|
||||
|
||||
@end
|
|
@ -1,8 +0,0 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface DiskViewCell : UITableViewCell
|
||||
|
||||
@property (nonatomic, retain) IBOutlet UIImageView *diskImage;
|
||||
@property (nonatomic, retain) IBOutlet UILabel *nameLabel;
|
||||
|
||||
@end
|
|
@ -1,26 +0,0 @@
|
|||
#import "DiskViewCell.h"
|
||||
|
||||
@implementation DiskViewCell
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
|
||||
{
|
||||
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
||||
if (self) {
|
||||
// Initialization code
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
|
||||
{
|
||||
[super setSelected:selected animated:animated];
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,41 +1,17 @@
|
|||
//
|
||||
// EmulatorView.h
|
||||
// emulator
|
||||
//
|
||||
// Created by admin on 1/18/15.
|
||||
// Copyright (c) 2015 reicast. All rights reserved.
|
||||
//
|
||||
|
||||
#import <GLKit/GLKit.h>
|
||||
#include "ios_mouse.h"
|
||||
|
||||
@interface EmulatorView : GLKView
|
||||
|
||||
- (void)handleKeyDown:(UIButton*)button;
|
||||
- (void)handleKeyUp:(UIButton*)button;
|
||||
- (void)touchLocation:(UITouch*)touch;
|
||||
|
||||
@property (nonatomic, strong) UIViewController *controllerView;
|
||||
@property IOSMouse *mouse;
|
||||
|
||||
@end
|
||||
|
||||
#define DC_BTN_C (1)
|
||||
#define DC_BTN_B (1<<1)
|
||||
#define DC_BTN_A (1<<2)
|
||||
#define DC_BTN_START (1<<3)
|
||||
#define DC_DPAD_UP (1<<4)
|
||||
#define DC_DPAD_DOWN (1<<5)
|
||||
#define DC_DPAD_LEFT (1<<6)
|
||||
#define DC_DPAD_RIGHT (1<<7)
|
||||
#define DC_BTN_Z (1<<8)
|
||||
#define DC_BTN_Y (1<<9)
|
||||
#define DC_BTN_X (1<<10)
|
||||
#define DC_BTN_D (1<<11)
|
||||
#define DC_DPAD2_UP (1<<12)
|
||||
#define DC_DPAD2_DOWN (1<<13)
|
||||
#define DC_DPAD2_LEFT (1<<14)
|
||||
#define DC_DPAD2_RIGHT (1<<15)
|
||||
|
||||
#define DC_AXIS_LT (0X10000)
|
||||
#define DC_AXIS_RT (0X10001)
|
||||
#define DC_AXIS_X (0X20000)
|
||||
#define DC_AXIS_Y (0X20001)
|
||||
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
//
|
||||
// EmulatorView.m
|
||||
// emulator
|
||||
//
|
||||
// Created by admin on 1/18/15.
|
||||
// Copyright (c) 2015 reicast. All rights reserved.
|
||||
//
|
||||
|
||||
|
@ -10,17 +6,11 @@
|
|||
#import "PadViewController.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
@implementation EmulatorView
|
||||
|
||||
/*
|
||||
// Only override drawRect: if you perform custom drawing.
|
||||
// An empty implementation adversely affects performance during animation.
|
||||
- (void)drawRect:(CGRect)rect {
|
||||
// Drawing code
|
||||
}
|
||||
*/
|
||||
|
||||
NSInteger a_button = 1;
|
||||
NSInteger b_button = 2;
|
||||
NSInteger x_button = 3;
|
||||
|
@ -42,37 +32,37 @@ NSInteger start_button = 11;
|
|||
{
|
||||
PadViewController * controller = (PadViewController *)self.controllerView;
|
||||
if (button == controller.img_dpad_l || button.tag == left_pad) {
|
||||
kcode[0] &= ~(DC_DPAD_LEFT);
|
||||
kcode[0] &= ~DC_DPAD_LEFT;
|
||||
}
|
||||
if (button == controller.img_dpad_r || button.tag == right_pad) {
|
||||
kcode[0] &= ~(DC_DPAD_RIGHT);
|
||||
kcode[0] &= ~DC_DPAD_RIGHT;
|
||||
}
|
||||
if (button == controller.img_dpad_u || button.tag == up_pad) {
|
||||
kcode[0] &= ~(DC_DPAD_UP);
|
||||
kcode[0] &= ~DC_DPAD_UP;
|
||||
}
|
||||
if (button == controller.img_dpad_d || button.tag == down_pad) {
|
||||
kcode[0] &= ~(DC_DPAD_DOWN);
|
||||
kcode[0] &= ~DC_DPAD_DOWN;
|
||||
}
|
||||
if (button == controller.img_abxy_a || button.tag == a_button) {
|
||||
kcode[0] &= ~(DC_BTN_A);
|
||||
kcode[0] &= ~DC_BTN_A;
|
||||
}
|
||||
if (button == controller.img_abxy_b || button.tag == b_button) {
|
||||
kcode[0] &= ~(DC_BTN_B);
|
||||
kcode[0] &= ~DC_BTN_B;
|
||||
}
|
||||
if (button == controller.img_abxy_x || button.tag == x_button) {
|
||||
kcode[0] &= ~(DC_BTN_X);
|
||||
kcode[0] &= ~DC_BTN_X;
|
||||
}
|
||||
if (button == controller.img_abxy_y || button.tag == y_button) {
|
||||
kcode[0] &= ~(DC_BTN_Y);
|
||||
kcode[0] &= ~DC_BTN_Y;
|
||||
}
|
||||
if (button == controller.img_lt || button.tag == left_trigger) {
|
||||
lt[0] = (255);
|
||||
lt[0] = 255;
|
||||
}
|
||||
if (button == controller.img_rt || button.tag == right_trigger) {
|
||||
rt[0] = (255);
|
||||
rt[0] = 255;
|
||||
}
|
||||
if (button == controller.img_start || button.tag == start_button) {
|
||||
kcode[0] &= ~(DC_BTN_START);
|
||||
kcode[0] &= ~DC_BTN_START;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,38 +70,67 @@ NSInteger start_button = 11;
|
|||
{
|
||||
PadViewController * controller = (PadViewController *)self.controllerView;
|
||||
if (button == controller.img_dpad_l || button.tag == left_pad) {
|
||||
kcode[0] |= ~(DC_DPAD_LEFT);
|
||||
kcode[0] |= DC_DPAD_LEFT;
|
||||
}
|
||||
if (button == controller.img_dpad_r || button.tag == right_pad) {
|
||||
kcode[0] |= ~(DC_DPAD_RIGHT);
|
||||
kcode[0] |= DC_DPAD_RIGHT;
|
||||
}
|
||||
if (button == controller.img_dpad_u || button.tag == up_pad) {
|
||||
kcode[0] |= ~(DC_DPAD_UP);
|
||||
kcode[0] |= DC_DPAD_UP;
|
||||
}
|
||||
if (button == controller.img_dpad_d || button.tag == down_pad) {
|
||||
kcode[0] |= ~(DC_DPAD_DOWN);
|
||||
kcode[0] |= DC_DPAD_DOWN;
|
||||
}
|
||||
if (button == controller.img_abxy_a || button.tag == a_button) {
|
||||
kcode[0] |= (DC_BTN_A);
|
||||
kcode[0] |= DC_BTN_A;
|
||||
}
|
||||
if (button == controller.img_abxy_b || button.tag == b_button) {
|
||||
kcode[0] |= (DC_BTN_B);
|
||||
kcode[0] |= DC_BTN_B;
|
||||
}
|
||||
if (button == controller.img_abxy_x || button.tag == x_button) {
|
||||
kcode[0] |= (DC_BTN_X);
|
||||
kcode[0] |= DC_BTN_X;
|
||||
}
|
||||
if (button == controller.img_abxy_y || button.tag == y_button) {
|
||||
kcode[0] |= (DC_BTN_Y);
|
||||
kcode[0] |= DC_BTN_Y;
|
||||
}
|
||||
if (button == controller.img_lt || button.tag == left_trigger) {
|
||||
lt[0] = (0);
|
||||
lt[0] = 0;
|
||||
}
|
||||
if (button == controller.img_rt || button.tag == right_trigger) {
|
||||
rt[0] = (0);
|
||||
rt[0] = 0;
|
||||
}
|
||||
if (button == controller.img_start || button.tag == start_button) {
|
||||
kcode[0] |= (DC_BTN_START);
|
||||
kcode[0] |= DC_BTN_START;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchLocation:(UITouch*)touch;
|
||||
{
|
||||
float scale = self.contentScaleFactor;
|
||||
CGPoint location = [touch locationInView:touch.view];
|
||||
_mouse->setAbsPos(location.x * scale, location.y * scale, self.bounds.size.width * scale, self.bounds.size.height * scale);
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
|
||||
{
|
||||
UITouch *touch = [touches anyObject];
|
||||
[self touchLocation:touch];
|
||||
if (gui_is_open())
|
||||
_mouse->setButton(Mouse::LEFT_BUTTON, true);
|
||||
}
|
||||
|
||||
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
|
||||
{
|
||||
UITouch *touch = [touches anyObject];
|
||||
[self touchLocation:touch];
|
||||
if (gui_is_open())
|
||||
_mouse->setButton(Mouse::LEFT_BUTTON, false);
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;
|
||||
{
|
||||
UITouch *touch = [touches anyObject];
|
||||
[self touchLocation:touch];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,572 +0,0 @@
|
|||
//
|
||||
// EmulatorViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai (angelXwind) on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "EmulatorViewController.h"
|
||||
|
||||
#import <OpenGLES/ES3/gl.h>
|
||||
#import <OpenGLES/ES3/glext.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "profiler/profiler.h"
|
||||
#include "cfg/cfg.h"
|
||||
#include "rend/TexCache.h"
|
||||
#include "hw/maple/maple_devs.h"
|
||||
#include "hw/maple/maple_if.h"
|
||||
#import <sys/kdebug_signpost.h>
|
||||
|
||||
#define USE_CRT_SHADER 0
|
||||
|
||||
@interface EmulatorViewController () {
|
||||
GLuint crtFragmentShader;
|
||||
GLuint crtShaderProgram;
|
||||
int crtUniform_DisplayRect;
|
||||
int crtUniform_EmulatedImage;
|
||||
int crtUniform_EmulatedImageSize;
|
||||
int crtUniform_FinalRes;
|
||||
|
||||
GLuint defaultVertexShader;
|
||||
}
|
||||
|
||||
@property (strong, nonatomic) EAGLContext *context;
|
||||
@property (strong, nonatomic) GLKBaseEffect *effect;
|
||||
|
||||
- (void)setupGL;
|
||||
- (void)tearDownGL;
|
||||
- (void)emuThread;
|
||||
|
||||
@end
|
||||
|
||||
//who has time for headers
|
||||
extern int screen_width,screen_height;
|
||||
bool rend_single_frame();
|
||||
bool gles_init();
|
||||
extern "C" int reicast_main(int argc, char* argv[]);
|
||||
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void move_pthread_to_realtime_scheduling_class(pthread_t pthread)
|
||||
{
|
||||
mach_timebase_info_data_t timebase_info;
|
||||
mach_timebase_info(&timebase_info);
|
||||
|
||||
const uint64_t NANOS_PER_MSEC = 1000000ULL;
|
||||
double clock2abs = ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
|
||||
|
||||
thread_time_constraint_policy_data_t policy;
|
||||
policy.period = 0;
|
||||
policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
|
||||
policy.constraint = (uint32_t)(10 * clock2abs);
|
||||
policy.preemptible = FALSE;
|
||||
|
||||
int kr = thread_policy_set(pthread_mach_thread_np(pthread_self()),
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(thread_policy_t)&policy,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
mach_error("thread_policy_set:", kr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void MakeCurrentThreadRealTime()
|
||||
{
|
||||
move_pthread_to_realtime_scheduling_class(pthread_self());
|
||||
}
|
||||
|
||||
@implementation EmulatorViewController
|
||||
|
||||
-(void)emuThread
|
||||
{
|
||||
char *Args[3];
|
||||
const char *P;
|
||||
|
||||
P = (const char *)[self.diskImage UTF8String];
|
||||
Args[0] = "dc";
|
||||
Args[1] = "-config";
|
||||
Args[2] = P&&P[0]? (char *)malloc(strlen(P)+32):0;
|
||||
|
||||
if(Args[2])
|
||||
{
|
||||
strcpy(Args[2],"config:image=");
|
||||
strcat(Args[2],P);
|
||||
}
|
||||
|
||||
MakeCurrentThreadRealTime();
|
||||
|
||||
reicast_main(Args[2]? 3:1,Args);
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
self.controllerView = [[PadViewController alloc] initWithNibName:@"PadViewController" bundle:nil];
|
||||
#endif
|
||||
|
||||
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
|
||||
|
||||
// Not sure what this effects in our case without making 2 contexts and swapping
|
||||
// [self.context setMultiThreaded:YES];
|
||||
|
||||
if (!self.context) {
|
||||
NSLog(@"Failed to create ES context");
|
||||
}
|
||||
|
||||
self.emuView = (EmulatorView *)self.view;
|
||||
// self.emuView.opaque = YES;
|
||||
self.emuView.context = self.context;
|
||||
self.emuView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
|
||||
// Set preferred refresh rate
|
||||
[self setPreferredFramesPerSecond:60];
|
||||
|
||||
[self.controllerView setControlOutput:self.emuView];
|
||||
|
||||
self.connectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
if ( GCController.controllers.count ){
|
||||
[self toggleHardwareController:YES];
|
||||
}
|
||||
}];
|
||||
self.disconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
if (GCController.controllers.count == 0) {
|
||||
[self toggleHardwareController:NO];
|
||||
}
|
||||
}];
|
||||
|
||||
if ([[GCController controllers] count]) {
|
||||
[self toggleHardwareController:YES];
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
[self addChildViewController:self.controllerView];
|
||||
self.controllerView.view.frame = self.view.bounds;
|
||||
self.controllerView.view.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
self.controllerView.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth;
|
||||
[self.view addSubview:self.controllerView.view];
|
||||
[self.controllerView didMoveToParentViewController:self];
|
||||
#endif
|
||||
|
||||
self.iCadeReader = [[iCadeReaderView alloc] init];
|
||||
[self.view addSubview:self.iCadeReader];
|
||||
self.iCadeReader.delegate = self;
|
||||
self.iCadeReader.active = YES;
|
||||
|
||||
[self setupGL];
|
||||
|
||||
if (!gles_init())
|
||||
die("OPENGL FAILED");
|
||||
|
||||
#if USE_CRT_SHADER
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
defaultVertexShader = [self compileShaderResource:@"default_vertex" ofType:GL_VERTEX_SHADER];
|
||||
[self setupCRTShader];
|
||||
#endif
|
||||
|
||||
NSThread* myThread = [[NSThread alloc] initWithTarget:self
|
||||
selector:@selector(emuThread)
|
||||
object:nil];
|
||||
[myThread start]; // Actually create the thread
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (crtShaderProgram > 0)
|
||||
{
|
||||
glDeleteProgram(crtShaderProgram);
|
||||
}
|
||||
if (crtFragmentShader > 0)
|
||||
{
|
||||
glDeleteShader(crtFragmentShader);
|
||||
}
|
||||
if (defaultVertexShader > 0)
|
||||
{
|
||||
glDeleteShader(defaultVertexShader);
|
||||
}
|
||||
|
||||
[self tearDownGL];
|
||||
|
||||
if ([EAGLContext currentContext] == self.context) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
//- (void)didReceiveMemoryWarning
|
||||
//{
|
||||
// [super didReceiveMemoryWarning];
|
||||
//
|
||||
// if ([self isViewLoaded] && ([[self view] window] == nil)) {
|
||||
// self.view = nil;
|
||||
//
|
||||
// [self tearDownGL];
|
||||
//
|
||||
// if ([EAGLContext currentContext] == self.context) {
|
||||
// [EAGLContext setCurrentContext:nil];
|
||||
// }
|
||||
// self.context = nil;
|
||||
// }
|
||||
//
|
||||
// // Dispose of any resources that can be recreated.
|
||||
//}
|
||||
|
||||
- (void)setupGL
|
||||
{
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
|
||||
}
|
||||
|
||||
- (void)tearDownGL
|
||||
{
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - GLKView and GLKViewController delegate methods
|
||||
|
||||
- (void)update
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)toggleHardwareController:(BOOL)useHardware {
|
||||
if (useHardware) {
|
||||
|
||||
[self.controllerView hideController];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
for(GCController*c in GCController.controllers) {
|
||||
if ((c.gamepad != nil || c.extendedGamepad != nil) && (c != _gController)) {
|
||||
|
||||
self.gController = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
self.gController = [GCController controllers].firstObject;
|
||||
#endif
|
||||
// TODO: ADd multi player using gController.playerIndex and iterate all controllers
|
||||
|
||||
if (self.gController.extendedGamepad) {
|
||||
[self.gController.extendedGamepad.buttonA setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~(DC_BTN_A);
|
||||
} else {
|
||||
kcode[0] |= (DC_BTN_A);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.buttonB setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~(DC_BTN_B);
|
||||
} else {
|
||||
kcode[0] |= (DC_BTN_B);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.buttonX setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~(DC_BTN_X);
|
||||
} else {
|
||||
kcode[0] |= (DC_BTN_X);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.buttonY setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~(DC_BTN_Y);
|
||||
} else {
|
||||
kcode[0] |= (DC_BTN_Y);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.rightTrigger setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
rt[0] = (255);
|
||||
} else {
|
||||
rt[0] = (0);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftTrigger setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
lt[0] = (255);
|
||||
} else {
|
||||
lt[0] = (0);
|
||||
}
|
||||
}];
|
||||
|
||||
// Either trigger for start
|
||||
[self.gController.extendedGamepad.rightShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~(DC_BTN_START);
|
||||
} else {
|
||||
kcode[0] |= (DC_BTN_START);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~(DC_BTN_START);
|
||||
} else {
|
||||
kcode[0] |= (DC_BTN_START);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.dpad setValueChangedHandler:^(GCControllerDirectionPad *dpad, float xValue, float yValue){
|
||||
if (dpad.right.isPressed) {
|
||||
kcode[0] &= ~(DC_DPAD_RIGHT);
|
||||
} else {
|
||||
kcode[0] |= (DC_DPAD_RIGHT);
|
||||
}
|
||||
if (dpad.left.isPressed) {
|
||||
kcode[0] &= ~(DC_DPAD_LEFT);
|
||||
} else {
|
||||
kcode[0] |= (DC_DPAD_LEFT);
|
||||
}
|
||||
if (dpad.up.isPressed) {
|
||||
kcode[0] &= ~(DC_DPAD_UP);
|
||||
} else {
|
||||
kcode[0] |= (DC_DPAD_UP);
|
||||
}
|
||||
if (dpad.down.isPressed) {
|
||||
kcode[0] &= ~(DC_DPAD_DOWN);
|
||||
} else {
|
||||
kcode[0] |= (DC_DPAD_DOWN);
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftThumbstick.xAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
s8 v=(s8)(value*127); //-127 ... + 127 range
|
||||
|
||||
NSLog(@"Joy X: %i", v);
|
||||
joyx[0] = v;
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftThumbstick.yAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
s8 v=(s8)(value*127 * - 1); //-127 ... + 127 range
|
||||
|
||||
NSLog(@"Joy Y: %i", v);
|
||||
joyy[0] = v;
|
||||
}];
|
||||
|
||||
// TODO: Right dpad
|
||||
// [self.gController.extendedGamepad.rightThumbstick.xAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
// s8 v=(s8)(value*127); //-127 ... + 127 range
|
||||
//
|
||||
// NSLog(@"Joy X: %i", v);
|
||||
// joyx[0] = v;
|
||||
// }];
|
||||
// [self.gController.extendedGamepad.rightThumbstick.yAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
// s8 v=(s8)(value*127 * - 1); //-127 ... + 127 range
|
||||
//
|
||||
// NSLog(@"Joy Y: %i", v);
|
||||
// joyy[0] = v;
|
||||
// }];
|
||||
}
|
||||
else if (self.gController.gamepad) {
|
||||
[self.gController.gamepad.buttonA setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_abxy_a];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_abxy_a];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.buttonB setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_abxy_b];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_abxy_b];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.buttonX setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_abxy_x];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_abxy_x];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.buttonY setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_abxy_y];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_abxy_y];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.dpad setValueChangedHandler:^(GCControllerDirectionPad *dpad, float xValue, float yValue){
|
||||
if (dpad.right.isPressed) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_dpad_r];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_dpad_r];
|
||||
}
|
||||
if (dpad.left.isPressed) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_dpad_l];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_dpad_l];
|
||||
}
|
||||
if (dpad.up.isPressed) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_dpad_u];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_dpad_u];
|
||||
}
|
||||
if (dpad.down.isPressed) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_dpad_d];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_dpad_d];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.gController.gamepad.rightShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_rt];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_rt];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.gController.gamepad.leftShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
[self.emuView handleKeyDown:self.controllerView.img_lt];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.controllerView.img_lt];
|
||||
}
|
||||
}];
|
||||
|
||||
//Add controller pause handler here
|
||||
}
|
||||
} else {
|
||||
self.gController = nil;
|
||||
[self.controllerView showController:self.view];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
||||
{
|
||||
// kdebug_signpost_start(10, 0, 0, 0, 0);
|
||||
screen_width = view.drawableWidth;
|
||||
screen_height = view.drawableHeight;
|
||||
|
||||
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
while(!rend_single_frame()) ;
|
||||
|
||||
#if USE_CRT_SHADER
|
||||
glUseProgram(crtShaderProgram);
|
||||
glUniform4f(crtUniform_DisplayRect, 0,0, 320, 640); // TODO: Correct sizes?
|
||||
glUniform1i(crtUniform_EmulatedImage, 0);
|
||||
glUniform2f(crtUniform_EmulatedImageSize, 320, 640);
|
||||
float finalResWidth = view.drawableWidth;
|
||||
float finalResHeight = view.drawableHeight;
|
||||
glUniform2f(crtUniform_FinalRes, finalResWidth, finalResHeight);
|
||||
#endif
|
||||
// kdebug_signpost_end(10, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*** CRT Shader borrowed from BrainDX for Provenance app ***/
|
||||
- (void)setupCRTShader
|
||||
{
|
||||
crtFragmentShader = [self compileShaderResource:@"crt_fragment" ofType:GL_FRAGMENT_SHADER];
|
||||
crtShaderProgram = [self linkVertexShader:defaultVertexShader withFragmentShader:crtFragmentShader];
|
||||
crtUniform_DisplayRect = glGetUniformLocation(crtShaderProgram, "DisplayRect");
|
||||
crtUniform_EmulatedImage = glGetUniformLocation(crtShaderProgram, "EmulatedImage");
|
||||
crtUniform_EmulatedImageSize = glGetUniformLocation(crtShaderProgram, "EmulatedImageSize");
|
||||
crtUniform_FinalRes = glGetUniformLocation(crtShaderProgram, "FinalRes");
|
||||
}
|
||||
|
||||
- (GLuint)compileShaderResource:(NSString*)shaderResourceName ofType:(GLenum)shaderType
|
||||
{
|
||||
NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderResourceName ofType:@"glsl"];
|
||||
if ( shaderPath == NULL )
|
||||
{
|
||||
NSLog(@"No shader path");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSString* shaderSource = [NSString stringWithContentsOfFile:shaderPath encoding:NSASCIIStringEncoding error:nil];
|
||||
if ( shaderSource == NULL )
|
||||
{
|
||||
NSLog(@"No shader source");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* shaderSourceCString = [shaderSource cStringUsingEncoding:NSASCIIStringEncoding];
|
||||
if ( shaderSourceCString == NULL )
|
||||
{
|
||||
NSLog(@"Nil shaderSourceCString");
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint shader = glCreateShader( shaderType );
|
||||
if ( shader == 0 )
|
||||
{
|
||||
NSLog(@"Nil shader");
|
||||
return 0;
|
||||
}
|
||||
|
||||
glShaderSource( shader, 1, &shaderSourceCString, NULL );
|
||||
glCompileShader( shader );
|
||||
|
||||
GLint compiled;
|
||||
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
|
||||
if ( compiled == 0 )
|
||||
{
|
||||
GLint infoLogLength = 0;
|
||||
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &infoLogLength );
|
||||
if ( infoLogLength > 1 )
|
||||
{
|
||||
char* infoLog = (char*)malloc( infoLogLength );
|
||||
glGetShaderInfoLog( shader, infoLogLength, NULL, infoLog );
|
||||
printf( "Error compiling shader: %s", infoLog );
|
||||
free( infoLog );
|
||||
}
|
||||
|
||||
NSLog(@"Compile fail");
|
||||
|
||||
glDeleteShader( shader );
|
||||
return 0;
|
||||
}
|
||||
|
||||
NSLog(@"Shader success %@", shaderResourceName);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
- (GLuint)linkVertexShader:(GLuint)vertexShader withFragmentShader:(GLuint)fragmentShader
|
||||
{
|
||||
GLuint shaderProgram = glCreateProgram();
|
||||
if ( shaderProgram == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
glAttachShader( shaderProgram, vertexShader );
|
||||
glAttachShader( shaderProgram, fragmentShader );
|
||||
|
||||
glBindAttribLocation( shaderProgram, GLKVertexAttribPosition, "vPosition" );
|
||||
glBindAttribLocation( shaderProgram, GLKVertexAttribTexCoord0, "vTexCoord" );
|
||||
|
||||
glLinkProgram( shaderProgram );
|
||||
|
||||
GLint linkStatus;
|
||||
glGetProgramiv( shaderProgram, GL_LINK_STATUS, &linkStatus );
|
||||
if ( linkStatus == 0 )
|
||||
{
|
||||
GLint infoLogLength = 0;
|
||||
glGetProgramiv( shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength );
|
||||
if ( infoLogLength > 1 )
|
||||
{
|
||||
char* infoLog = (char*)malloc( infoLogLength );
|
||||
glGetProgramInfoLog( shaderProgram, infoLogLength, NULL, infoLog );
|
||||
printf( "Error linking program: %s", infoLog );
|
||||
free( infoLog );
|
||||
}
|
||||
|
||||
glDeleteProgram( shaderProgram );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="d3D-2Q-2X9">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Flycast View Controller-->
|
||||
<scene sceneID="Gin-VO-aqM">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="emulatorView" id="d3D-2Q-2X9" customClass="FlycastViewController" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="r9P-b5-V6P" customClass="EmulatorView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="P3X-ZA-qIW"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="AiE-mC-9ra" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="152" y="78"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
|
@ -1,10 +1,3 @@
|
|||
//
|
||||
// EmulatorViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai (angelXwind) on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
|
@ -13,15 +6,14 @@
|
|||
#import "PadViewController.h"
|
||||
#import "EmulatorView.h"
|
||||
|
||||
@interface EmulatorViewController : GLKViewController <iCadeEventDelegate>
|
||||
@interface FlycastViewController : GLKViewController <iCadeEventDelegate>
|
||||
|
||||
@property NSString* diskImage;
|
||||
@property (nonatomic) iCadeReaderView* iCadeReader;
|
||||
@property (nonatomic) GCController *gController __attribute__((weak_import));
|
||||
@property (nonatomic, strong) id connectObserver;
|
||||
@property (nonatomic, strong) id disconnectObserver;
|
||||
@property (nonatomic, strong) EmulatorView *emuView;
|
||||
|
||||
@property (nonatomic, strong) PadViewController *controllerView;
|
||||
@property (nonatomic, strong) PadViewController *padController;
|
||||
|
||||
@end
|
|
@ -0,0 +1,423 @@
|
|||
//
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
#import "FlycastViewController.h"
|
||||
|
||||
#import <OpenGLES/ES3/gl.h>
|
||||
#import <OpenGLES/ES3/glext.h>
|
||||
#import <OpenGLES/EAGL.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "input/gamepad_device.h"
|
||||
#include "wsi/context.h"
|
||||
#include "rend/mainui.h"
|
||||
#include "emulator.h"
|
||||
#include "log/LogManager.h"
|
||||
#include "stdclass.h"
|
||||
#include "cfg/option.h"
|
||||
#include "ios_mouse.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
static std::shared_ptr<IOSMouse> mouse;
|
||||
|
||||
void common_linux_setup();
|
||||
|
||||
@interface FlycastViewController () {
|
||||
}
|
||||
|
||||
@property (strong, nonatomic) EAGLContext *context;
|
||||
|
||||
- (void)setupGL;
|
||||
|
||||
@end
|
||||
|
||||
extern int screen_width,screen_height;
|
||||
extern int screen_dpi;
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static void move_pthread_to_realtime_scheduling_class(pthread_t pthread)
|
||||
{
|
||||
mach_timebase_info_data_t timebase_info;
|
||||
mach_timebase_info(&timebase_info);
|
||||
|
||||
const uint64_t NANOS_PER_MSEC = 1000000ULL;
|
||||
double clock2abs = ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
|
||||
|
||||
thread_time_constraint_policy_data_t policy;
|
||||
policy.period = 0;
|
||||
policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
|
||||
policy.constraint = (uint32_t)(10 * clock2abs);
|
||||
policy.preemptible = FALSE;
|
||||
|
||||
int kr = thread_policy_set(pthread_mach_thread_np(pthread_self()),
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(thread_policy_t)&policy,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
mach_error("thread_policy_set:", kr);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO use this for emu thread?
|
||||
static void MakeCurrentThreadRealTime()
|
||||
{
|
||||
move_pthread_to_realtime_scheduling_class(pthread_self());
|
||||
}
|
||||
|
||||
@implementation FlycastViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
LogManager::Init();
|
||||
|
||||
std::string homedir = [[[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] path] UTF8String];
|
||||
homedir += "/";
|
||||
set_user_config_dir(homedir);
|
||||
set_user_data_dir(homedir);
|
||||
|
||||
#ifdef DEBUG
|
||||
int ret = task_set_exception_ports(
|
||||
mach_task_self(),
|
||||
EXC_MASK_BAD_ACCESS,
|
||||
MACH_PORT_NULL,
|
||||
EXCEPTION_DEFAULT,
|
||||
0);
|
||||
|
||||
if (ret != KERN_SUCCESS) {
|
||||
printf("task_set_exception_ports: %s\n", mach_error_string(ret));
|
||||
}
|
||||
#endif
|
||||
|
||||
common_linux_setup();
|
||||
|
||||
flycast_init(0, nullptr);
|
||||
config::ContentPath.get().clear();
|
||||
config::ContentPath.get().push_back(homedir);
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
self.padController = [[PadViewController alloc] initWithNibName:@"PadViewController" bundle:nil];
|
||||
#endif
|
||||
|
||||
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
|
||||
|
||||
// Not sure what this effects in our case without making 2 contexts and swapping
|
||||
// [self.context setMultiThreaded:YES];
|
||||
|
||||
if (!self.context) {
|
||||
NSLog(@"Failed to create ES context");
|
||||
}
|
||||
|
||||
self.emuView = (EmulatorView *)self.view;
|
||||
// self.emuView.opaque = YES;
|
||||
self.emuView.context = self.context;
|
||||
self.emuView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
|
||||
|
||||
// Set preferred refresh rate
|
||||
[self setPreferredFramesPerSecond:60];
|
||||
|
||||
[self.padController setControlOutput:self.emuView];
|
||||
|
||||
self.connectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
if ( GCController.controllers.count ){
|
||||
[self toggleHardwareController:YES];
|
||||
}
|
||||
}];
|
||||
self.disconnectObserver = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||
if (GCController.controllers.count == 0) {
|
||||
[self toggleHardwareController:NO];
|
||||
}
|
||||
}];
|
||||
|
||||
if ([[GCController controllers] count]) {
|
||||
[self toggleHardwareController:YES];
|
||||
}
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
[self addChildViewController:self.padController];
|
||||
self.padController.view.frame = self.view.bounds;
|
||||
self.padController.view.translatesAutoresizingMaskIntoConstraints = YES;
|
||||
self.padController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth;
|
||||
[self.view addSubview:self.padController.view];
|
||||
[self.padController didMoveToParentViewController:self];
|
||||
[self.padController hideController];
|
||||
#endif
|
||||
|
||||
self.iCadeReader = [[iCadeReaderView alloc] init];
|
||||
[self.view addSubview:self.iCadeReader];
|
||||
self.iCadeReader.delegate = self;
|
||||
self.iCadeReader.active = YES;
|
||||
|
||||
[self setupGL];
|
||||
|
||||
screen_width = roundf([[UIScreen mainScreen] nativeBounds].size.width);
|
||||
screen_height = roundf([[UIScreen mainScreen] nativeBounds].size.height);
|
||||
if (screen_width < screen_height)
|
||||
std::swap(screen_width, screen_height);
|
||||
float scale = 1;
|
||||
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
|
||||
scale = [[UIScreen mainScreen] scale];
|
||||
}
|
||||
screen_dpi = roundf(160 * scale);
|
||||
InitRenderApi();
|
||||
mainui_init();
|
||||
mainui_enabled = true;
|
||||
|
||||
self.emuView.mouse = ::mouse.get();
|
||||
|
||||
// Swipe right to open the menu in-game
|
||||
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipe:)];
|
||||
[swipe setDirection:UISwipeGestureRecognizerDirectionRight];
|
||||
[self.view addGestureRecognizer:swipe];
|
||||
}
|
||||
|
||||
- (void)handleSwipe:(UISwipeGestureRecognizer *)swipe {
|
||||
gui_open_settings();
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if ([EAGLContext currentContext] == self.context) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupGL
|
||||
{
|
||||
[EAGLContext setCurrentContext:self.context];
|
||||
}
|
||||
|
||||
#pragma mark - GLKView and GLKViewController delegate methods
|
||||
|
||||
- (void)update
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
- (void)toggleHardwareController:(BOOL)useHardware {
|
||||
if (useHardware) {
|
||||
|
||||
[self.padController hideController];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
for(GCController*c in GCController.controllers) {
|
||||
if ((c.gamepad != nil || c.extendedGamepad != nil) && (c != _gController)) {
|
||||
|
||||
self.gController = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
self.gController = [GCController controllers].firstObject;
|
||||
#endif
|
||||
// TODO: Add multi player using gController.playerIndex and iterate all controllers
|
||||
|
||||
if (self.gController.extendedGamepad) {
|
||||
[self.gController.extendedGamepad.buttonA setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~DC_BTN_A;
|
||||
} else {
|
||||
kcode[0] |= DC_BTN_A;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.buttonB setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~DC_BTN_B;
|
||||
} else {
|
||||
kcode[0] |= DC_BTN_B;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.buttonX setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~DC_BTN_X;
|
||||
} else {
|
||||
kcode[0] |= DC_BTN_X;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.buttonY setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~DC_BTN_Y;
|
||||
} else {
|
||||
kcode[0] |= DC_BTN_Y;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.rightTrigger setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
rt[0] = 255;
|
||||
} else {
|
||||
rt[0] = 0;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftTrigger setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
lt[0] = 255;
|
||||
} else {
|
||||
lt[0] = 0;
|
||||
}
|
||||
}];
|
||||
|
||||
// Either trigger for start
|
||||
[self.gController.extendedGamepad.rightShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~DC_BTN_START;
|
||||
} else {
|
||||
kcode[0] |= DC_BTN_START;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
kcode[0] &= ~DC_BTN_START;
|
||||
} else {
|
||||
kcode[0] |= DC_BTN_START;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.dpad setValueChangedHandler:^(GCControllerDirectionPad *dpad, float xValue, float yValue){
|
||||
if (dpad.right.isPressed) {
|
||||
kcode[0] &= ~DC_DPAD_RIGHT;
|
||||
} else {
|
||||
kcode[0] |= DC_DPAD_RIGHT;
|
||||
}
|
||||
if (dpad.left.isPressed) {
|
||||
kcode[0] &= ~DC_DPAD_LEFT;
|
||||
} else {
|
||||
kcode[0] |= DC_DPAD_LEFT;
|
||||
}
|
||||
if (dpad.up.isPressed) {
|
||||
kcode[0] &= ~DC_DPAD_UP;
|
||||
} else {
|
||||
kcode[0] |= DC_DPAD_UP;
|
||||
}
|
||||
if (dpad.down.isPressed) {
|
||||
kcode[0] &= ~DC_DPAD_DOWN;
|
||||
} else {
|
||||
kcode[0] |= DC_DPAD_DOWN;
|
||||
}
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftThumbstick.xAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
s8 v=(s8)(value*127); //-127 ... + 127 range
|
||||
|
||||
NSLog(@"Joy X: %i", v);
|
||||
joyx[0] = v;
|
||||
}];
|
||||
[self.gController.extendedGamepad.leftThumbstick.yAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
s8 v=(s8)(value*127 * - 1); //-127 ... + 127 range
|
||||
|
||||
NSLog(@"Joy Y: %i", v);
|
||||
joyy[0] = v;
|
||||
}];
|
||||
|
||||
// TODO: Right dpad
|
||||
// [self.gController.extendedGamepad.rightThumbstick.xAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
// s8 v=(s8)(value*127); //-127 ... + 127 range
|
||||
//
|
||||
// NSLog(@"Joy X: %i", v);
|
||||
// joyx[0] = v;
|
||||
// }];
|
||||
// [self.gController.extendedGamepad.rightThumbstick.yAxis setValueChangedHandler:^(GCControllerAxisInput *axis, float value){
|
||||
// s8 v=(s8)(value*127 * - 1); //-127 ... + 127 range
|
||||
//
|
||||
// NSLog(@"Joy Y: %i", v);
|
||||
// joyy[0] = v;
|
||||
// }];
|
||||
}
|
||||
else if (self.gController.gamepad) {
|
||||
[self.gController.gamepad.buttonA setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.padController.img_abxy_a];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_abxy_a];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.buttonB setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.padController.img_abxy_b];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_abxy_b];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.buttonX setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.padController.img_abxy_x];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_abxy_x];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.buttonY setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed && value >= 0.1) {
|
||||
[self.emuView handleKeyDown:self.padController.img_abxy_y];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_abxy_y];
|
||||
}
|
||||
}];
|
||||
[self.gController.gamepad.dpad setValueChangedHandler:^(GCControllerDirectionPad *dpad, float xValue, float yValue){
|
||||
if (dpad.right.isPressed) {
|
||||
[self.emuView handleKeyDown:self.padController.img_dpad_r];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_dpad_r];
|
||||
}
|
||||
if (dpad.left.isPressed) {
|
||||
[self.emuView handleKeyDown:self.padController.img_dpad_l];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_dpad_l];
|
||||
}
|
||||
if (dpad.up.isPressed) {
|
||||
[self.emuView handleKeyDown:self.padController.img_dpad_u];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_dpad_u];
|
||||
}
|
||||
if (dpad.down.isPressed) {
|
||||
[self.emuView handleKeyDown:self.padController.img_dpad_d];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_dpad_d];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.gController.gamepad.rightShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
[self.emuView handleKeyDown:self.padController.img_rt];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_rt];
|
||||
}
|
||||
}];
|
||||
|
||||
[self.gController.gamepad.leftShoulder setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
|
||||
if (pressed) {
|
||||
[self.emuView handleKeyDown:self.padController.img_lt];
|
||||
} else {
|
||||
[self.emuView handleKeyUp:self.padController.img_lt];
|
||||
}
|
||||
}];
|
||||
|
||||
//Add controller pause handler here
|
||||
}
|
||||
} else {
|
||||
self.gController = nil;
|
||||
[self.padController showController:self.view];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
|
||||
{
|
||||
if (dc_is_running() != [self.padController isControllerVisible] && self.gController == nil)
|
||||
{
|
||||
if (dc_is_running())
|
||||
[self.padController showController:self.view];
|
||||
else
|
||||
[self.padController hideController];
|
||||
}
|
||||
mainui_rend_frame();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void os_SetupInput()
|
||||
{
|
||||
mouse = std::make_shared<IOSMouse>();
|
||||
GamepadDevice::Register(mouse);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// InputViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface InputViewController : UITableViewController
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
|
||||
|
||||
@end
|
|
@ -1,55 +0,0 @@
|
|||
//
|
||||
// InputViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "InputViewController.h"
|
||||
#import "SWRevealViewController.h"
|
||||
|
||||
@interface InputViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation InputViewController
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.title = @"Input";
|
||||
|
||||
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
|
||||
_sidebarButton.target = self.revealViewController;
|
||||
_sidebarButton.action = @selector(revealToggle:);
|
||||
|
||||
// Set the gesture
|
||||
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
|
||||
// Uncomment the following line to preserve selection between presentations.
|
||||
// self.clearsSelectionOnViewWillAppear = NO;
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
// TODO: write the rest of the view controller logic
|
||||
|
||||
@end
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5yN-ib-e7B">
|
||||
<device id="retina6_1" orientation="landscape" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="H4c-ak-AnR">
|
||||
<objects>
|
||||
<viewController id="5yN-ib-e7B" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="VkR-ZF-hcR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="896" height="414"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="flycast" translatesAutoresizingMaskIntoConstraints="NO" id="gLM-Eh-Wd0">
|
||||
<rect key="frame" x="304" y="64" width="288" height="286"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<viewLayoutGuide key="safeArea" id="hPj-CF-OCp"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="38V-np-Q7Z" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="133.125" y="78.16901408450704"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="flycast" width="512" height="512"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -1,104 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="mSg-lr-0DL">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Root View Controller-->
|
||||
<scene sceneID="q8K-fk-uPf">
|
||||
<objects>
|
||||
<tableViewController id="ZcT-ex-GUK" customClass="PathsViewController" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="LNG-KY-d6N">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<prototypes>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="Cell" rowHeight="80" id="mMa-C3-VYu" customClass="DiskViewCell">
|
||||
<rect key="frame" x="0.0" y="22" width="320" height="80"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="mMa-C3-VYu" id="snt-ku-Aaq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="79.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="disk_unknown.png" id="6Qh-mW-Z9j">
|
||||
<rect key="frame" x="8" y="4" width="72" height="72"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Epl-iu-f5s">
|
||||
<rect key="frame" x="88" y="24" width="199" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="diskImage" destination="6Qh-mW-Z9j" id="b3r-L8-LS3"/>
|
||||
<outlet property="nameLabel" destination="Epl-iu-f5s" id="i0S-JF-deT"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="ZcT-ex-GUK" id="TGz-Qe-tBz"/>
|
||||
<outlet property="delegate" destination="ZcT-ex-GUK" id="LAp-Yu-Mwb"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" title="Root View Controller" id="5jN-Uj-bBb"/>
|
||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics"/>
|
||||
<connections>
|
||||
<segue destination="WRM-pR-XCP" kind="modal" identifier="emulatorView" id="b10-sb-xpr"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="mdD-bX-Gqc" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-88" y="-692"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="VLz-J1-2XD">
|
||||
<objects>
|
||||
<navigationController navigationBarHidden="YES" id="mSg-lr-0DL" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="vT9-en-Ct5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
<segue destination="ZcT-ex-GUK" kind="relationship" relationship="rootViewController" id="fhp-zt-Xhh"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="i7I-Ys-F6b" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-692" y="-692"/>
|
||||
</scene>
|
||||
<!--Emulator View Controller-->
|
||||
<scene sceneID="h6I-2s-MCy">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="emulatorView" wantsFullScreenLayout="YES" id="WRM-pR-XCP" customClass="EmulatorViewController" sceneMemberID="viewController">
|
||||
<view key="view" multipleTouchEnabled="YES" contentMode="scaleToFill" id="JQE-db-ZiC" customClass="EmulatorView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="568" height="320"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<accessibility key="accessibilityConfiguration">
|
||||
<accessibilityTraits key="traits" none="YES" notEnabled="YES"/>
|
||||
</accessibility>
|
||||
<gestureRecognizers/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="FmO-Yo-nVN"/>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ioY-OH-Jev" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="486" y="-692"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="disk_unknown.png" width="95" height="95"/>
|
||||
</resources>
|
||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||
<simulatedStatusBarMetrics key="statusBar"/>
|
||||
<simulatedOrientationMetrics key="orientation"/>
|
||||
<simulatedScreenMetrics key="destination" type="retina4"/>
|
||||
</simulatedMetricsContainer>
|
||||
<color key="tintColor" red="0.2470588386" green="0.50196081400000003" blue="0.84705889229999998" alpha="1" colorSpace="deviceRGB"/>
|
||||
</document>
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// PadViewController.h
|
||||
// reicast-ios
|
||||
//
|
||||
// Created by Lounge Katt on 8/25/15.
|
||||
// Copyright (c) 2015 reicast. All rights reserved.
|
||||
//
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
//
|
||||
// Created by Lounge Katt on 8/25/15.
|
||||
// Copyright (c) 2015 reicast. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PadViewController.h"
|
||||
#import "EmulatorView.h"
|
||||
|
||||
@interface PadViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation PadViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (void)showController:(UIView *)parentView
|
||||
{
|
||||
[parentView addSubview:self.view];
|
||||
}
|
||||
|
||||
- (void)hideController
|
||||
{
|
||||
[self.view removeFromSuperview];
|
||||
}
|
||||
|
||||
- (BOOL)isControllerVisible {
|
||||
if (self.view.window != nil) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)setControlOutput:(EmulatorView *)output
|
||||
{
|
||||
self.handler = output;
|
||||
}
|
||||
|
||||
- (IBAction)keycodeDown:(id)sender
|
||||
{
|
||||
[self.handler handleKeyDown:(UIButton*)sender];
|
||||
}
|
||||
|
||||
- (IBAction)keycodeUp:(id)sender
|
||||
{
|
||||
[self.handler handleKeyUp:(UIButton*)sender];
|
||||
}
|
||||
|
||||
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
|
||||
{
|
||||
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES">
|
||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
|
@ -24,7 +24,7 @@
|
|||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view multipleTouchEnabled="YES" contentMode="scaleToFill" id="3M7-1s-N5r">
|
||||
<view multipleTouchEnabled="YES" alpha="0.5" contentMode="scaleToFill" id="3M7-1s-N5r">
|
||||
<rect key="frame" x="0.0" y="0.0" width="568" height="340"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
|
@ -32,7 +32,7 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="80" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="9" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8Gl-Iv-u8L" userLabel="LT-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="9" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8Gl-Iv-u8L" userLabel="LT-Button">
|
||||
<rect key="frame" x="0.0" y="0.0" width="80" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -47,7 +47,7 @@
|
|||
<rect key="frame" x="488" y="0.0" width="80" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="10" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="V8J-vG-dlF" userLabel="RT-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="10" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="V8J-vG-dlF" userLabel="RT-Button">
|
||||
<rect key="frame" x="488" y="0.0" width="80" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -70,7 +70,7 @@
|
|||
<rect key="frame" x="0.0" y="44" width="140" height="140"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rp6-Nd-1qa" userLabel="L-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="7" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rp6-Nd-1qa" userLabel="L-Button">
|
||||
<rect key="frame" x="0.0" y="94" width="46" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -81,7 +81,7 @@
|
|||
<action selector="keycodeUp:" destination="-1" eventType="touchUpInside" id="5gI-j0-ANf"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CVH-hw-R8F" userLabel="R-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="8" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CVH-hw-R8F" userLabel="R-Button">
|
||||
<rect key="frame" x="94" y="94" width="46" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -92,7 +92,7 @@
|
|||
<action selector="keycodeUp:" destination="-1" eventType="touchUpInside" id="woi-3Y-IfD"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WMD-Fv-ibu" userLabel="U-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="5" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WMD-Fv-ibu" userLabel="U-Button">
|
||||
<rect key="frame" x="50" y="44" width="40" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -103,7 +103,7 @@
|
|||
<action selector="keycodeUp:" destination="-1" eventType="touchUpInside" id="R0R-dl-GAG"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="s7g-nq-lRU" userLabel="D-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="6" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="s7g-nq-lRU" userLabel="D-Button">
|
||||
<rect key="frame" x="50" y="144" width="40" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -118,7 +118,7 @@
|
|||
<rect key="frame" x="408" y="159" width="160" height="161"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="3" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iwO-7q-c8H" userLabel="X-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="3" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iwO-7q-c8H" userLabel="X-Button">
|
||||
<rect key="frame" x="408" y="210" width="60" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -129,7 +129,7 @@
|
|||
<action selector="keycodeUp:" destination="-1" eventType="touchUpInside" id="dhr-NT-lcF"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="2" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7LB-OY-vh3" userLabel="B-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="2" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7LB-OY-vh3" userLabel="B-Button">
|
||||
<rect key="frame" x="508" y="210" width="60" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -140,7 +140,7 @@
|
|||
<action selector="keycodeUp:" destination="-1" eventType="touchUpInside" id="zqg-KK-Wxb"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hGZ-v7-VA5" userLabel="Y-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="4" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hGZ-v7-VA5" userLabel="Y-Button">
|
||||
<rect key="frame" x="458" y="159" width="60" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -151,7 +151,7 @@
|
|||
<action selector="keycodeUp:" destination="-1" eventType="touchUpInside" id="oai-Xb-scl"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iKO-3z-Ias" userLabel="A-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="1" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iKO-3z-Ias" userLabel="A-Button">
|
||||
<rect key="frame" x="458" y="260" width="60" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
@ -166,7 +166,7 @@
|
|||
<rect key="frame" x="244" y="272" width="80" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
</imageView>
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="11" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VtI-tC-PSX" userLabel="S-Button">
|
||||
<button opaque="NO" multipleTouchEnabled="YES" tag="11" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VtI-tC-PSX" userLabel="S-Button">
|
||||
<rect key="frame" x="257" y="272" width="54" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<state key="normal">
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// PathsViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface PathsViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource>
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray* diskImages;
|
||||
|
||||
@end
|
|
@ -1,115 +0,0 @@
|
|||
//
|
||||
// PathsViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "PathsViewController.h"
|
||||
//#import "SWRevealViewController.h"
|
||||
#import "EmulatorViewController.h"
|
||||
#import "DiskViewCell.h"
|
||||
|
||||
@interface PathsViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation PathsViewController
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSURL *)documents
|
||||
{
|
||||
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.title = @"Paths";
|
||||
|
||||
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
|
||||
// _sidebarButton.target = self.revealViewController;
|
||||
// _sidebarButton.action = @selector(revealToggle:);
|
||||
|
||||
// Set the gesture
|
||||
// [self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
|
||||
// Uncomment the following line to preserve selection between presentations.
|
||||
// self.clearsSelectionOnViewWillAppear = NO;
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
|
||||
self.diskImages = [[NSMutableArray alloc] init];
|
||||
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self documents].path error:NULL];
|
||||
NSPredicate *diskPredicate = [NSPredicate predicateWithFormat:@"self ENDSWITH '.chd' || self ENDSWITH '.gdi'
|
||||
|| self ENDSWITH '.cdi' || self ENDSWITH '.cue' || self ENDSWITH '.CHD' || self ENDSWITH '.GDI'
|
||||
|| self ENDSWITH '.CDI' || self ENDSWITH '.CUE'"];
|
||||
self.diskImages = [NSMutableArray arrayWithArray:[files filteredArrayUsingPredicate:diskPredicate]];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
-(NSInteger)numberOfSectionsInTableView: (UITableView*)tableView
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
-(NSInteger)tableView: (UITableView *)tableView numberOfRowsInSection: (NSInteger)section
|
||||
{
|
||||
return [self.diskImages count];
|
||||
}
|
||||
|
||||
-(NSString*)tableView: (UITableView*)tableView titleForHeaderInSection: (NSInteger)section
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return 80;
|
||||
// Assign the specific cell height to prevent issues with custom size
|
||||
}
|
||||
|
||||
-(UITableViewCell*)tableView: (UITableView*)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
|
||||
{
|
||||
static NSString *CellIdentifier = @"Cell";
|
||||
|
||||
DiskViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
|
||||
NSString* imagePath = [self.diskImages objectAtIndex: indexPath.row];
|
||||
|
||||
cell.nameLabel.text = [[imagePath lastPathComponent] stringByDeletingPathExtension];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
-(void)prepareForSegue: (UIStoryboardSegue*)segue sender: (id)sender
|
||||
{
|
||||
if ([segue.identifier isEqualToString:@"emulatorView"]) {
|
||||
NSIndexPath* indexPath = self.tableView.indexPathForSelectedRow;
|
||||
NSString* filePath = [self.diskImages objectAtIndex: indexPath.row];
|
||||
NSString* diskPath = [[self documents].path stringByAppendingPathComponent: filePath];
|
||||
EmulatorViewController* emulatorView = segue.destinationViewController;
|
||||
emulatorView.diskImage = diskPath;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)tableView: (UITableView*)tableView didSelectRowAtIndexPath: (NSIndexPath*)indexPath
|
||||
{
|
||||
[self performSegueWithIdentifier: @"emulatorView" sender: self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,274 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2013 Joan Lluch <joan.lluch@sweetwilliamsl.com>
|
||||
|
||||
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.
|
||||
|
||||
Early code inspired on a similar class by Philip Kluz (Philip.Kluz@zuui.org)
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
RELEASE NOTES
|
||||
|
||||
Version 1.1.2 (Current Version)
|
||||
|
||||
- The status bar style and appearance are now handled in sync with the class animations.
|
||||
You can implement the methods preferredStatusBarStyle and prefersStatusBarHidden on your child controllers to define the desired appearance
|
||||
|
||||
- The loadView method now calls a method, loadStoryboardControllers, just for the purpose of loading child controllers from a storyboard.
|
||||
You can override this method and remove the @try @catch statements if you want the debuger not to stop at them in case you have set an exception breakpoint.
|
||||
|
||||
Version 1.1.1
|
||||
|
||||
- You can now get a tapGestureRecognizer from the class. See the tapGestureRecognizer method for more information.
|
||||
|
||||
- Both the panGestureRecognizer and the tapGestureRecognizer are now attached to the revealViewController's front content view
|
||||
by default, so they will start working just by calling their access methods even if you do not attach them to any of your views.
|
||||
This enables you to dissable interactions on your views -for example based on position- without breaking normal gesture behavior.
|
||||
|
||||
- Corrected a bug that caused a crash on iOS6 and earlier.
|
||||
|
||||
Version 1.1.0
|
||||
|
||||
- The method setFrontViewController:animated now performs the correct animations both for left and right controllers.
|
||||
|
||||
- The class now automatically handles the status bar appearance depending on the currently shown child controller.
|
||||
|
||||
Version 1.0.8
|
||||
|
||||
- Support for constant width frontView by setting a negative value to reveal widths. See properties rearViewRevealWidth and rightViewRevealWidth
|
||||
|
||||
- Support for draggableBorderWidth. See property of the same name.
|
||||
|
||||
- The Pan gesture recongnizer can be disabled by implementing the following delegate method and returning NO
|
||||
revealControllerPanGestureShouldBegin:
|
||||
|
||||
- Added the ability to track pan gesture reveal progress through the following new delegate methods
|
||||
revealController:panGestureBeganFromLocation:progress:
|
||||
revealController:panGestureMovedToLocation:progress:
|
||||
revealController:panGestureEndedToLocation:progress:
|
||||
|
||||
Previous Versions
|
||||
|
||||
- No release notes were updated for previous versions.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class SWRevealViewController;
|
||||
@protocol SWRevealViewControllerDelegate;
|
||||
|
||||
#pragma mark - SWRevealViewController Class
|
||||
|
||||
// Enum values for setFrontViewPosition:animated:
|
||||
typedef enum
|
||||
{
|
||||
// Front controller is removed from view. Animated transitioning from this state will cause the same
|
||||
// effect than animating from FrontViewPositionLeftSideMost. Use this instead of FrontViewPositionLeftSideMost when
|
||||
// you want to remove the front view controller view from the view hierarchy.
|
||||
FrontViewPositionLeftSideMostRemoved,
|
||||
|
||||
// Left most position, front view is presented left-offseted by rightViewRevealWidth+rigthViewRevealOverdraw
|
||||
FrontViewPositionLeftSideMost,
|
||||
|
||||
// Left position, front view is presented left-offseted by rightViewRevealWidth
|
||||
FrontViewPositionLeftSide,
|
||||
|
||||
// Center position, rear view is hidden behind front controller
|
||||
FrontViewPositionLeft,
|
||||
|
||||
// Right possition, front view is presented right-offseted by rearViewRevealWidth
|
||||
FrontViewPositionRight,
|
||||
|
||||
// Right most possition, front view is presented right-offseted by rearViewRevealWidth+rearViewRevealOverdraw
|
||||
FrontViewPositionRightMost,
|
||||
|
||||
// Front controller is removed from view. Animated transitioning from this state will cause the same
|
||||
// effect than animating from FrontViewPositionRightMost. Use this instead of FrontViewPositionRightMost when
|
||||
// you intent to remove the front controller view from the view hierarchy.
|
||||
FrontViewPositionRightMostRemoved,
|
||||
|
||||
} FrontViewPosition;
|
||||
|
||||
|
||||
@interface SWRevealViewController : UIViewController
|
||||
|
||||
// Object instance init and rear view setting
|
||||
- (id)initWithRearViewController:(UIViewController *)rearViewController frontViewController:(UIViewController *)frontViewController;
|
||||
|
||||
// Rear view controller, can be nil if not used
|
||||
@property (strong, nonatomic) UIViewController *rearViewController;
|
||||
|
||||
// Optional right view controller, can be nil if not used
|
||||
@property (strong, nonatomic) UIViewController *rightViewController;
|
||||
|
||||
// Front view controller, can be nil on initialization but must be supplied by the time its view is loaded
|
||||
@property (strong, nonatomic) UIViewController *frontViewController;
|
||||
|
||||
// Sets the frontViewController using a default set of chained animations consisting on moving the
|
||||
// presented frontViewController to the top most right, replacing it, and moving it back to the left position
|
||||
- (void)setFrontViewController:(UIViewController *)frontViewController animated:(BOOL)animated;
|
||||
|
||||
// Front view position, use this to set a particular position state on the controller
|
||||
// On initialization it is set to FrontViewPositionLeft
|
||||
@property (assign, nonatomic) FrontViewPosition frontViewPosition;
|
||||
|
||||
// Chained animation of the frontViewController position. You can call it several times in a row to achieve
|
||||
// any set of animations you wish. Animations will be chained and performed one after the other.
|
||||
- (void)setFrontViewPosition:(FrontViewPosition)frontViewPosition animated:(BOOL)animated;
|
||||
|
||||
// Toogles the current state of the front controller between Left or Right and fully visible
|
||||
// Use setFrontViewPosition to set a particular position
|
||||
- (void)revealToggleAnimated:(BOOL)animated;
|
||||
- (void)rightRevealToggleAnimated:(BOOL)animated; // <-- simetric implementation of the above for the rightViewController
|
||||
|
||||
// The following methods are meant to be directly connected to the action method of a button
|
||||
// to perform user triggered postion change of the controller views. This is ussually added to a
|
||||
// button on top left or right of the frontViewController
|
||||
- (void)revealToggle:(id)sender;
|
||||
- (void)rightRevealToggle:(id)sender; // <-- simetric implementation of the above for the rightViewController
|
||||
|
||||
// The following method will provide a panGestureRecognizer suitable to be added to any view
|
||||
// in order to perform usual drag and swipe gestures to reveal the rear views. This is usually added to the top bar
|
||||
// of a front controller, but it can be added to your frontViewController view or to the reveal controller view to provide full screen panning.
|
||||
// The provided panGestureRecognizer is initially added to the reveal controller's front container view, so you can dissable
|
||||
// user interactions on your controllers views and the recognizer will continue working.
|
||||
- (UIPanGestureRecognizer*)panGestureRecognizer;
|
||||
|
||||
// The following method will provide a tapGestureRecognizer suitable to be added to any view on the frontController
|
||||
// for concealing the rear views. By default no tap recognizer is created or added to any view, however if you call this method after
|
||||
// the controller's view has been loaded the recognizer is added to the reveal controller's front container view.
|
||||
// Thus, you can disable user interactions on your frontViewController view without affecting the tap recognizer.
|
||||
- (UITapGestureRecognizer*)tapGestureRecognizer;
|
||||
|
||||
// The following properties are provided for further customization, they are set to default values on initialization,
|
||||
// you should not generally have to set them
|
||||
|
||||
// Defines how much of the rear or right view is shown, default is 260. A negative value indicates that the reveal width should be
|
||||
// computed by substracting the full front view width, so the revealed frontView width is constant.
|
||||
@property (assign, nonatomic) CGFloat rearViewRevealWidth;
|
||||
@property (assign, nonatomic) CGFloat rightViewRevealWidth; // <-- simetric implementation of the above for the rightViewController
|
||||
|
||||
// Defines how much of an overdraw can occur when dragging further than 'rearViewRevealWidth', default is 60.
|
||||
@property (assign, nonatomic) CGFloat rearViewRevealOverdraw;
|
||||
@property (assign, nonatomic) CGFloat rightViewRevealOverdraw; // <-- simetric implementation of the above for the rightViewController
|
||||
|
||||
// Defines how much displacement is applied to the rear view when animating or dragging the front view, default is 40.
|
||||
@property (assign, nonatomic) CGFloat rearViewRevealDisplacement;
|
||||
@property (assign, nonatomic) CGFloat rightViewRevealDisplacement;
|
||||
|
||||
// Defines a width on the border of the view attached to the panGesturRecognizer where the gesture is allowed,
|
||||
// default is 0 which means no restriction.
|
||||
@property (assign, nonatomic) CGFloat draggableBorderWidth;
|
||||
|
||||
// If YES (the default) the controller will bounce to the Left position when dragging further than 'rearViewRevealWidth'
|
||||
@property (assign, nonatomic) BOOL bounceBackOnOverdraw;
|
||||
@property (assign, nonatomic) BOOL bounceBackOnLeftOverdraw;
|
||||
|
||||
// If YES (default is NO) the controller will allow permanent dragging up to the rightMostPosition
|
||||
@property (assign, nonatomic) BOOL stableDragOnOverdraw;
|
||||
@property (assign, nonatomic) BOOL stableDragOnLeftOverdraw; // <-- simetric implementation of the above for the rightViewController
|
||||
|
||||
// If YES (default is NO) the front view controller will be ofsseted vertically by the height of a navigation bar.
|
||||
// Use this on iOS7 when you add an instance of RevealViewController as a child of a UINavigationController (or another SWRevealViewController)
|
||||
// and you want the front view controller to be presented below the navigation bar of its UINavigationController grand parent .
|
||||
// The rearViewController will still appear full size and blurred behind the navigation bar of its UINavigationController grand parent
|
||||
@property (assign, nonatomic) BOOL presentFrontViewHierarchically;
|
||||
|
||||
// Velocity required for the controller to toggle its state based on a swipe movement, default is 300
|
||||
@property (assign, nonatomic) CGFloat quickFlickVelocity;
|
||||
|
||||
// Default duration for the revealToggle animation, default is 0.25
|
||||
@property (assign, nonatomic) NSTimeInterval toggleAnimationDuration;
|
||||
|
||||
// Defines the radius of the front view's shadow, default is 2.5f
|
||||
@property (assign, nonatomic) CGFloat frontViewShadowRadius;
|
||||
|
||||
// Defines the radius of the front view's shadow offset default is {0.0f,2.5f}
|
||||
@property (assign, nonatomic) CGSize frontViewShadowOffset;
|
||||
|
||||
//Defines the front view's shadow opacity, default is 1.0f
|
||||
@property (assign, nonatomic) CGFloat frontViewShadowOpacity;
|
||||
|
||||
// The class properly handles all the relevant calls to appearance methods on the contained controllers.
|
||||
// Moreover you can assign a delegate to let the class inform you on positions and animation activity.
|
||||
|
||||
// Delegate
|
||||
@property (weak, nonatomic) id<SWRevealViewControllerDelegate> delegate;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - SWRevealViewControllerDelegate Protocol
|
||||
|
||||
@protocol SWRevealViewControllerDelegate<NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
// The following delegate methods will be called before and after the front view moves to a position
|
||||
- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position;
|
||||
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position;
|
||||
|
||||
// This will be called inside the reveal animation, thus you can use it to place your own code that will be animated in sync
|
||||
- (void)revealController:(SWRevealViewController *)revealController animateToPosition:(FrontViewPosition)position;
|
||||
|
||||
// Implement this to return NO when you want the pan gesture recognizer to be ignored
|
||||
- (BOOL)revealControllerPanGestureShouldBegin:(SWRevealViewController *)revealController;
|
||||
|
||||
// Implement this to return NO when you want the tap gesture recognizer to be ignored
|
||||
- (BOOL)revealControllerTapGestureShouldBegin:(SWRevealViewController *)revealController;
|
||||
|
||||
// Called when the gestureRecognizer began and ended
|
||||
- (void)revealControllerPanGestureBegan:(SWRevealViewController *)revealController;
|
||||
- (void)revealControllerPanGestureEnded:(SWRevealViewController *)revealController;
|
||||
|
||||
// The following methods provide a means to track the evolution of the gesture recognizer.
|
||||
// The 'location' parameter is the X origin coordinate of the front view as the user drags it
|
||||
// The 'progress' parameter is a positive value from 0 to 1 indicating the front view location relative to the
|
||||
// rearRevealWidth or rightRevealWidth. 1 is fully revealed, dragging ocurring in the overDraw region will result in values above 1.
|
||||
- (void)revealController:(SWRevealViewController *)revealController panGestureBeganFromLocation:(CGFloat)location progress:(CGFloat)progress;
|
||||
- (void)revealController:(SWRevealViewController *)revealController panGestureMovedToLocation:(CGFloat)location progress:(CGFloat)progress;
|
||||
- (void)revealController:(SWRevealViewController *)revealController panGestureEndedToLocation:(CGFloat)location progress:(CGFloat)progress;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - UIViewController(SWRevealViewController) Category
|
||||
|
||||
// We add a category of UIViewController to let childViewControllers easily access their parent SWRevealViewController
|
||||
@interface UIViewController(SWRevealViewController)
|
||||
|
||||
- (SWRevealViewController*)revealViewController;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// This will allow the class to be defined on a storyboard
|
||||
#pragma mark - SWRevealViewControllerSegue
|
||||
|
||||
@interface SWRevealViewControllerSegue : UIStoryboardSegue
|
||||
|
||||
@property (strong) void(^performBlock)( SWRevealViewControllerSegue* segue, UIViewController* svc, UIViewController* dvc );
|
||||
|
||||
@end
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// SettingsViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SettingsViewController : UITableViewController
|
||||
@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
|
||||
|
||||
@end
|
|
@ -1,55 +0,0 @@
|
|||
//
|
||||
// SettingsViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "SettingsViewController.h"
|
||||
#import "SWRevealViewController.h"
|
||||
|
||||
@interface SettingsViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation SettingsViewController
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
self.title = @"Settings";
|
||||
|
||||
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
|
||||
_sidebarButton.target = self.revealViewController;
|
||||
_sidebarButton.action = @selector(revealToggle:);
|
||||
|
||||
// Set the gesture
|
||||
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
|
||||
// Uncomment the following line to preserve selection between presentations.
|
||||
// self.clearsSelectionOnViewWillAppear = NO;
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
// TODO: view controller logic
|
||||
|
||||
@end
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// Shader.fsh
|
||||
// emulator
|
||||
//
|
||||
// Created by Lounge Katt on 2/6/14.
|
||||
// Copyright (c) 2014 Lounge Katt. All rights reserved.
|
||||
//
|
||||
|
||||
varying lowp vec4 colorVarying;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = colorVarying;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// Shader.vsh
|
||||
// emulator
|
||||
//
|
||||
// Created by Lounge Katt on 2/6/14.
|
||||
// Copyright (c) 2014 Lounge Katt. All rights reserved.
|
||||
//
|
||||
|
||||
attribute vec4 position;
|
||||
attribute vec3 normal;
|
||||
|
||||
varying lowp vec4 colorVarying;
|
||||
|
||||
uniform mat4 modelViewProjectionMatrix;
|
||||
uniform mat3 normalMatrix;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 eyeNormal = normalize(normalMatrix * normal);
|
||||
vec3 lightPosition = vec3(0.0, 0.0, 1.0);
|
||||
vec4 diffuseColor = vec4(0.4, 0.4, 1.0, 1.0);
|
||||
|
||||
float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition)));
|
||||
|
||||
colorVarying = diffuseColor * nDotVP;
|
||||
|
||||
gl_Position = modelViewProjectionMatrix * position;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
//
|
||||
// SideDrawerViewController.h
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface SideDrawerViewController : UITableViewController
|
||||
|
||||
@end
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
// SideDrawerViewController.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Karen Tsai on 2014/3/5.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import "SideDrawerViewController.h"
|
||||
#import "SWRevealViewController.h"
|
||||
|
||||
@interface SideDrawerViewController ()
|
||||
|
||||
@end
|
||||
|
||||
@implementation SideDrawerViewController {
|
||||
NSArray *menuItems;
|
||||
}
|
||||
|
||||
- (id)initWithStyle:(UITableViewStyle)style
|
||||
{
|
||||
self = [super initWithStyle:style];
|
||||
if (self) {
|
||||
// Custom initialization
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
menuItems = @[@"browser", @"settings", @"paths", @"input", @"about"];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
|
||||
{
|
||||
// Return the number of sections.
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
// Return the number of rows in the section.
|
||||
return [menuItems count];
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender
|
||||
{
|
||||
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
|
||||
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
|
||||
destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];
|
||||
|
||||
if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
|
||||
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
|
||||
|
||||
swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
|
||||
|
||||
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
|
||||
[navController setViewControllers: @[dvc] animated: NO ];
|
||||
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>FlycastStoryboard</string>
|
||||
<key>UIMainStoryboardFile~ipad</key>
|
||||
<string>MainStoryboard</string>
|
||||
<key>UIPrerenderedIcon</key>
|
||||
<true/>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,14 @@
|
|||
//
|
||||
// Copyright (c) 2015 reicast. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef flycast_ios_flycast_ios_Prefix_pch
|
||||
#define flycast_ios_flycast_ios_Prefix_pch
|
||||
|
||||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- https://siguza.github.io/psychicpaper/ -->
|
||||
<!---><!-->
|
||||
<key>platform-application</key>
|
||||
<true/>
|
||||
<key>com.apple.private.security.no-container</key>
|
||||
<true/>
|
||||
<key>task_for_pid-allow</key>
|
||||
<true/>
|
||||
<key>com.apple.system-task-ports</key>
|
||||
<true/>
|
||||
<!-- -->
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,27 +1,12 @@
|
|||
//
|
||||
// ios_main.m
|
||||
// emulator
|
||||
//
|
||||
// Created by admin on 12/17/14.
|
||||
// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <poll.h>
|
||||
#include <termios.h>
|
||||
//#include <curses.h>
|
||||
#include <fcntl.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdarg.h>
|
||||
#include <signal.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include "hw/sh4/dyna/blockmanager.h"
|
||||
#include <unistd.h>
|
||||
#include "hw/maple/maple_cfg.h"
|
||||
#include "emulator.h"
|
||||
#include "log/LogManager.h"
|
||||
#include "rend/gui.h"
|
||||
|
||||
int darw_printf(const char* text,...)
|
||||
{
|
||||
|
@ -37,54 +22,36 @@ int darw_printf(const char* text,...)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void common_linux_setup();
|
||||
int dc_init(int argc, char* argv[]);
|
||||
void dc_run();
|
||||
|
||||
extern "C" int reicast_main(int argc, char* argv[])
|
||||
{
|
||||
//if (argc==2)
|
||||
//ndcid=atoi(argv[1]);
|
||||
|
||||
string homedir = [ [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0] path] UTF8String];
|
||||
set_user_config_dir(homedir);
|
||||
set_user_data_dir(homedir);
|
||||
|
||||
freopen( (homedir + "/log.txt").c_str(), "wb", stdout);
|
||||
|
||||
printf("Config dir is: %s\n", get_writable_config_path("/").c_str());
|
||||
printf("Data dir is: %s\n", get_writable_data_path("/").c_str());
|
||||
|
||||
common_linux_setup();
|
||||
|
||||
dc_init(argc,argv);
|
||||
|
||||
dc_run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void os_DoEvents() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
u32 os_Push(void*, u32, bool) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void os_SetWindowText(const char* t) {
|
||||
puts(t);
|
||||
}
|
||||
|
||||
void os_CreateWindow() {
|
||||
|
||||
}
|
||||
|
||||
void os_SetupInput() {
|
||||
}
|
||||
|
||||
void UpdateInputState() {
|
||||
|
||||
}
|
||||
|
||||
std::string os_Locale(){
|
||||
return [[[NSLocale preferredLanguages] objectAtIndex:0] UTF8String];
|
||||
}
|
||||
|
||||
std::string os_PrecomposedString(std::string string){
|
||||
return [[[NSString stringWithUTF8String:string.c_str()] precomposedStringWithCanonicalMapping] UTF8String];
|
||||
}
|
||||
|
||||
extern "C" void emu_dc_term(void)
|
||||
{
|
||||
if (dc_is_running())
|
||||
dc_exit();
|
||||
dc_term();
|
||||
LogManager::Shutdown();
|
||||
}
|
||||
|
||||
extern "C" void emu_gui_open(void)
|
||||
{
|
||||
if (!gui_is_open())
|
||||
gui_open_settings();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "input/gamepad_device.h"
|
||||
|
||||
class IOSMouse : public SystemMouse
|
||||
{
|
||||
public:
|
||||
IOSMouse() : SystemMouse("iOS")
|
||||
{
|
||||
_unique_id = "ios_mouse";
|
||||
loadMapping();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1,7 +1,4 @@
|
|||
//
|
||||
// main.m
|
||||
// emulator
|
||||
//
|
||||
// Created by Lounge Katt on 2/6/14.
|
||||
// Copyright (c) 2014 Lounge Katt. All rights reserved.
|
||||
//
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -31,14 +31,14 @@
|
|||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@2x.png",
|
||||
"size" : "60x60",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-180.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
|
@ -79,7 +79,7 @@
|
|||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76@2x.png",
|
||||
"filename" : "Icon-152.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB |
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "landscape",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "ipad",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "landscape",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
21
shell/apple/emulator-ios/reicast-ios/Images.xcassets/flycast.imageset/Contents.json
vendored
Normal file
21
shell/apple/emulator-ios/reicast-ios/Images.xcassets/flycast.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "flycast.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
shell/apple/emulator-ios/reicast-ios/Images.xcassets/flycast.imageset/flycast.png
vendored
Normal file
BIN
shell/apple/emulator-ios/reicast-ios/Images.xcassets/flycast.imageset/flycast.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
Loading…
Reference in New Issue