mirror of https://github.com/LIJI32/SameBoy.git
Porting GBViewMetal
This commit is contained in:
parent
093998389c
commit
4c5d896630
|
@ -0,0 +1,35 @@
|
|||
#include <TargetConditionals.h>
|
||||
#include <Core/gb.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#define NSView UIView
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GB_FRAME_BLENDING_MODE_DISABLED,
|
||||
GB_FRAME_BLENDING_MODE_SIMPLE,
|
||||
GB_FRAME_BLENDING_MODE_ACCURATE,
|
||||
GB_FRAME_BLENDING_MODE_ACCURATE_EVEN = GB_FRAME_BLENDING_MODE_ACCURATE,
|
||||
GB_FRAME_BLENDING_MODE_ACCURATE_ODD,
|
||||
} GB_frame_blending_mode_t;
|
||||
|
||||
@interface GBViewBase : NSView
|
||||
{
|
||||
@public
|
||||
GB_gameboy_t *_gb;
|
||||
}
|
||||
|
||||
@property (nonatomic) GB_gameboy_t *gb;
|
||||
@property (nonatomic) GB_frame_blending_mode_t frameBlendingMode;
|
||||
@property (nonatomic, strong) NSView *internalView;
|
||||
- (void) flip;
|
||||
- (uint32_t *) pixels;
|
||||
- (void)screenSizeChanged;
|
||||
- (void) createInternalView;
|
||||
- (uint32_t *)currentBuffer;
|
||||
- (uint32_t *)previousBuffer;
|
||||
|
||||
@end
|
|
@ -0,0 +1,83 @@
|
|||
#import "GBViewBase.h"
|
||||
|
||||
@implementation GBViewBase
|
||||
{
|
||||
uint32_t *_imageBuffers[3];
|
||||
unsigned _currentBuffer;
|
||||
GB_frame_blending_mode_t _frameBlendingMode;
|
||||
}
|
||||
|
||||
- (void)screenSizeChanged
|
||||
{
|
||||
if (_imageBuffers[0]) free(_imageBuffers[0]);
|
||||
if (_imageBuffers[1]) free(_imageBuffers[1]);
|
||||
if (_imageBuffers[2]) free(_imageBuffers[2]);
|
||||
|
||||
size_t buffer_size = sizeof(_imageBuffers[0][0]) * GB_get_screen_width(_gb) * GB_get_screen_height(_gb);
|
||||
|
||||
_imageBuffers[0] = calloc(1, buffer_size);
|
||||
_imageBuffers[1] = calloc(1, buffer_size);
|
||||
_imageBuffers[2] = calloc(1, buffer_size);
|
||||
}
|
||||
|
||||
- (void)flip
|
||||
{
|
||||
_currentBuffer = (_currentBuffer + 1) % self.numberOfBuffers;
|
||||
}
|
||||
|
||||
- (unsigned) numberOfBuffers
|
||||
{
|
||||
return _frameBlendingMode? 3 : 2;
|
||||
}
|
||||
|
||||
- (void) createInternalView
|
||||
{
|
||||
assert(false && "createInternalView must not be inherited");
|
||||
}
|
||||
|
||||
- (uint32_t *)currentBuffer
|
||||
{
|
||||
return _imageBuffers[_currentBuffer];
|
||||
}
|
||||
|
||||
- (uint32_t *)previousBuffer
|
||||
{
|
||||
return _imageBuffers[(_currentBuffer + 2) % self.numberOfBuffers];
|
||||
}
|
||||
|
||||
- (uint32_t *) pixels
|
||||
{
|
||||
return _imageBuffers[(_currentBuffer + 1) % self.numberOfBuffers];
|
||||
}
|
||||
|
||||
- (void) setFrameBlendingMode:(GB_frame_blending_mode_t)frameBlendingMode
|
||||
{
|
||||
_frameBlendingMode = frameBlendingMode;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
- (GB_frame_blending_mode_t)frameBlendingMode
|
||||
{
|
||||
if (_frameBlendingMode == GB_FRAME_BLENDING_MODE_ACCURATE) {
|
||||
if (!_gb || GB_is_sgb(_gb)) {
|
||||
return GB_FRAME_BLENDING_MODE_SIMPLE;
|
||||
}
|
||||
return GB_is_odd_frame(_gb)? GB_FRAME_BLENDING_MODE_ACCURATE_ODD : GB_FRAME_BLENDING_MODE_ACCURATE_EVEN;
|
||||
}
|
||||
return _frameBlendingMode;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(_imageBuffers[0]);
|
||||
free(_imageBuffers[1]);
|
||||
free(_imageBuffers[2]);
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
- (void)setNeedsDisplay
|
||||
{
|
||||
[self setNeedsDisplay:true];
|
||||
}
|
||||
#endif
|
||||
@end
|
|
@ -0,0 +1,11 @@
|
|||
#include <TargetConditionals.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#if TARGET_OS_IPHONE
|
||||
#import "../iOS/GBView.h"
|
||||
#else
|
||||
#import "../Cocoa/GBView.h"
|
||||
#endif
|
||||
|
||||
@interface GBViewMetal : GBView<MTKViewDelegate>
|
||||
+ (bool) isSupported;
|
||||
@end
|
|
@ -25,10 +25,14 @@ static const vector_float2 rect[] =
|
|||
|
||||
+ (bool)isSupported
|
||||
{
|
||||
#if TARGET_OS_IPHONE
|
||||
return true;
|
||||
#else
|
||||
if (MTLCopyAllDevices) {
|
||||
return [MTLCopyAllDevices() count];
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) allocateTextures
|
||||
|
@ -135,7 +139,9 @@ static const vector_float2 rect[] =
|
|||
|
||||
- (void)drawInMTKView:(MTKView *)view
|
||||
{
|
||||
#if !TARGET_OS_IPHONE
|
||||
if (!(view.window.occlusionState & NSWindowOcclusionStateVisible)) return;
|
||||
#endif
|
||||
if (!self.gb) return;
|
||||
if (texture.width != GB_get_screen_width(self.gb) ||
|
||||
texture.height != GB_get_screen_height(self.gb)) {
|
||||
|
@ -161,7 +167,7 @@ static const vector_float2 rect[] =
|
|||
MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor;
|
||||
id<MTLCommandBuffer> command_buffer = [command_queue commandBuffer];
|
||||
|
||||
if (render_pass_descriptor != nil) {
|
||||
if (render_pass_descriptor) {
|
||||
*(GB_frame_blending_mode_t *)[frame_blending_mode_buffer contents] = [self frameBlendingMode];
|
||||
*(vector_float2 *)[output_resolution_buffer contents] = output_resolution;
|
||||
|
||||
|
@ -210,10 +216,15 @@ static const vector_float2 rect[] =
|
|||
{
|
||||
[super flip];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
#if TARGET_OS_IPHONE
|
||||
[(MTKView *)self.internalView setNeedsDisplay];
|
||||
#else
|
||||
[(MTKView *)self.internalView setNeedsDisplay:true];
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
- (NSImage *)renderToImage
|
||||
{
|
||||
CIImage *ciImage = [CIImage imageWithMTLTexture:[[(MTKView *)self.internalView currentDrawable] texture]
|
||||
|
@ -228,5 +239,6 @@ static const vector_float2 rect[] =
|
|||
CGImageRelease(cgImage);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
|
@ -1,32 +1,16 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#include <Core/gb.h>
|
||||
#import <JoyKit/JoyKit.h>
|
||||
#import "GBOSDView.h"
|
||||
#import "GBViewBase.h"
|
||||
|
||||
|
||||
@class Document;
|
||||
|
||||
typedef enum {
|
||||
GB_FRAME_BLENDING_MODE_DISABLED,
|
||||
GB_FRAME_BLENDING_MODE_SIMPLE,
|
||||
GB_FRAME_BLENDING_MODE_ACCURATE,
|
||||
GB_FRAME_BLENDING_MODE_ACCURATE_EVEN = GB_FRAME_BLENDING_MODE_ACCURATE,
|
||||
GB_FRAME_BLENDING_MODE_ACCURATE_ODD,
|
||||
} GB_frame_blending_mode_t;
|
||||
|
||||
@interface GBView : NSView<JOYListener>
|
||||
- (void) flip;
|
||||
- (uint32_t *) pixels;
|
||||
@interface GBView : GBViewBase<JOYListener>
|
||||
@property (nonatomic, weak) IBOutlet Document *document;
|
||||
@property (nonatomic) GB_gameboy_t *gb;
|
||||
@property (nonatomic) GB_frame_blending_mode_t frameBlendingMode;
|
||||
@property (nonatomic, getter=isMouseHidingEnabled) bool mouseHidingEnabled;
|
||||
@property (nonatomic) bool isRewinding;
|
||||
@property (nonatomic, strong) NSView *internalView;
|
||||
@property (weak) GBOSDView *osdView;
|
||||
- (void) createInternalView;
|
||||
- (uint32_t *)currentBuffer;
|
||||
- (uint32_t *)previousBuffer;
|
||||
- (void)screenSizeChanged;
|
||||
- (void)setRumble: (double)amp;
|
||||
- (NSImage *)renderToImage;
|
||||
- (void)setRumble: (double)amp;
|
||||
@end
|
||||
|
|
|
@ -104,8 +104,6 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
|
||||
@implementation GBView
|
||||
{
|
||||
uint32_t *image_buffers[3];
|
||||
unsigned char current_buffer;
|
||||
bool mouse_hidden;
|
||||
NSTrackingArea *tracking_area;
|
||||
bool _mouseHidingEnabled;
|
||||
|
@ -116,7 +114,6 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
bool analogClockMultiplierValid;
|
||||
NSEventModifierFlags previousModifiers;
|
||||
JOYController *lastController;
|
||||
GB_frame_blending_mode_t _frameBlendingMode;
|
||||
bool _turbo;
|
||||
bool _mouseControlEnabled;
|
||||
}
|
||||
|
@ -137,11 +134,6 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
return [super allocWithZone:zone];
|
||||
}
|
||||
|
||||
- (void) createInternalView
|
||||
{
|
||||
assert(false && "createInternalView must not be inherited");
|
||||
}
|
||||
|
||||
- (void) _init
|
||||
{
|
||||
[self registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
|
||||
|
@ -162,15 +154,7 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
|
||||
- (void)screenSizeChanged
|
||||
{
|
||||
if (image_buffers[0]) free(image_buffers[0]);
|
||||
if (image_buffers[1]) free(image_buffers[1]);
|
||||
if (image_buffers[2]) free(image_buffers[2]);
|
||||
|
||||
size_t buffer_size = sizeof(image_buffers[0][0]) * GB_get_screen_width(_gb) * GB_get_screen_height(_gb);
|
||||
|
||||
image_buffers[0] = calloc(1, buffer_size);
|
||||
image_buffers[1] = calloc(1, buffer_size);
|
||||
image_buffers[2] = calloc(1, buffer_size);
|
||||
[super screenSizeChanged];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self setFrame:self.superview.frame];
|
||||
|
@ -182,33 +166,8 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
[self setFrame:self.superview.frame];
|
||||
}
|
||||
|
||||
- (void) setFrameBlendingMode:(GB_frame_blending_mode_t)frameBlendingMode
|
||||
{
|
||||
_frameBlendingMode = frameBlendingMode;
|
||||
[self setNeedsDisplay:true];
|
||||
}
|
||||
|
||||
|
||||
- (GB_frame_blending_mode_t)frameBlendingMode
|
||||
{
|
||||
if (_frameBlendingMode == GB_FRAME_BLENDING_MODE_ACCURATE) {
|
||||
if (!_gb || GB_is_sgb(_gb)) {
|
||||
return GB_FRAME_BLENDING_MODE_SIMPLE;
|
||||
}
|
||||
return GB_is_odd_frame(_gb)? GB_FRAME_BLENDING_MODE_ACCURATE_ODD : GB_FRAME_BLENDING_MODE_ACCURATE_EVEN;
|
||||
}
|
||||
return _frameBlendingMode;
|
||||
}
|
||||
- (unsigned char) numberOfBuffers
|
||||
{
|
||||
return _frameBlendingMode? 3 : 2;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
free(image_buffers[0]);
|
||||
free(image_buffers[1]);
|
||||
free(image_buffers[2]);
|
||||
if (mouse_hidden) {
|
||||
mouse_hidden = false;
|
||||
[NSCursor unhide];
|
||||
|
@ -217,6 +176,7 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
[self setRumble:0];
|
||||
[JOYController unregisterListener:self];
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||
{
|
||||
if (!(self = [super initWithCoder:coder])) {
|
||||
|
@ -301,12 +261,7 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
(analogClockMultiplierValid && analogClockMultiplier < 1)) {
|
||||
[self.osdView displayText:@"Slow motion..."];
|
||||
}
|
||||
current_buffer = (current_buffer + 1) % self.numberOfBuffers;
|
||||
}
|
||||
|
||||
- (uint32_t *) pixels
|
||||
{
|
||||
return image_buffers[(current_buffer + 1) % self.numberOfBuffers];
|
||||
[super flip];
|
||||
}
|
||||
|
||||
-(void)keyDown:(NSEvent *)theEvent
|
||||
|
@ -760,16 +715,6 @@ static const uint8_t workboy_vk_to_key[] = {
|
|||
previousModifiers = event.modifierFlags;
|
||||
}
|
||||
|
||||
- (uint32_t *)currentBuffer
|
||||
{
|
||||
return image_buffers[current_buffer];
|
||||
}
|
||||
|
||||
- (uint32_t *)previousBuffer
|
||||
{
|
||||
return image_buffers[(current_buffer + 2) % self.numberOfBuffers];
|
||||
}
|
||||
|
||||
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
NSPasteboard *pboard = [sender draggingPasteboard];
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <MetalKit/MetalKit.h>
|
||||
#import "GBView.h"
|
||||
|
||||
@interface GBViewMetal : GBView<MTKViewDelegate>
|
||||
+ (bool) isSupported;
|
||||
@end
|
|
@ -0,0 +1,5 @@
|
|||
#import "GBViewBase.h"
|
||||
|
||||
@interface GBView : GBViewBase
|
||||
|
||||
@end
|
|
@ -0,0 +1,12 @@
|
|||
#import "GBView.h"
|
||||
|
||||
@implementation GBView
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
[self createInternalView];
|
||||
[self addSubview:self.internalView];
|
||||
self.internalView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
return self;
|
||||
}
|
||||
@end
|
|
@ -1,6 +1,8 @@
|
|||
#import "GBViewController.h"
|
||||
#import "GBHorizontalLayout.h"
|
||||
#import "GBVerticalLayout.h"
|
||||
#import "GBViewMetal.h"
|
||||
#include <Core/gb.h>
|
||||
|
||||
static void positionView(UIImageView *view, CGPoint position)
|
||||
{
|
||||
|
@ -26,6 +28,8 @@ static void positionView(UIImageView *view, CGPoint position)
|
|||
UIImageView *_bButtonView;
|
||||
UIImageView *_startButtonView;
|
||||
UIImageView *_selectButtonView;
|
||||
GBView *_gbView;
|
||||
GB_gameboy_t _gb;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
|
@ -33,36 +37,42 @@ static void positionView(UIImageView *view, CGPoint position)
|
|||
_window = [[UIWindow alloc] init];
|
||||
_window.rootViewController = self;
|
||||
[_window makeKeyAndVisible];
|
||||
|
||||
_window.backgroundColor = [UIColor colorWithRed:174 / 255.0 green:176 / 255.0 blue:180 / 255.0 alpha:1.0];
|
||||
|
||||
_horizontalLayout = [[GBHorizontalLayout alloc] init];
|
||||
_verticalLayout = [[GBVerticalLayout alloc] init];
|
||||
|
||||
_backgroundView = [[UIImageView alloc] initWithImage:nil];
|
||||
[_window addSubview:_backgroundView];
|
||||
self.view = _backgroundView;
|
||||
|
||||
_dpadView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dpad"]];
|
||||
_aButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
|
||||
_bButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button"]];
|
||||
_startButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
|
||||
_selectButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"button2"]];
|
||||
_gbView = [[GBViewMetal alloc] initWithFrame:CGRectZero];
|
||||
|
||||
GB_init(&_gb, GB_MODEL_CGB_E);
|
||||
_gbView.gb = &_gb;
|
||||
[_gbView screenSizeChanged];
|
||||
|
||||
[self willRotateToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation
|
||||
duration:0];
|
||||
|
||||
[_backgroundView addSubview:_dpadView];
|
||||
[_backgroundView addSubview:_aButtonView];
|
||||
[_backgroundView addSubview:_bButtonView];
|
||||
[_backgroundView addSubview:_startButtonView];
|
||||
[_backgroundView addSubview:_selectButtonView];
|
||||
[_backgroundView addSubview:_gbView];
|
||||
|
||||
[self orientationChange];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(orientationChange)
|
||||
name:UIApplicationDidChangeStatusBarOrientationNotification
|
||||
object:nil];
|
||||
return true;
|
||||
}
|
||||
|
||||
- (void)orientationChange
|
||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
|
||||
{
|
||||
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
||||
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
|
||||
_currentLayout = _verticalLayout;
|
||||
}
|
||||
|
@ -78,6 +88,16 @@ static void positionView(UIImageView *view, CGPoint position)
|
|||
positionView(_bButtonView, _currentLayout.bLocation);
|
||||
positionView(_startButtonView, _currentLayout.startLocation);
|
||||
positionView(_selectButtonView, _currentLayout.selectLocation);
|
||||
|
||||
CGRect screenFrame = _currentLayout.screenRect;
|
||||
screenFrame.origin.x /= [UIScreen mainScreen].scale;
|
||||
screenFrame.origin.y /= [UIScreen mainScreen].scale;
|
||||
screenFrame.size.width /= [UIScreen mainScreen].scale;
|
||||
screenFrame.size.height /= [UIScreen mainScreen].scale;
|
||||
|
||||
_gbView.frame = screenFrame;
|
||||
memset(_gbView.pixels, rand(), 160 * 144 * 4);
|
||||
[_gbView flip];
|
||||
}
|
||||
|
||||
- (BOOL)prefersHomeIndicatorAutoHidden
|
||||
|
|
Loading…
Reference in New Issue