4#import <Foundation/Foundation.h>
12#import <Metal/Metal.h>
13#import <MetalKit/MetalKit.h>
15#import <MobileCoreServices/MobileCoreServices.h>
16#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
28#include "imgui/backends/imgui_impl_metal.h"
29#include "imgui/imgui.h"
37- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
38 bundle:(nullable NSBundle *)nibBundleOrNil {
39 self = [
super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
41 _device = MTLCreateSystemDefaultDevice();
42 _commandQueue = [
_device newCommandQueue];
45 NSLog(
@"Metal is not supported");
53 ImGui::CreateContext();
54 ImGuiIO &io = ImGui::GetIO();
56 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
57 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
62 SDL_iOSSetEventPump(SDL_TRUE);
63 int argc = NSProcessInfo.processInfo.arguments.count;
64 char **argv =
new char *[
argc];
65 for (
int i = 0; i < argc; i++) {
66 NSString *arg = NSProcessInfo.processInfo.arguments[
i];
67 const char *cString = [
arg UTF8String];
68 argv[
i] =
new char[
strlen(cString) + 1];
69 strcpy(argv[i], cString);
72 std::string rom_filename =
"";
74 rom_filename = argv[1];
76 SDL_iOSSetEventPump(SDL_FALSE);
79 SDL_SetHint(SDL_HINT_IME_SHOW_UI,
"1");
80 if (!_controller->CreateWindow().ok()) {
81 printf(
"Error creating window: %s\n", SDL_GetError());
84 if (!_controller->CreateRenderer().ok()) {
85 printf(
"Error creating renderer: %s\n", SDL_GetError());
89 ImGui_ImplSDL2_InitForSDLRenderer(_controller->window(),
93 if (!LoadPackageFonts().ok()) {
96 _controller->Initialize(
"");
97 _controller->set_active(
true);
99 _hoverGestureRecognizer =
101 [
self.
view addGestureRecognizer:_hoverGestureRecognizer];
104 action:@selector(HandlePinch:)];
105 [
self.
view addGestureRecognizer:_pinchRecognizer];
107 _longPressRecognizer =
109 [
self.
view addGestureRecognizer:_longPressRecognizer];
112 action:@selector(HandleSwipe:)];
113 _swipeRecognizer.direction =
114 UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft;
115 [
self.
view addGestureRecognizer:_swipeRecognizer];
119- (MTKView *)mtkView {
120 return (MTKView *)self.view;
124 self.view = [[MTKView alloc] initWithFrame:CGRectMake(0, 0, 1200, 720)];
130 self.mtkView.device = self.device;
131 self.mtkView.delegate = self;
134 ImGui_ImplOSX_Init(self.view);
135 [NSApp activateIgnoringOtherApps:YES];
139- (void)drawInMTKView:(MTKView *)view {
140 ImGuiIO &io = ImGui::GetIO();
141 io.DisplaySize.x = view.bounds.size.width;
142 io.DisplaySize.y = view.bounds.size.height;
145 CGFloat framebufferScale =
146 view.window.screen.backingScaleFactor ?: NSScreen.mainScreen.backingScaleFactor;
148 CGFloat framebufferScale = view.window.screen.scale ?: UIScreen.mainScreen.scale;
150 io.DisplayFramebufferScale = ImVec2(framebufferScale, framebufferScale);
152 ImGui_ImplSDLRenderer2_NewFrame();
153 ImGui_ImplSDL2_NewFrame();
155 ImGui_ImplOSX_NewFrame(view);
159 ImGui::SetNextWindowPos(ImVec2(0, 0));
160 ImVec2 dimensions(io.DisplaySize.x, io.DisplaySize.y);
161 ImGui::SetNextWindowSize(dimensions, ImGuiCond_Always);
162 if (ImGui::Begin(
"##YazeMain",
nullptr,
163 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
164 ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
165 ImGuiWindowFlags_NoBringToFrontOnFocus)) {
166 auto controller_status = _controller->OnLoad();
167 if (!controller_status.ok()) {
172 _controller->DoRender();
175- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {
184- (void)viewWillAppear {
185 [
super viewWillAppear];
186 self.view.window.delegate = self;
189- (void)windowWillClose:(NSNotification *)notification {
190 ImGui_ImplMetal_Shutdown();
191 ImGui_ImplOSX_Shutdown();
192 ImGui::DestroyContext();
202- (void)UpdateIOWithTouchEvent:(UIEvent *)event {
203 UITouch *anyTouch =
event.allTouches.anyObject;
204 CGPoint touchLocation = [anyTouch locationInView:
self.view];
205 ImGuiIO &io = ImGui::GetIO();
206 io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
207 io.AddMousePosEvent(touchLocation.x, touchLocation.y);
209 BOOL hasActiveTouch = NO;
210 for (UITouch *touch in event.allTouches) {
211 if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled) {
212 hasActiveTouch = YES;
216 io.AddMouseButtonEvent(0, hasActiveTouch);
219- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
220 [
self UpdateIOWithTouchEvent:event];
222- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
223 [
self UpdateIOWithTouchEvent:event];
225- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
226 [
self UpdateIOWithTouchEvent:event];
228- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
229 [
self UpdateIOWithTouchEvent:event];
232- (void)HoverGesture:(UIHoverGestureRecognizer *)gesture {
233 ImGuiIO &io = ImGui::GetIO();
234 io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
236 UIGestureRecognizer *gestureRecognizer = (UIGestureRecognizer *)gesture;
237 if (gesture.zOffset < 0.50) {
238 io.AddMousePosEvent([gestureRecognizer locationInView:self.view].x,
239 [gestureRecognizer locationInView:self.view].y);
243- (void)HandlePinch:(UIPinchGestureRecognizer *)gesture {
244 ImGuiIO &io = ImGui::GetIO();
245 io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
246 io.AddMouseWheelEvent(0.0f, gesture.scale);
249- (void)HandleSwipe:(UISwipeGestureRecognizer *)gesture {
250 ImGuiIO &io = ImGui::GetIO();
251 io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
252 if (gesture.direction == UISwipeGestureRecognizerDirectionRight) {
253 io.AddMouseWheelEvent(1.0f, 0.0f);
254 }
else if (gesture.direction == UISwipeGestureRecognizerDirectionLeft) {
255 io.AddMouseWheelEvent(-1.0f, 0.0f);
259- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture {
260 ImGuiIO &io = ImGui::GetIO();
261 io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
262 io.AddMouseButtonEvent(1, gesture.state == UIGestureRecognizerStateBegan);
275@interface AppDelegate : NSObject <NSApplicationDelegate>
276@property(nonatomic, strong) NSWindow *window;
279@implementation AppDelegate
281- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
285- (instancetype)init {
286 if (self = [super init]) {
287 NSViewController *rootViewController = [[
AppViewController alloc] initWithNibName:nil
289 self.window = [[NSWindow alloc]
290 initWithContentRect:NSZeroRect
291 styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
292 NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable
293 backing:NSBackingStoreBuffered
295 self.window.contentViewController = rootViewController;
296 [
self.window center];
297 [
self.window makeKeyAndOrderFront:
self];
308- (BOOL)application:(UIApplication *)application
309 didFinishLaunchingWithOptions:(NSDictionary<UIApplicationLaunchOptionsKey,
id> *)launchOptions {
311 self.window = [[
UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
312 self.window.rootViewController = rootViewController;
313 [
self.
window makeKeyAndVisible];
317- (void)applicationWillTerminate:(UIApplication *)application {
318 ImGui_ImplSDLRenderer2_Shutdown();
319 ImGui_ImplSDL2_Shutdown();
320 ImGui::DestroyContext();
324- (void)PresentDocumentPickerWithCompletionHandler:
325 (
void (^)(NSString *selectedFile))completionHandler {
326 self.completionHandler = completionHandler;
328 NSArray *documentTypes = @[ [UTType typeWithIdentifier:@"org.halext.sfc"] ];
329 UIViewController *rootViewController = self.window.rootViewController;
331 [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:documentTypes];
332 _documentPicker.delegate = self;
333 _documentPicker.modalPresentationStyle = UIModalPresentationFormSheet;
335 [rootViewController presentViewController:_documentPicker animated:YES completion:nil];
338- (void)documentPicker:(UIDocumentPickerViewController *)controller
339 didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
340 NSURL *selectedFileURL = [urls firstObject];
342 if (self.completionHandler) {
343 if (selectedFileURL) {
344 self.completionHandler(selectedFileURL.path);
345 std::string fileName = std::string([selectedFileURL.path UTF8String]);
348 [selectedFileURL startAccessingSecurityScopedResource];
350 auto data = [NSData dataWithContentsOfURL:selectedFileURL];
352 uint8_t *bytes = (uint8_t *)[data bytes];
354 size_t size = [data length];
356 std::vector<uint8_t> rom_data;
357 rom_data.resize(size);
358 std::copy(bytes, bytes + size, rom_data.begin());
361 std::string filename = std::string([selectedFileURL.path UTF8String]);
363 [selectedFileURL stopAccessingSecurityScopedResource];
366 self.completionHandler(
@"");
369 self.completionHandler = nil;
370 [controller dismissViewControllerAnimated:YES completion:nil];
373- (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller {
374 if (self.completionHandler) {
375 self.completionHandler(
@"");
377 self.completionHandler = nil;
378 [controller dismissViewControllerAnimated:YES completion:nil];
390int main(
int argc,
const char *argv[]) {
return NSApplicationMain(argc, argv); }
393int main(
int argc,
char *argv[]) {
395 return UIApplicationMain(argc, argv, nil, NSStringFromClass([
AppDelegate class]));
static std::shared_ptr< Rom > shared_rom_
Main controller for the application.
static Renderer & GetInstance()
int main(int argc, char **argv)
#define PRINT_IF_ERROR(expression)