Some fixes for iOS

This commit is contained in:
Selim Mustafaev 2023-09-28 22:40:54 +03:00
parent be7d432f6d
commit e2c33d36f7
6 changed files with 91 additions and 25 deletions

View File

@ -14,12 +14,16 @@
- (instancetype)initWithNesSystem:(NesSystem*)system { - (instancetype)initWithNesSystem:(NesSystem*)system {
if(self = [super init]) { if(self = [super init]) {
self.system = system; self.system = system;
self.contentsGravity = kCAGravityResizeAspect;
_timer = [NSTimer timerWithTimeInterval:1.0/60.0 repeats:YES block:^(NSTimer * _Nonnull timer) { _timer = [NSTimer timerWithTimeInterval:1.0/60.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
if(self.system) { if(self.system) {
self.contents = self.system.frame; self.contents = (__bridge id _Nullable)(self.system.frame);
[self.system stepToNextFrame]; [self.system stepToNextFrame];
} }
}]; }];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSDefaultRunLoopMode];
} }
return self; return self;
} }

View File

@ -28,24 +28,28 @@
size_t frameBufferSize = nes::Ppu::SCREEN_WIDTH * nes::Ppu::SCREEN_HEIGHT * sizeof(nes::Pixel); size_t frameBufferSize = nes::Ppu::SCREEN_WIDTH * nes::Ppu::SCREEN_HEIGHT * sizeof(nes::Pixel);
_system->setNewFrameCallback([&](auto frameBuffer) { _system->setNewFrameCallback([frameBufferSize, self](auto frameBuffer) {
_runEmulation = NO; _runEmulation = NO;
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, (void*)frameBuffer, frameBufferSize, NULL); CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, (void*)frameBuffer, frameBufferSize, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
_frame = CGImageCreate(nes::Ppu::SCREEN_WIDTH, CGImageRef image = CGImageCreate(nes::Ppu::SCREEN_WIDTH,
nes::Ppu::SCREEN_HEIGHT, nes::Ppu::SCREEN_HEIGHT,
8, 8,
sizeof(nes::Pixel)*8, sizeof(nes::Pixel)*8,
nes::Ppu::SCREEN_WIDTH * sizeof(nes::Pixel), nes::Ppu::SCREEN_WIDTH * sizeof(nes::Pixel),
colorspace, colorspace,
kCGBitmapByteOrderDefault, kCGImageAlphaPremultipliedLast,
dataProvider, dataProvider,
NULL, NULL,
true, true,
kCGRenderingIntentDefault); kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider); CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorspace); CGColorSpaceRelease(colorspace);
dispatch_async(dispatch_get_main_queue(), ^{
_frame = image;
});
}); });
} }
return self; return self;
@ -54,16 +58,18 @@
- (void)runRom:(NSURL*)url { - (void)runRom:(NSURL*)url {
_system->insertCartridge([url fileSystemRepresentation]); _system->insertCartridge([url fileSystemRepresentation]);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[_condition lock]; while(TRUE) {
while (!_runEmulation) { [_condition lock];
[_condition wait]; while (!_runEmulation) {
[_condition wait];
}
while(_runEmulation) {
_system->tick();
}
[_condition unlock];
} }
while(_runEmulation) {
_system->tick();
}
[_condition unlock];
}); });
} }

View File

@ -9,5 +9,6 @@
#define NesKit_h #define NesKit_h
#import "../NesSystem.h" #import "../NesSystem.h"
#import "../NesLayer.h"
#endif /* Header_h */ #endif /* Header_h */

View File

@ -8,14 +8,65 @@
import UIKit import UIKit
import NesKit import NesKit
class NesView: UIView {
let nesLayer: NesLayer
init(system: NesSystem) {
self.nesLayer = NesLayer(nesSystem: system)
super.init(frame: .zero)
self.layer.addSublayer(self.nesLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.nesLayer.frame = self.layer.frame
}
}
class ViewController: UIViewController { class ViewController: UIViewController {
var system = NesSystem() let system = NesSystem()
lazy var nesView = NesView(system: system)
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
view.addSubview(nesView)
nesView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
nesView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
nesView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
nesView.topAnchor.constraint(equalTo: view.topAnchor),
nesView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.openFilePicker()
}
} }
func openFilePicker() {
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.data])
documentPicker.delegate = self
documentPicker.modalPresentationStyle = .overFullScreen
documentPicker.allowsMultipleSelection = false
present(documentPicker, animated: true)
}
}
extension ViewController: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print("Did pick document at: ", url)
system.runRom(url.path(percentEncoded: false))
}
} }

View File

@ -28,6 +28,7 @@ namespace nes {
_chrRom = std::span<uint8_t>(_romData.get() + sizeof(RomHeader) + prgSize, chrSize); _chrRom = std::span<uint8_t>(_romData.get() + sizeof(RomHeader) + prgSize, chrSize);
_mapper = std::make_unique<Mapper0>(_header->prgChunks, _header->chrChunks); _mapper = std::make_unique<Mapper0>(_header->prgChunks, _header->chrChunks);
_mirroring = _header->flags.mirroring == 0 ? Mirroring::Horizontal : Mirroring::Vertical;
} }
uint8_t Cartridge::readPrg(uint16_t address) { uint8_t Cartridge::readPrg(uint16_t address) {
@ -41,7 +42,7 @@ namespace nes {
} }
Cartridge::Mirroring Cartridge::mirroring() const { Cartridge::Mirroring Cartridge::mirroring() const {
return _header->flags.mirroring == 0 ? Mirroring::Horizontal : Mirroring::Vertical; return _mirroring;
} }
} }

View File

@ -53,6 +53,9 @@ namespace nes {
RomHeader* _header; RomHeader* _header;
std::span<uint8_t> _prgRom; std::span<uint8_t> _prgRom;
std::span<uint8_t> _chrRom; std::span<uint8_t> _chrRom;
private:
Mirroring _mirroring;
}; };
} }