2015-12-30 06:41:46 +00:00
|
|
|
#if defined(Hiro_Canvas)
|
|
|
|
|
2013-03-15 13:11:33 +00:00
|
|
|
@implementation CocoaCanvas : NSImageView
|
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
-(id) initWith:(hiro::mCanvas&)canvasReference {
|
2013-03-15 13:11:33 +00:00
|
|
|
if(self = [super initWithFrame:NSMakeRect(0, 0, 0, 0)]) {
|
|
|
|
canvas = &canvasReference;
|
|
|
|
[self setEditable:NO]; //disable image drag-and-drop functionality
|
2013-11-28 10:29:01 +00:00
|
|
|
NSTrackingArea* area = [[[NSTrackingArea alloc] initWithRect:[self frame]
|
2013-03-15 13:11:33 +00:00
|
|
|
options:NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
|
|
|
|
owner:self userInfo:nil
|
|
|
|
] autorelease];
|
|
|
|
[self addTrackingArea:area];
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2019-07-26 15:52:29 +00:00
|
|
|
-(void) resetCursorRects {
|
2019-07-26 16:27:56 +00:00
|
|
|
if(auto mouseCursor = NSMakeCursor(canvas->mouseCursor())) {
|
2019-07-26 15:52:29 +00:00
|
|
|
[self addCursorRect:self.bounds cursor:mouseCursor];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-29 09:42:45 +00:00
|
|
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
|
|
|
return DropPathsOperation(sender);
|
|
|
|
}
|
|
|
|
|
|
|
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
2016-07-01 11:58:12 +00:00
|
|
|
auto paths = DropPaths(sender);
|
2016-05-04 10:07:13 +00:00
|
|
|
if(!paths) return NO;
|
2015-12-30 06:41:46 +00:00
|
|
|
canvas->doDrop(paths);
|
2013-07-29 09:42:45 +00:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown {
|
2016-01-08 09:23:46 +00:00
|
|
|
if(isDown) {
|
2013-03-15 13:11:33 +00:00
|
|
|
switch([event buttonNumber]) {
|
2016-01-08 09:23:46 +00:00
|
|
|
case 0: return canvas->doMousePress(hiro::Mouse::Button::Left);
|
|
|
|
case 1: return canvas->doMousePress(hiro::Mouse::Button::Right);
|
|
|
|
case 2: return canvas->doMousePress(hiro::Mouse::Button::Middle);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch([event buttonNumber]) {
|
|
|
|
case 0: return canvas->doMouseRelease(hiro::Mouse::Button::Left);
|
|
|
|
case 1: return canvas->doMouseRelease(hiro::Mouse::Button::Right);
|
|
|
|
case 2: return canvas->doMouseRelease(hiro::Mouse::Button::Middle);
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-26 15:52:29 +00:00
|
|
|
-(void) mouseEntered:(NSEvent*)event {
|
|
|
|
canvas->doMouseEnter();
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) mouseExited:(NSEvent*)event {
|
2015-12-30 06:41:46 +00:00
|
|
|
canvas->doMouseLeave();
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) mouseMove:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
if([event window] == nil) return;
|
|
|
|
NSPoint location = [self convertPoint:[event locationInWindow] fromView:nil];
|
2015-12-30 06:41:46 +00:00
|
|
|
canvas->doMouseMove({(int)location.x, (int)([self frame].size.height - 1 - location.y)});
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) mouseDown:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseButton:event down:YES];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) mouseUp:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseButton:event down:NO];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) mouseDragged:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseMove:event];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) rightMouseDown:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseButton:event down:YES];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) rightMouseUp:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseButton:event down:NO];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) rightMouseDragged:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseMove:event];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) otherMouseDown:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseButton:event down:YES];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) otherMouseUp:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseButton:event down:NO];
|
|
|
|
}
|
|
|
|
|
2013-03-21 12:59:01 +00:00
|
|
|
-(void) otherMouseDragged:(NSEvent*)event {
|
2013-03-15 13:11:33 +00:00
|
|
|
[self mouseMove:event];
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
namespace hiro {
|
|
|
|
|
|
|
|
auto pCanvas::construct() -> void {
|
|
|
|
@autoreleasepool {
|
|
|
|
cocoaView = cocoaCanvas = [[CocoaCanvas alloc] initWith:self()];
|
|
|
|
pWidget::construct();
|
|
|
|
}
|
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
auto pCanvas::destruct() -> void {
|
|
|
|
@autoreleasepool {
|
2016-01-07 08:14:33 +00:00
|
|
|
[cocoaView removeFromSuperview];
|
2015-12-30 06:41:46 +00:00
|
|
|
[cocoaView release];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto pCanvas::minimumSize() const -> Size {
|
2016-01-08 09:23:46 +00:00
|
|
|
if(auto& icon = state().icon) return {(int)icon.width(), (int)icon.height()};
|
2015-12-30 06:41:46 +00:00
|
|
|
return {0, 0};
|
|
|
|
}
|
|
|
|
|
Update to bsnes v107.1 release.
byuu says:
Don't let the point release fool you, there are many significant changes in this
release. I will be keeping bsnes releases using a point system until the new
higan release is ready.
Changelog:
- GUI: added high DPI support
- GUI: fixed the state manager image preview
- Windows: added a new waveOut driver with support for dynamic rate control
- Windows: corrected the XAudio 2.1 dynamic rate control support [BearOso]
- Windows: corrected the Direct3D 9.0 fullscreen exclusive window centering
- Windows: fixed XInput controller support on Windows 10
- SFC: added high-level emulation for the DSP1, DSP2, DSP4, ST010, and Cx4
coprocessors
- SFC: fixed a slight rendering glitch in the intro to Megalomania
If the coprocessor firmware is missing, bsnes will fallback on HLE where it is
supported, which is everything other than SD Gundam GX and the two Hayazashi
Nidan Morita Shougi games.
The Windows dynamic rate control works best with Direct3D in fullscreen
exclusive mode. I recommend the waveOut driver over the XAudio 2.1 driver, as it
is not possible to target a single XAudio2 version on all Windows OS releases.
The waveOut driver should work everywhere out of the box.
Note that with DRC, the synchronization source is your monitor, so you will
want to be running at 60hz (NTSC) or 50hz (PAL). If you have an adaptive sync
monitor, you should instead use the WASAPI (exclusive) or ASIO audio driver.
2019-04-09 01:16:30 +00:00
|
|
|
auto pCanvas::setAlignment(Alignment) -> void {
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
auto pCanvas::setColor(Color color) -> void {
|
2016-01-08 09:23:46 +00:00
|
|
|
update();
|
2015-12-30 06:41:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto pCanvas::setDroppable(bool droppable) -> void {
|
2013-07-29 09:42:45 +00:00
|
|
|
@autoreleasepool {
|
|
|
|
if(droppable) {
|
|
|
|
[cocoaCanvas registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
|
|
|
} else {
|
|
|
|
[cocoaCanvas unregisterDraggedTypes];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-07 09:44:09 +00:00
|
|
|
auto pCanvas::setFocusable(bool focusable) -> void {
|
|
|
|
//TODO
|
|
|
|
}
|
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
auto pCanvas::setGeometry(Geometry geometry) -> void {
|
2013-11-28 10:29:01 +00:00
|
|
|
pWidget::setGeometry(geometry);
|
2016-01-08 09:23:46 +00:00
|
|
|
update();
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
auto pCanvas::setGradient(Gradient gradient) -> void {
|
2016-01-08 09:23:46 +00:00
|
|
|
update();
|
2013-11-28 10:29:01 +00:00
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
|
2016-01-07 08:14:33 +00:00
|
|
|
auto pCanvas::setIcon(const image& icon) -> void {
|
2016-01-08 09:23:46 +00:00
|
|
|
update();
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
2015-12-30 06:41:46 +00:00
|
|
|
auto pCanvas::update() -> void {
|
2016-01-08 09:23:46 +00:00
|
|
|
_rasterize();
|
|
|
|
@autoreleasepool {
|
|
|
|
[cocoaView setNeedsDisplay:YES];
|
|
|
|
}
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
|
|
|
|
Update to bsnes v107.1 release.
byuu says:
Don't let the point release fool you, there are many significant changes in this
release. I will be keeping bsnes releases using a point system until the new
higan release is ready.
Changelog:
- GUI: added high DPI support
- GUI: fixed the state manager image preview
- Windows: added a new waveOut driver with support for dynamic rate control
- Windows: corrected the XAudio 2.1 dynamic rate control support [BearOso]
- Windows: corrected the Direct3D 9.0 fullscreen exclusive window centering
- Windows: fixed XInput controller support on Windows 10
- SFC: added high-level emulation for the DSP1, DSP2, DSP4, ST010, and Cx4
coprocessors
- SFC: fixed a slight rendering glitch in the intro to Megalomania
If the coprocessor firmware is missing, bsnes will fallback on HLE where it is
supported, which is everything other than SD Gundam GX and the two Hayazashi
Nidan Morita Shougi games.
The Windows dynamic rate control works best with Direct3D in fullscreen
exclusive mode. I recommend the waveOut driver over the XAudio 2.1 driver, as it
is not possible to target a single XAudio2 version on all Windows OS releases.
The waveOut driver should work everywhere out of the box.
Note that with DRC, the synchronization source is your monitor, so you will
want to be running at 60hz (NTSC) or 50hz (PAL). If you have an adaptive sync
monitor, you should instead use the WASAPI (exclusive) or ASIO audio driver.
2019-04-09 01:16:30 +00:00
|
|
|
//todo: support cases where the icon size does not match the canvas size (alignment)
|
2015-12-30 06:41:46 +00:00
|
|
|
auto pCanvas::_rasterize() -> void {
|
2013-11-28 10:29:01 +00:00
|
|
|
@autoreleasepool {
|
2016-01-08 09:23:46 +00:00
|
|
|
int width = 0;
|
|
|
|
int height = 0;
|
|
|
|
|
|
|
|
if(auto& icon = state().icon) {
|
|
|
|
width = icon.width();
|
|
|
|
height = icon.height();
|
|
|
|
} else {
|
|
|
|
width = pSizable::state().geometry.width();
|
|
|
|
height = pSizable::state().geometry.height();
|
|
|
|
}
|
|
|
|
if(width <= 0 || height <= 0) return;
|
2013-11-28 10:29:01 +00:00
|
|
|
|
|
|
|
if(width != surfaceWidth || height != surfaceHeight) {
|
2016-01-08 09:23:46 +00:00
|
|
|
[cocoaView setImage:nil];
|
|
|
|
surface = nullptr;
|
|
|
|
bitmap = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
surfaceWidth = width;
|
|
|
|
surfaceHeight = height;
|
|
|
|
|
|
|
|
if(!surface) {
|
|
|
|
surface = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] autorelease];
|
|
|
|
bitmap = [[[NSBitmapImageRep alloc]
|
2013-11-28 10:29:01 +00:00
|
|
|
initWithBitmapDataPlanes:nil
|
|
|
|
pixelsWide:width pixelsHigh:height
|
|
|
|
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES
|
2019-07-26 15:52:29 +00:00
|
|
|
isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
|
2013-11-28 10:29:01 +00:00
|
|
|
bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
|
2016-01-08 09:23:46 +00:00
|
|
|
bytesPerRow:(width * 4) bitsPerPixel:32
|
2013-11-28 10:29:01 +00:00
|
|
|
] autorelease];
|
2016-01-08 09:23:46 +00:00
|
|
|
[surface addRepresentation:bitmap];
|
|
|
|
[cocoaView setImage:surface];
|
2013-11-28 10:29:01 +00:00
|
|
|
}
|
|
|
|
|
Update to v102r02 release.
byuu says:
Changelog:
- I caved on the `samples[] = {0.0}` thing, but I'm very unhappy about it
- if it's really invalid C++, then GCC needs to stop accepting it
in strict `-std=c++14` mode
- Emulator::Interface::Information::resettable is gone
- Emulator::Interface::reset() is gone
- FC, SFC, MD cores updated to remove soft reset behavior
- split GameBoy::Interface into GameBoyInterface,
GameBoyColorInterface
- split WonderSwan::Interface into WonderSwanInterface,
WonderSwanColorInterface
- PCE: fixed off-by-one scanline error [hex_usr]
- PCE: temporary hack to prevent crashing when VDS is set to < 2
- hiro: Cocoa: removed (u)int(#) constants; converted (u)int(#)
types to (u)int_(#)t types
- icarus: replaced usage of unique with strip instead (so we don't
mess up frameworks on macOS)
- libco: added macOS-specific section marker [Ryphecha]
So ... the major news this time is the removal of the soft reset
behavior. This is a major!! change that results in a 100KiB diff file,
and it's very prone to accidental mistakes!! If anyone is up for
testing, or even better -- looking over the code changes between v102r01
and v102r02 and looking for any issues, please do so. Ideally we'll want
to test every NES mapper type and every SNES coprocessor type by loading
said games and power cycling to make sure the games are all cleanly
resetting. It's too big of a change for me to cover there not being any
issues on my own, but this is truly critical code, so yeah ... please
help if you can.
We technically lose a bit of hardware documentation here. The soft reset
events do all kinds of interesting things in all kinds of different
chips -- or at least they do on the SNES. This is obviously not ideal.
But in the process of removing these portions of code, I found a few
mistakes I had made previously. It simplifies resetting the system state
a lot when not trying to have all the power() functions call the reset()
functions to share partial functionality.
In the future, the goal will be to come up with a way to add back in the
soft reset behavior via keyboard binding as with the Master System core.
What's going to have to happen is that the key binding will have to send
a "reset pulse" to every emulated chip, and those chips are going to
have to act independently to power() instead of reusing functionality.
We'll get there eventually, but there's many things of vastly greater
importance to work on right now, so it'll be a while. The information
isn't lost ... we'll just have to pull it out of v102 when we are ready.
Note that I left the SNES reset vector simulation code in, even though
it's not possible to trigger, for the time being.
Also ... the Super Game Boy core is still disconnected. To be honest, it
totally slipped my mind when I released v102 that it wasn't connected
again yet. This one's going to be pretty tricky to be honest. I'm
thinking about making a third GameBoy::Interface class just for SGB, and
coming up with some way of bypassing platform-> calls when in this
mode.
2017-01-22 21:04:26 +00:00
|
|
|
auto target = (uint32_t*)[bitmap bitmapData];
|
2016-01-08 09:23:46 +00:00
|
|
|
|
|
|
|
if(auto icon = state().icon) {
|
2017-06-22 06:04:07 +00:00
|
|
|
icon.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); //Cocoa uses ABGR format
|
2016-01-08 09:23:46 +00:00
|
|
|
memory::copy(target, icon.data(), icon.size());
|
|
|
|
} else if(auto& gradient = state().gradient) {
|
|
|
|
auto& colors = gradient.state.colors;
|
|
|
|
image fill;
|
|
|
|
fill.allocate(width, height);
|
|
|
|
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
|
|
|
|
memory::copy(target, fill.data(), fill.size());
|
|
|
|
} else {
|
Update to v102r02 release.
byuu says:
Changelog:
- I caved on the `samples[] = {0.0}` thing, but I'm very unhappy about it
- if it's really invalid C++, then GCC needs to stop accepting it
in strict `-std=c++14` mode
- Emulator::Interface::Information::resettable is gone
- Emulator::Interface::reset() is gone
- FC, SFC, MD cores updated to remove soft reset behavior
- split GameBoy::Interface into GameBoyInterface,
GameBoyColorInterface
- split WonderSwan::Interface into WonderSwanInterface,
WonderSwanColorInterface
- PCE: fixed off-by-one scanline error [hex_usr]
- PCE: temporary hack to prevent crashing when VDS is set to < 2
- hiro: Cocoa: removed (u)int(#) constants; converted (u)int(#)
types to (u)int_(#)t types
- icarus: replaced usage of unique with strip instead (so we don't
mess up frameworks on macOS)
- libco: added macOS-specific section marker [Ryphecha]
So ... the major news this time is the removal of the soft reset
behavior. This is a major!! change that results in a 100KiB diff file,
and it's very prone to accidental mistakes!! If anyone is up for
testing, or even better -- looking over the code changes between v102r01
and v102r02 and looking for any issues, please do so. Ideally we'll want
to test every NES mapper type and every SNES coprocessor type by loading
said games and power cycling to make sure the games are all cleanly
resetting. It's too big of a change for me to cover there not being any
issues on my own, but this is truly critical code, so yeah ... please
help if you can.
We technically lose a bit of hardware documentation here. The soft reset
events do all kinds of interesting things in all kinds of different
chips -- or at least they do on the SNES. This is obviously not ideal.
But in the process of removing these portions of code, I found a few
mistakes I had made previously. It simplifies resetting the system state
a lot when not trying to have all the power() functions call the reset()
functions to share partial functionality.
In the future, the goal will be to come up with a way to add back in the
soft reset behavior via keyboard binding as with the Master System core.
What's going to have to happen is that the key binding will have to send
a "reset pulse" to every emulated chip, and those chips are going to
have to act independently to power() instead of reusing functionality.
We'll get there eventually, but there's many things of vastly greater
importance to work on right now, so it'll be a while. The information
isn't lost ... we'll just have to pull it out of v102 when we are ready.
Note that I left the SNES reset vector simulation code in, even though
it's not possible to trigger, for the time being.
Also ... the Super Game Boy core is still disconnected. To be honest, it
totally slipped my mind when I released v102 that it wasn't connected
again yet. This one's going to be pretty tricky to be honest. I'm
thinking about making a third GameBoy::Interface class just for SGB, and
coming up with some way of bypassing platform-> calls when in this
mode.
2017-01-22 21:04:26 +00:00
|
|
|
uint32_t color = state().color.value();
|
2016-01-08 09:23:46 +00:00
|
|
|
for(auto n : range(width * height)) target[n] = color;
|
2013-11-28 10:29:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-15 13:11:33 +00:00
|
|
|
}
|
2015-12-30 06:41:46 +00:00
|
|
|
|
|
|
|
#endif
|