nes/NesKit/NesSystem.mm

86 lines
2.5 KiB
Plaintext

//
// NesSystem.mm
//
//
// Created by Selim Mustafaev on 27.09.2023.
//
#import "NesSystem.h"
#import <NesKitCpp.h>
#import <memory>
@interface NesSystem()
@end
@implementation NesSystem {
std::unique_ptr<nes::System> _system;
NSCondition* _condition;
BOOL _runEmulation;
}
- (instancetype)init {
if(self = [super init]) {
_system = std::make_unique<nes::System>();
_condition = [NSCondition new];
_runEmulation = YES;
size_t frameBufferSize = nes::Ppu::SCREEN_WIDTH * nes::Ppu::SCREEN_HEIGHT * sizeof(nes::Pixel);
_system->setNewFrameCallback([frameBufferSize, self](auto frameBuffer) {
_runEmulation = NO;
CGImageRelease(_frame);
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, (void*)frameBuffer, frameBufferSize, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef image = CGImageCreate(nes::Ppu::SCREEN_WIDTH,
nes::Ppu::SCREEN_HEIGHT,
8,
sizeof(nes::Pixel)*8,
nes::Ppu::SCREEN_WIDTH * sizeof(nes::Pixel),
colorspace,
kCGImageAlphaPremultipliedLast,
dataProvider,
NULL,
false,
kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorspace);
dispatch_async(dispatch_get_main_queue(), ^{
_frame = image;
});
});
}
return self;
}
- (void)runRom:(NSURL*)url {
_system->insertCartridge([url fileSystemRepresentation]);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while(TRUE) {
[_condition lock];
while (!_runEmulation) {
[_condition wait];
}
while(_runEmulation) {
_system->tick();
}
[_condition unlock];
}
});
}
- (void)stepToNextFrame {
[_condition lock];
_runEmulation = YES;
[_condition signal];
[_condition unlock];
}
@end