From be7d432f6d8ad3b0ba38b792023476ddb32d5b13 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Thu, 28 Sep 2023 18:26:39 +0300 Subject: [PATCH] Adding some logic to Objective-C++ wrapper --- NesKit/NesLayer.h | 24 +++++++++++++++++++++ NesKit/NesLayer.m | 27 ++++++++++++++++++++++++ NesKit/NesSystem.h | 5 +++++ NesKit/NesSystem.mm | 51 ++++++++++++++++++++++++++++++++++++++++++++- Package.swift | 2 +- 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 NesKit/NesLayer.h create mode 100644 NesKit/NesLayer.m diff --git a/NesKit/NesLayer.h b/NesKit/NesLayer.h new file mode 100644 index 0000000..b96dbd1 --- /dev/null +++ b/NesKit/NesLayer.h @@ -0,0 +1,24 @@ +// +// NesLayer.h +// +// +// Created by Мустафаев Селим Мустафаевич on 28.09.2023. +// + + + +#import +#import +#import "NesSystem.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NesLayer : CALayer + +@property NesSystem* system; + +- (instancetype)initWithNesSystem:(NesSystem*)system; + +@end + +NS_ASSUME_NONNULL_END diff --git a/NesKit/NesLayer.m b/NesKit/NesLayer.m new file mode 100644 index 0000000..e110c90 --- /dev/null +++ b/NesKit/NesLayer.m @@ -0,0 +1,27 @@ +// +// NesLayer.m +// +// +// Created by Мустафаев Селим Мустафаевич on 28.09.2023. +// + +#import "NesLayer.h" + +@implementation NesLayer { + NSTimer* _timer; +} + +- (instancetype)initWithNesSystem:(NesSystem*)system { + if(self = [super init]) { + self.system = system; + _timer = [NSTimer timerWithTimeInterval:1.0/60.0 repeats:YES block:^(NSTimer * _Nonnull timer) { + if(self.system) { + self.contents = self.system.frame; + [self.system stepToNextFrame]; + } + }]; + } + return self; +} + +@end diff --git a/NesKit/NesSystem.h b/NesKit/NesSystem.h index 73e0f99..3a025d9 100644 --- a/NesKit/NesSystem.h +++ b/NesKit/NesSystem.h @@ -6,12 +6,17 @@ // #import +#import NS_ASSUME_NONNULL_BEGIN @interface NesSystem : NSObject +@property CGImageRef frame; + - (instancetype)init; +- (void)runRom:(NSString*)path; +- (void)stepToNextFrame; @end diff --git a/NesKit/NesSystem.mm b/NesKit/NesSystem.mm index 88a6bb9..e47b82e 100644 --- a/NesKit/NesSystem.mm +++ b/NesKit/NesSystem.mm @@ -1,5 +1,5 @@ // -// NesSystem.m +// NesSystem.mm // // // Created by Selim Mustafaev on 27.09.2023. @@ -16,13 +16,62 @@ @implementation NesSystem { std::unique_ptr _system; + NSCondition* _condition; + BOOL _runEmulation; } - (instancetype)init { if(self = [super init]) { _system = std::make_unique(); + _condition = [NSCondition new]; + _runEmulation = YES; + + size_t frameBufferSize = nes::Ppu::SCREEN_WIDTH * nes::Ppu::SCREEN_HEIGHT * sizeof(nes::Pixel); + + _system->setNewFrameCallback([&](auto frameBuffer) { + _runEmulation = NO; + + CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, (void*)frameBuffer, frameBufferSize, NULL); + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); + _frame = CGImageCreate(nes::Ppu::SCREEN_WIDTH, + nes::Ppu::SCREEN_HEIGHT, + 8, + sizeof(nes::Pixel)*8, + nes::Ppu::SCREEN_WIDTH * sizeof(nes::Pixel), + colorspace, + kCGBitmapByteOrderDefault, + dataProvider, + NULL, + true, + kCGRenderingIntentDefault); + CGDataProviderRelease(dataProvider); + CGColorSpaceRelease(colorspace); + }); } return self; } +- (void)runRom:(NSURL*)url { + _system->insertCartridge([url fileSystemRepresentation]); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [_condition lock]; + while (!_runEmulation) { + [_condition wait]; + } + + while(_runEmulation) { + _system->tick(); + } + + [_condition unlock]; + }); +} + +- (void)stepToNextFrame { + [_condition lock]; + _runEmulation = YES; + [_condition signal]; + [_condition unlock]; +} + @end diff --git a/Package.swift b/Package.swift index aec3978..1cc23d0 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 5.8 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription