1 /*****************************************************************************\
2      Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3                 This file is licensed under the Snes9x License.
4    For further information, consult the LICENSE file in the root directory.
5 \*****************************************************************************/
6 
7 /***********************************************************************************
8   SNES9X for Mac OS (c) Copyright John Stiles
9 
10   Snes9x for Mac OS X
11 
12   (c) Copyright 2001 - 2011  zones
13   (c) Copyright 2002 - 2005  107
14   (c) Copyright 2002         PB1400c
15   (c) Copyright 2004         Alexander and Sander
16   (c) Copyright 2004 - 2005  Steven Seeger
17   (c) Copyright 2005         Ryan Vogt
18  ***********************************************************************************/
19 
20 
21 #include "port.h"
22 
23 #include "mac-prefix.h"
24 #include "mac-os.h"
25 #include "mac-gworld.h"
26 
27 #define kIconSize	16
28 
29 static void SetIconImage (CGImageRef, CGRect, int);
30 #ifdef MAC_PANTHER_SUPPORT
31 static IconRef CreateIconRefFromImage (CGImageRef, CGRect);
32 #endif
33 
34 
DrawSubCGImage(CGContextRef ctx,CGImageRef image,CGRect src,CGRect dst)35 void DrawSubCGImage (CGContextRef ctx, CGImageRef image, CGRect src, CGRect dst)
36 {
37     float	w = (float) CGImageGetWidth(image);
38     float	h = (float) CGImageGetHeight(image);
39 
40 	CGRect	drawRect = CGRectMake(0.0f, 0.0f, w, h);
41 
42 	if (!CGRectEqualToRect(src, dst))
43 	{
44 		float	sx = CGRectGetWidth(dst)  / CGRectGetWidth(src);
45 		float	sy = CGRectGetHeight(dst) / CGRectGetHeight(src);
46 		float	dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx);
47 		float	dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy);
48 
49 		drawRect = CGRectMake(dx, dy, w * sx, h * sy);
50 	}
51 
52 	CGContextSaveGState(ctx);
53 	CGContextClipToRect(ctx, dst);
54 	CGContextDrawImage(ctx, drawRect, image);
55 	CGContextRestoreGState(ctx);
56 }
57 
SetIconImage(CGImageRef image,CGRect rct,int n)58 static void SetIconImage (CGImageRef image, CGRect rct, int n)
59 {
60 	if (systemVersion >= 0x1040)
61 		macIconImage[n] = CGImageCreateWithImageInRect(image, rct);
62 #ifdef MAC_PANTHER_SUPPORT
63 	else
64 		macIconRef[n] = CreateIconRefFromImage(image, rct);
65 #endif
66 }
67 
CreateIconImages(void)68 void CreateIconImages (void)
69 {
70 	CGDataProviderRef	prov;
71 	CGImageRef			image;
72 	CFURLRef			url;
73 
74 	image = NULL;
75 	memset(macIconImage, 0, sizeof(macIconImage));
76 #ifdef MAC_PANTHER_SUPPORT
77 	if (systemVersion < 0x1040)
78 		memset(macIconRef, 0, sizeof(macIconRef));
79 #endif
80 
81 	url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("icons"),  CFSTR("png"), NULL);
82 	if (url)
83 	{
84 		prov = CGDataProviderCreateWithURL(url);
85 		if (prov)
86 		{
87 			image = CGImageCreateWithPNGDataProvider(prov, NULL, true, kCGRenderingIntentDefault);
88 			CGDataProviderRelease(prov);
89 		}
90 
91 		CFRelease(url);
92 	}
93 
94 	if (image)
95 	{
96 		int	x, y, v = 0, n = 0;
97 
98 		macPadIconIndex = n;
99 		for (y = 0; y < 8; y++)
100 		{
101 			for (x = 0; x < 12; x++)
102 				SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++);
103 			v += kIconSize;
104 		}
105 
106 		macLegendIconIndex = n;
107 		for (x = 0; x < 2; x++)
108 			SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++);
109 		v += kIconSize;
110 
111 		macMusicBoxIconIndex = n;
112 		for (x = 0; x < 3; x++)
113 			SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++);
114 		v += kIconSize;
115 
116 		macFunctionIconIndex = n;
117 		for (x = 0; x < 17; x++)
118 			SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++);
119 
120 		CGImageRelease(image);
121 
122 	#ifdef MAC_PANTHER_SUPPORT
123 		if (systemVersion < 0x1040)
124 		{
125 			CGColorSpaceRef		color;
126 			CGContextRef		ctx;
127 			CGRect				rct;
128 			static UInt32		data[2][kIconSize * kIconSize];
129 
130 			rct = CGRectMake(0, 0, kIconSize, kIconSize);
131 
132 			color = CGColorSpaceCreateDeviceRGB();
133 			if (color)
134 			{
135 				for (int i = 0; i < 2; i++)
136 				{
137 					ctx = CGBitmapContextCreate(data[i], kIconSize, kIconSize, 8, kIconSize * 4, color, kCGImageAlphaNoneSkipFirst);
138 					if (ctx)
139 					{
140 						PlotIconRefInContext(ctx, &rct, kAlignNone, kTransformNone, NULL, kPlotIconRefNormalFlags, macIconRef[macLegendIconIndex + i]);
141 						CGContextRelease(ctx);
142 
143 						prov = CGDataProviderCreateWithData(NULL, data[i], kIconSize * kIconSize * 4, NULL);
144 						if (prov)
145 						{
146 							macIconImage[macLegendIconIndex + i] = CGImageCreate(kIconSize, kIconSize, 8, 32, kIconSize * 4, color, kCGImageAlphaNoneSkipFirst, prov, NULL, 1, kCGRenderingIntentDefault);
147 							CGDataProviderRelease(prov);
148 						}
149 					}
150 				}
151 
152 				CGColorSpaceRelease(color);
153 			}
154 		}
155 	#endif
156 	}
157 }
158 
ReleaseIconImages(void)159 void ReleaseIconImages (void)
160 {
161 	for (int i = 0; i < 118; i++)
162 	{
163 		if (systemVersion >= 0x1040)
164 		{
165 			if (macIconImage[i])
166 				CGImageRelease(macIconImage[i]);
167 		}
168 	#ifdef MAC_PANTHER_SUPPORT
169 		else
170 		{
171 			if (macIconRef[i])
172 				ReleaseIconRef(macIconRef[i]);
173 		}
174 	#endif
175 	}
176 
177 #ifdef MAC_PANTHER_SUPPORT
178 	if (systemVersion < 0x1040)
179 	{
180 		if (macIconImage[macLegendIconIndex])
181 			CGImageRelease(macIconImage[macLegendIconIndex]);
182 		if (macIconImage[macLegendIconIndex + 1])
183 			CGImageRelease(macIconImage[macLegendIconIndex + 1]);
184 	}
185 #endif
186 }
187 
188 #ifdef MAC_PANTHER_SUPPORT
CreateIconRefFromImage(CGImageRef srcImage,CGRect srcRect)189 static IconRef CreateIconRefFromImage (CGImageRef srcImage, CGRect srcRect)
190 {
191 	OSStatus			err;
192 	CGContextRef		cctx, actx;
193 	CGColorSpaceRef		color;
194 	CGRect				dstRect;
195 	IconRef				iconRef;
196 	IconFamilyHandle	icns;
197 	Handle				hdl;
198 	SInt32				size;
199 	UInt32				rgb[kIconSize * kIconSize];
200 	UInt8				alp[kIconSize * kIconSize];
201 
202 	srcRect.origin.y = CGImageGetHeight(srcImage) - srcRect.origin.y - kIconSize;
203 
204 	color = CGColorSpaceCreateDeviceRGB();
205 	if (color)
206 	{
207 		cctx = CGBitmapContextCreate(rgb, kIconSize, kIconSize, 8, kIconSize * 4, color, kCGImageAlphaNoneSkipFirst);
208 		if (cctx)
209 		{
210 			dstRect = CGRectMake(0, 0, kIconSize, kIconSize);
211 			DrawSubCGImage(cctx, srcImage, srcRect, dstRect);
212 
213 			actx = CGBitmapContextCreate(alp, kIconSize, kIconSize, 8, kIconSize, NULL, kCGImageAlphaOnly);
214 			if (actx)
215 			{
216 				DrawSubCGImage(actx, srcImage, srcRect, dstRect);
217 				CGContextRelease(actx);
218 			}
219 
220 			CGContextRelease(cctx);
221 		}
222 
223 		CGColorSpaceRelease(color);
224 	}
225 
226 	iconRef = NULL;
227 
228 	size = sizeof(OSType) + sizeof(SInt32);
229 	icns = (IconFamilyHandle) NewHandle(size);
230 	if (icns)
231 	{
232 		// Big-endian: Panther is for PowerPC only
233 		(*icns)->resourceType = kIconFamilyType;
234 		(*icns)->resourceSize = size;
235 
236 		err = PtrToHand(rgb, &hdl, sizeof(rgb));
237 		if (err == noErr)
238 		{
239 			err = SetIconFamilyData(icns, kSmall32BitData, hdl);
240 			DisposeHandle(hdl);
241 
242 			if (err == noErr)
243 			{
244 				err = PtrToHand(alp, &hdl, sizeof(alp));
245 				if (err == noErr)
246 				{
247 					err = SetIconFamilyData(icns, kSmall8BitMask, hdl);
248 					DisposeHandle(hdl);
249 				}
250 			}
251 		}
252 
253 		if (err == noErr)
254 			err = GetIconRefFromIconFamilyPtr(*icns, GetHandleSize((Handle) icns), &iconRef);
255 
256 		DisposeHandle((Handle) icns);
257 	}
258 
259 	return (iconRef);
260 }
261 #endif
262