Printer support in Cocoa

This commit is contained in:
Lior Halphon 2017-01-13 22:26:44 +02:00
parent 527ae01e0e
commit 613d3b2e82
4 changed files with 152 additions and 3 deletions

View File

@ -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;

View File

@ -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

View File

@ -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>

View File

@ -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">