mirror of https://github.com/bsnes-emu/bsnes.git
Printer support in Cocoa
This commit is contained in:
parent
527ae01e0e
commit
613d3b2e82
|
@ -25,6 +25,9 @@
|
|||
@property (strong) IBOutlet NSTextField *vramStatusLabel;
|
||||
@property (strong) IBOutlet NSTableView *paletteTableView;
|
||||
@property (strong) IBOutlet NSTableView *spritesTableView;
|
||||
@property (strong) IBOutlet NSPanel *printerFeedWindow;
|
||||
@property (strong) IBOutlet NSImageView *feedImageView;
|
||||
@property (strong) IBOutlet NSButton *feedSaveButton;
|
||||
|
||||
-(uint8_t) readMemory:(uint16_t) addr;
|
||||
-(void) writeMemory:(uint16_t) addr value:(uint8_t)value;
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
uint16_t oamCount;
|
||||
uint8_t oamHeight;
|
||||
bool oamUpdating;
|
||||
|
||||
NSMutableData *currentPrinterImageData;
|
||||
enum {GBAccessoryNone, GBAccessoryPrinter} accessory;
|
||||
}
|
||||
|
||||
@property GBAudioClient *audioClient;
|
||||
|
@ -46,6 +49,9 @@
|
|||
- (const char *) getAsyncDebuggerInput;
|
||||
- (void) cameraRequestUpdate;
|
||||
- (uint8_t) cameraGetPixelAtX:(uint8_t)x andY:(uint8_t)y;
|
||||
- (void) printImage:(uint32_t *)image height:(unsigned) height
|
||||
topMargin:(unsigned) topMargin bottomMargin: (unsigned) bottomMargin
|
||||
exposure:(unsigned) exposure;
|
||||
@end
|
||||
|
||||
static void vblank(GB_gameboy_t *gb)
|
||||
|
@ -75,7 +81,7 @@ static char *asyncConsoleInput(GB_gameboy_t *gb)
|
|||
|
||||
static uint32_t rgbEncode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
return (r << 0) | (g << 8) | (b << 16);
|
||||
return (r << 0) | (g << 8) | (b << 16) | 0xFF000000;
|
||||
}
|
||||
|
||||
static void cameraRequestUpdate(GB_gameboy_t *gb)
|
||||
|
@ -90,6 +96,13 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
return [self cameraGetPixelAtX:x andY:y];
|
||||
}
|
||||
|
||||
static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height,
|
||||
uint8_t top_margin, uint8_t bottom_margin, uint8_t exposure)
|
||||
{
|
||||
Document *self = (__bridge Document *)(gb->user_data);
|
||||
[self printImage:image height:height topMargin:top_margin bottomMargin:bottom_margin exposure:exposure];
|
||||
}
|
||||
|
||||
@implementation Document
|
||||
{
|
||||
GB_gameboy_t gb;
|
||||
|
@ -132,6 +145,7 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
|
||||
- (void) initCommon
|
||||
{
|
||||
gb.user_data = (__bridge void *)(self);
|
||||
GB_set_vblank_callback(&gb, (GB_vblank_callback_t) vblank);
|
||||
GB_set_log_callback(&gb, (GB_log_callback_t) consoleLog);
|
||||
GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput);
|
||||
|
@ -139,7 +153,6 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
GB_set_rgb_encode_callback(&gb, rgbEncode);
|
||||
GB_set_camera_get_pixel_callback(&gb, cameraGetPixel);
|
||||
GB_set_camera_update_request_callback(&gb, cameraRequestUpdate);
|
||||
gb.user_data = (__bridge void *)(self);
|
||||
}
|
||||
|
||||
- (void) vblank
|
||||
|
@ -271,6 +284,14 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
window_frame.size.height);
|
||||
[self.mainWindow setFrame:window_frame display:YES];
|
||||
self.vramStatusLabel.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
|
||||
|
||||
[self.feedSaveButton removeFromSuperview];
|
||||
/* contentView.superview.subviews.lastObject is the titlebar view */
|
||||
NSView *titleView = self.printerFeedWindow.contentView.superview.subviews.lastObject;
|
||||
[titleView addSubview: self.feedSaveButton];
|
||||
self.feedSaveButton.frame = (NSRect){{268, 2}, {48, 17}};
|
||||
|
||||
[self start];
|
||||
|
||||
}
|
||||
|
@ -400,6 +421,12 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if ([anItem action] == @selector(disconnectAllAccessories:)) {
|
||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryNone];
|
||||
}
|
||||
else if ([anItem action] == @selector(connectPrinter:)) {
|
||||
[(NSMenuItem*)anItem setState:accessory == GBAccessoryPrinter];
|
||||
}
|
||||
return [super validateUserInterfaceItem:anItem];
|
||||
}
|
||||
|
||||
|
@ -1073,4 +1100,71 @@ static uint8_t cameraGetPixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
|
|||
{
|
||||
[self.vramWindow makeKeyAndOrderFront:sender];
|
||||
}
|
||||
|
||||
- (void) printImage:(uint32_t *)imageBytes height:(unsigned) height
|
||||
topMargin:(unsigned) topMargin bottomMargin: (unsigned) bottomMargin
|
||||
exposure:(unsigned) exposure
|
||||
{
|
||||
uint32_t paddedImage[160 * (topMargin + height + bottomMargin)];
|
||||
memset(paddedImage, 0xFF, sizeof(paddedImage));
|
||||
memcpy(paddedImage + (160 * topMargin), imageBytes, 160 * height * sizeof(imageBytes[0]));
|
||||
if (!self.printerFeedWindow.isVisible) {
|
||||
currentPrinterImageData = [[NSMutableData alloc] init];
|
||||
}
|
||||
[currentPrinterImageData appendBytes:paddedImage length:sizeof(paddedImage)];
|
||||
self.feedImageView.image = [Document imageFromData:currentPrinterImageData
|
||||
width:160
|
||||
height:currentPrinterImageData.length / 160 / sizeof(imageBytes[0])
|
||||
scale:2.0];
|
||||
/* UI related code must run on main thread. */
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSRect frame = self.printerFeedWindow.frame;
|
||||
frame.size = self.feedImageView.image.size;
|
||||
frame.size.height += self.printerFeedWindow.frame.size.height - self.printerFeedWindow.contentView.frame.size.height;
|
||||
[self.printerFeedWindow setMaxSize:frame.size];
|
||||
[self.printerFeedWindow setFrame:frame display:NO animate: self.printerFeedWindow.isVisible];
|
||||
[self.printerFeedWindow orderFront:NULL];
|
||||
});
|
||||
|
||||
}
|
||||
- (IBAction)savePrinterFeed:(id)sender
|
||||
{
|
||||
bool shouldResume = running;
|
||||
[self stop];
|
||||
NSSavePanel * savePanel = [NSSavePanel savePanel];
|
||||
[savePanel setAllowedFileTypes:@[@"png"]];
|
||||
[savePanel beginSheetModalForWindow:self.printerFeedWindow completionHandler:^(NSInteger result){
|
||||
if (result == NSFileHandlingPanelOKButton) {
|
||||
[savePanel orderOut:self];
|
||||
CGImageRef cgRef = [self.feedImageView.image CGImageForProposedRect:NULL
|
||||
context:nil
|
||||
hints:nil];
|
||||
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgRef];
|
||||
[imageRep setSize:(NSSize){160, self.feedImageView.image.size.height / 2}];
|
||||
NSData *data = [imageRep representationUsingType:NSPNGFileType properties:@{}];
|
||||
[data writeToURL:savePanel.URL atomically:NO];
|
||||
[self.printerFeedWindow setIsVisible:NO];
|
||||
}
|
||||
if (shouldResume) {
|
||||
[self start];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)disconnectAllAccessories:(id)sender
|
||||
{
|
||||
[self performAtomicBlock:^{
|
||||
accessory = GBAccessoryNone;
|
||||
GB_disconnect_serial(&gb);
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)connectPrinter:(id)sender
|
||||
{
|
||||
[self performAtomicBlock:^{
|
||||
accessory = GBAccessoryPrinter;
|
||||
GB_connect_printer(&gb, printImage);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
|
@ -10,6 +10,8 @@
|
|||
<outlet property="consoleInput" destination="l22-S8-uji" id="Heu-am-YgB"/>
|
||||
<outlet property="consoleOutput" destination="doS-dM-hnl" id="Gn5-ju-Wb0"/>
|
||||
<outlet property="consoleWindow" destination="21F-Ah-yHX" id="eQ4-ug-LsT"/>
|
||||
<outlet property="feedImageView" destination="Ar0-nN-eop" id="wHa-St-o4G"/>
|
||||
<outlet property="feedSaveButton" destination="RLc-0I-sYZ" id="Yy9-dG-xXY"/>
|
||||
<outlet property="gridButton" destination="fL6-2S-Rgd" id="jtV-jh-GHC"/>
|
||||
<outlet property="mainWindow" destination="xOd-HO-29H" id="h8M-YB-vcC"/>
|
||||
<outlet property="memoryBankInput" destination="rdV-q6-hc6" id="KBx-9T-2mX"/>
|
||||
|
@ -17,6 +19,7 @@
|
|||
<outlet property="memoryView" destination="8hr-8o-3rN" id="fF0-rh-8ND"/>
|
||||
<outlet property="memoryWindow" destination="mRm-dL-mCj" id="VPR-lu-vtI"/>
|
||||
<outlet property="paletteTableView" destination="gfC-d3-dmq" id="fTC-eL-Qg3"/>
|
||||
<outlet property="printerFeedWindow" destination="NdE-0B-WCf" id="yVK-cS-NOJ"/>
|
||||
<outlet property="spritesTableView" destination="TOc-XJ-w9w" id="O4R-4Z-9hU"/>
|
||||
<outlet property="tilemapImageView" destination="LlK-tV-bjv" id="nSY-Xd-BjZ"/>
|
||||
<outlet property="tilemapMapButton" destination="YIJ-Qc-SIZ" id="BB7-Gg-7XP"/>
|
||||
|
@ -32,7 +35,7 @@
|
|||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="xOd-HO-29H" userLabel="Window">
|
||||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="xOd-HO-29H" userLabel="Window">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
|
||||
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
|
@ -679,5 +682,35 @@
|
|||
<contentBorderThickness minY="24"/>
|
||||
<point key="canvasLocation" x="182" y="760"/>
|
||||
</window>
|
||||
<window title="Printer Feed" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" hidesOnDeactivate="YES" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="NdE-0B-WCf" customClass="NSPanel">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="272" y="172" width="320" height="288"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="RRS-aa-bPT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="288"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" id="Ar0-nN-eop" customClass="GBImageView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="288"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageAlignment="topLeft" id="sff-hk-4nM"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
</view>
|
||||
<point key="canvasLocation" x="-159" y="356"/>
|
||||
</window>
|
||||
<button verticalHuggingPriority="750" id="RLc-0I-sYZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="48" height="25"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="roundTextured" title="Save" bezelStyle="texturedRounded" alignment="center" controlSize="mini" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="shw-MJ-B3T">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="miniSystem"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="savePrinterFeed:" target="-2" id="Y3g-fU-2te"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="-507" y="397"/>
|
||||
</button>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
|
@ -339,6 +339,25 @@
|
|||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Connectivity" id="IcW-ZC-4wb">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Connectivity" id="BDM-Cv-BOm">
|
||||
<items>
|
||||
<menuItem title="None" id="SiH-Q4-OBY">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="disconnectAllAccessories:" target="-1" id="5hY-9U-nRn"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="GameBoy Printer" id="zHR-Ha-pOR">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="connectPrinter:" target="-1" id="tl1-CL-tAw"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Developer" id="IwX-DJ-dBk">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Developer" id="UVb-cc-at0">
|
||||
|
|
Loading…
Reference in New Issue