diff --git a/core/deps/miniupnpc/connecthostport.c b/core/deps/miniupnpc/connecthostport.c index 79f832b8d..fcfc8638e 100644 --- a/core/deps/miniupnpc/connecthostport.c +++ b/core/deps/miniupnpc/connecthostport.c @@ -25,7 +25,7 @@ #else /* #ifdef _WIN32 */ #include #include -#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT +#if defined(MINIUPNPC_SET_SOCKET_TIMEOUT) || defined(__APPLE__) #include #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ #include diff --git a/core/hw/aica/dsp_arm64.cpp b/core/hw/aica/dsp_arm64.cpp index 0faaf3012..23d5a3805 100644 --- a/core/hw/aica/dsp_arm64.cpp +++ b/core/hw/aica/dsp_arm64.cpp @@ -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: diff --git a/core/hw/arm7/arm7_rec.cpp b/core/hw/arm7/arm7_rec.cpp index 744536b7a..e25a61a22 100644 --- a/core/hw/arm7/arm7_rec.cpp +++ b/core/hw/arm7/arm7_rec.cpp @@ -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"))); diff --git a/core/hw/arm7/arm7_rec_arm64.cpp b/core/hw/arm7/arm7_rec_arm64.cpp index e39a6ae7d..15fee8f6b 100644 --- a/core/hw/arm7/arm7_rec_arm64.cpp +++ b/core/hw/arm7/arm7_rec_arm64.cpp @@ -28,6 +28,7 @@ using namespace vixl::aarch64; //#include #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 { Arm7Compiler& assembler; diff --git a/core/hw/sh4/dyna/driver.cpp b/core/hw/sh4/dyna/driver.cpp index 9a0bd213d..0d67bf1e3 100644 --- a/core/hw/sh4/dyna/driver.cpp +++ b/core/hw/sh4/dyna/driver.cpp @@ -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] diff --git a/core/linux/common.cpp b/core/linux/common.cpp index f57714929..24fac641e 100644 --- a/core/linux/common.cpp +++ b/core/linux/common.cpp @@ -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(); diff --git a/core/linux/posix_vmem.cpp b/core/linux/posix_vmem.cpp index 69f32fcac..7977060a3 100644 --- a/core/linux/posix_vmem.cpp +++ b/core/linux/posix_vmem.cpp @@ -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() diff --git a/core/oslib/oslib.h b/core/oslib/oslib.h index 939092981..46cb1e033 100644 --- a/core/oslib/oslib.h +++ b/core/oslib/oslib.h @@ -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) { diff --git a/core/rec-ARM64/rec_arm64.cpp b/core/rec-ARM64/rec_arm64.cpp index 045be856c..608cd553a 100644 --- a/core/rec-ARM64/rec_arm64.cpp +++ b/core/rec-ARM64/rec_arm64.cpp @@ -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"); diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 54ba46b9e..a14715e66 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -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; diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index d70e97237..1cfb91247 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -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& 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; diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 15cbddf8b..3deace7b3 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -120,6 +120,7 @@ struct gl_ctx GLuint fbo; int width; int height; + GLuint origFbo; } ofbo; const char *gl_version; diff --git a/core/rend/gles/gltex.cpp b/core/rend/gles/gltex.cpp index ad42c0b9b..e6b5f346b 100644 --- a/core/rend/gles/gltex.cpp +++ b/core/rend/gles/gltex.cpp @@ -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 diff --git a/core/rend/gles/imgui_impl_opengl3.cpp b/core/rend/gles/imgui_impl_opengl3.cpp index 12ba3e62d..6422eed97 100644 --- a/core/rend/gles/imgui_impl_opengl3.cpp +++ b/core/rend/gles/imgui_impl_opengl3.cpp @@ -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); diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 2f7f877ed..7b5c0f7f8 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -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 diff --git a/core/stdclass.h b/core/stdclass.h index d47265818..81daed3be 100644 --- a/core/stdclass.h +++ b/core/stdclass.h @@ -10,15 +10,12 @@ #ifdef __ANDROID__ #include #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: diff --git a/core/types.h b/core/types.h index a7a73af23..c06ec0b3b 100644 --- a/core/types.h +++ b/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 diff --git a/core/wsi/osx.h b/core/wsi/osx.h index ff341c000..8ca1c7aa5 100644 --- a/core/wsi/osx.h +++ b/core/wsi/osx.h @@ -20,9 +20,9 @@ */ #pragma once #if defined(__APPLE__) -#if defined(TARGET_IPHONE) //apple-specific ogles2 headers -#include -#include +#if defined(TARGET_IPHONE) //apple-specific ogles3 headers +#include +#include #else #include #endif diff --git a/shell/apple/emulator-ios/emulator/AboutViewController.h b/shell/apple/emulator-ios/emulator/AboutViewController.h deleted file mode 100644 index b38c04f18..000000000 --- a/shell/apple/emulator-ios/emulator/AboutViewController.h +++ /dev/null @@ -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 - -@interface AboutViewController : UITableViewController { - IBOutlet UILabel *versionLabel; -} -@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton; - -@end diff --git a/shell/apple/emulator-ios/emulator/AboutViewController.m b/shell/apple/emulator-ios/emulator/AboutViewController.m deleted file mode 100644 index 89a53f2c7..000000000 --- a/shell/apple/emulator-ios/emulator/AboutViewController.m +++ /dev/null @@ -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 diff --git a/shell/apple/emulator-ios/emulator/AppDelegate.h b/shell/apple/emulator-ios/emulator/AppDelegate.h index 7e1f307ca..1e6526689 100644 --- a/shell/apple/emulator-ios/emulator/AppDelegate.h +++ b/shell/apple/emulator-ios/emulator/AppDelegate.h @@ -1,7 +1,4 @@ // -// AppDelegate.h -// emulator -// // Created by Lounge Katt on 2/6/14. // Copyright (c) 2014 Lounge Katt. All rights reserved. // diff --git a/shell/apple/emulator-ios/emulator/AppDelegate.m b/shell/apple/emulator-ios/emulator/AppDelegate.m index 5207e7f4f..0a79193e9 100644 --- a/shell/apple/emulator-ios/emulator/AppDelegate.m +++ b/shell/apple/emulator-ios/emulator/AppDelegate.m @@ -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 diff --git a/shell/apple/emulator-ios/emulator/BrowserTableViewController.h b/shell/apple/emulator-ios/emulator/BrowserTableViewController.h deleted file mode 100644 index 5df255029..000000000 --- a/shell/apple/emulator-ios/emulator/BrowserTableViewController.h +++ /dev/null @@ -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 - -@interface BrowserTableViewController : UITableViewController { - NSArray *games; -} -@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton; - -@end diff --git a/shell/apple/emulator-ios/emulator/BrowserTableViewController.m b/shell/apple/emulator-ios/emulator/BrowserTableViewController.m deleted file mode 100644 index 245b8f759..000000000 --- a/shell/apple/emulator-ios/emulator/BrowserTableViewController.m +++ /dev/null @@ -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 diff --git a/shell/apple/emulator-ios/emulator/CloudVMUViewController.h b/shell/apple/emulator-ios/emulator/CloudVMUViewController.h deleted file mode 100644 index aaed41aaa..000000000 --- a/shell/apple/emulator-ios/emulator/CloudVMUViewController.h +++ /dev/null @@ -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 - -@interface CloudVMUViewController : UITableViewController -@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton; - -@end diff --git a/shell/apple/emulator-ios/emulator/CloudVMUViewController.m b/shell/apple/emulator-ios/emulator/CloudVMUViewController.m deleted file mode 100644 index 418ee4cd4..000000000 --- a/shell/apple/emulator-ios/emulator/CloudVMUViewController.m +++ /dev/null @@ -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 diff --git a/shell/apple/emulator-ios/emulator/DiskViewCell.h b/shell/apple/emulator-ios/emulator/DiskViewCell.h deleted file mode 100644 index 208041a80..000000000 --- a/shell/apple/emulator-ios/emulator/DiskViewCell.h +++ /dev/null @@ -1,8 +0,0 @@ -#import - -@interface DiskViewCell : UITableViewCell - -@property (nonatomic, retain) IBOutlet UIImageView *diskImage; -@property (nonatomic, retain) IBOutlet UILabel *nameLabel; - -@end diff --git a/shell/apple/emulator-ios/emulator/DiskViewCell.m b/shell/apple/emulator-ios/emulator/DiskViewCell.m deleted file mode 100644 index c199b6ac1..000000000 --- a/shell/apple/emulator-ios/emulator/DiskViewCell.m +++ /dev/null @@ -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 diff --git a/shell/apple/emulator-ios/emulator/EmulatorView.h b/shell/apple/emulator-ios/emulator/EmulatorView.h index 534129088..c30a4cd95 100644 --- a/shell/apple/emulator-ios/emulator/EmulatorView.h +++ b/shell/apple/emulator-ios/emulator/EmulatorView.h @@ -1,41 +1,17 @@ // -// EmulatorView.h -// emulator -// -// Created by admin on 1/18/15. // Copyright (c) 2015 reicast. All rights reserved. // #import +#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) - diff --git a/shell/apple/emulator-ios/emulator/EmulatorView.mm b/shell/apple/emulator-ios/emulator/EmulatorView.mm index 13ae6ed7a..6fae8cde9 100644 --- a/shell/apple/emulator-ios/emulator/EmulatorView.mm +++ b/shell/apple/emulator-ios/emulator/EmulatorView.mm @@ -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 *)touches withEvent:(UIEvent *)event; +{ + UITouch *touch = [touches anyObject]; + [self touchLocation:touch]; + if (gui_is_open()) + _mouse->setButton(Mouse::LEFT_BUTTON, true); +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; +{ + UITouch *touch = [touches anyObject]; + [self touchLocation:touch]; + if (gui_is_open()) + _mouse->setButton(Mouse::LEFT_BUTTON, false); +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +{ + UITouch *touch = [touches anyObject]; + [self touchLocation:touch]; +} + @end diff --git a/shell/apple/emulator-ios/emulator/EmulatorViewController.mm b/shell/apple/emulator-ios/emulator/EmulatorViewController.mm deleted file mode 100644 index 908cae464..000000000 --- a/shell/apple/emulator-ios/emulator/EmulatorViewController.mm +++ /dev/null @@ -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 -#import -#import - -#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 - -#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 -#include -#include - -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 diff --git a/shell/apple/emulator-ios/emulator/FlycastStoryboard.storyboard b/shell/apple/emulator-ios/emulator/FlycastStoryboard.storyboard new file mode 100644 index 000000000..40b3a9c7d --- /dev/null +++ b/shell/apple/emulator-ios/emulator/FlycastStoryboard.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shell/apple/emulator-ios/emulator/EmulatorViewController.h b/shell/apple/emulator-ios/emulator/FlycastViewController.h similarity index 57% rename from shell/apple/emulator-ios/emulator/EmulatorViewController.h rename to shell/apple/emulator-ios/emulator/FlycastViewController.h index 9adc29517..584d963b3 100644 --- a/shell/apple/emulator-ios/emulator/EmulatorViewController.h +++ b/shell/apple/emulator-ios/emulator/FlycastViewController.h @@ -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 #import @@ -13,15 +6,14 @@ #import "PadViewController.h" #import "EmulatorView.h" -@interface EmulatorViewController : GLKViewController +@interface FlycastViewController : GLKViewController -@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 diff --git a/shell/apple/emulator-ios/emulator/FlycastViewController.mm b/shell/apple/emulator-ios/emulator/FlycastViewController.mm new file mode 100644 index 000000000..572aec978 --- /dev/null +++ b/shell/apple/emulator-ios/emulator/FlycastViewController.mm @@ -0,0 +1,423 @@ +// +// Copyright (c) 2014 Karen Tsai (angelXwind). All rights reserved. +// +#import "FlycastViewController.h" + +#import +#import +#import + +#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 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 +#include +#include + +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(); + GamepadDevice::Register(mouse); +} diff --git a/shell/apple/emulator-ios/emulator/InputViewController.h b/shell/apple/emulator-ios/emulator/InputViewController.h deleted file mode 100644 index 7f7547f4a..000000000 --- a/shell/apple/emulator-ios/emulator/InputViewController.h +++ /dev/null @@ -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 - -@interface InputViewController : UITableViewController -@property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton; - -@end diff --git a/shell/apple/emulator-ios/emulator/InputViewController.m b/shell/apple/emulator-ios/emulator/InputViewController.m deleted file mode 100644 index 00e7a1d53..000000000 --- a/shell/apple/emulator-ios/emulator/InputViewController.m +++ /dev/null @@ -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 diff --git a/shell/apple/emulator-ios/emulator/LaunchScreen.storyboard b/shell/apple/emulator-ios/emulator/LaunchScreen.storyboard new file mode 100644 index 000000000..33e2cfcde --- /dev/null +++ b/shell/apple/emulator-ios/emulator/LaunchScreen.storyboard @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shell/apple/emulator-ios/emulator/MainStoryboard.storyboard b/shell/apple/emulator-ios/emulator/MainStoryboard.storyboard deleted file mode 100644 index 44aacd968..000000000 --- a/shell/apple/emulator-ios/emulator/MainStoryboard.storyboard +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/shell/apple/emulator-ios/emulator/PadViewController.h b/shell/apple/emulator-ios/emulator/PadViewController.h index 4eec618d7..d304872f7 100644 --- a/shell/apple/emulator-ios/emulator/PadViewController.h +++ b/shell/apple/emulator-ios/emulator/PadViewController.h @@ -1,7 +1,4 @@ // -// PadViewController.h -// reicast-ios -// // Created by Lounge Katt on 8/25/15. // Copyright (c) 2015 reicast. All rights reserved. // diff --git a/shell/apple/emulator-ios/emulator/PadViewController.mm b/shell/apple/emulator-ios/emulator/PadViewController.mm new file mode 100644 index 000000000..27532aab2 --- /dev/null +++ b/shell/apple/emulator-ios/emulator/PadViewController.mm @@ -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 diff --git a/shell/apple/emulator-ios/emulator/PadViewController.xib b/shell/apple/emulator-ios/emulator/PadViewController.xib index 6dd66febc..ba2e69312 100644 --- a/shell/apple/emulator-ios/emulator/PadViewController.xib +++ b/shell/apple/emulator-ios/emulator/PadViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -24,7 +24,7 @@ - + @@ -32,7 +32,7 @@ - - - - - - -