Mednafen 0.9.19-WIP [message #2399] |
Mon, 30 January 2012 01:02 |
|
Especially notable end-user-visible changes with this release:
- Improved PSX emulation.
- GameBoy system type selection(though not completely implemented for the case of selecting CGB for a DMG game).
- For NES emulation, improved iNES mapper 69 expansion sound emulation accuracy.
- Default video settings that make more sense with modern desktop PC setups.
- Experimental support for interpolation on only one axis without the use of a pixel shader, via new values for the <system>.videoip setting.
- New pixel shaders "autoip" and "autoipsharper", and a different algorithm for "ipsharper", "ipxnotysharper", and "ipynotxsharper".
- New video stretch modes, "aspect_int" and "aspect_mult2".
- Changed "video.glvsync" setting semantics to make forcibly disabling vsync simpler.
- Added new setting "video.blit_timesync", which can be set to 0 to reduce video latency by up to 1 frame, though with caveats.
- Support for screen rotation for all supported emulated systems, and remapped the rotate button from "F8" to "ALT + O".
- Increased the maximum supported sound output rate to 1048576 Hz.
- Win32 build now compiled with gcc 4.5.4-prerelease(with flag -mstackrealign for the time being to work around a memory alignment issue, which may hurt performance).
The following settings have changed semantics and/or allowed values:
- <system>.pixshader
- <system>.stretch
- sound.rate
- video.glvsync
- Various PSX settings.
The following settings have been added:
- gb.system_type
- video.blit_timesync
- wswan.language
- Various PSX settings.
The following settings have been renamed:
- command.rotatescreen -> command.rotate_screen
The following settings have been removed:
mednafen-0.9.19-wip-win32.zip
SHA1: 6f0505f06663c549d90083e0bb843b1c52928de4
mednafen-0.9.19-wip.tar.bz2
SHA1: 319ecb59cfca1baa9e733cb695186cc86f36151a
[Updated on: Fri, 14 November 2014 21:54]
|
|
Re: Mednafen 0.9.19-WIP [message #2402 is a reply to message #2399 ] |
Mon, 30 January 2012 03:43 |
|
As always, a great job
|
|
Re: Mednafen 0.9.19-WIP [message #2408 is a reply to message #2399 ] |
Thu, 02 February 2012 16:27 |
|
FTBFS on Arch Linux 64-bit, C++ casting rules ftw
file.cpp: In member function 'bool MDFNFILE::MakeMemWrapAndClose(void*, int)':
file.cpp:296:72: error: invalid conversion from 'void*' to 'gzFile' [-fpermissive]
/usr/include/zlib.h:1290:21: error: initializing argument 1 of 'int gzread(gzFile, voidp, unsigned int)' [-fpermissive]
file.cpp:323:43: error: invalid conversion from 'void*' to 'gzFile' [-fpermissive]
/usr/include/zlib.h:1513:30: error: initializing argument 1 of 'const char* gzerror(gzFile, int*)' [-fpermissive]
file.cpp:368:13: error: invalid conversion from 'void*' to 'gzFile' [-fpermissive]
/usr/include/zlib.h:1488:24: error: initializing argument 1 of 'int gzclose(gzFile)' [-fpermissive]
|
|
Re: Mednafen 0.9.19-WIP [message #2410 is a reply to message #2399 ] |
Thu, 02 February 2012 16:48 |
|
Thanks for the updates
For the Debian package I'm using a few patches, the first two of which may be useful more generally.
The first allows building with strict format checking:
--- mednafen.orig/src/ngp/TLCS-900h/TLCS900h_disassemble.cpp
+++ mednafen/src/ngp/TLCS-900h/TLCS900h_disassemble.cpp
@@ -209,7 +209,7 @@
if (size == 0 && first == 0xC7)
{
- sprintf(str_r, extra);
+ sprintf(str_r, "%s", extra);
return;
}
The second is just for a spelling mistake ("conjunction" rather than "conjuction"):
--- mednafen.orig/src/vb/vb.cpp
+++ mednafen/src/vb/vb.cpp
@@ -969,7 +969,7 @@
static const MDFNSetting_EnumList VB3DMode_List[] =
{
- { "anaglyph", VB3DMODE_ANAGLYPH, gettext_noop("Anaglyph"), gettext_noop("Used in conjuction with classic dual-lens-color glasses.") },
+ { "anaglyph", VB3DMODE_ANAGLYPH, gettext_noop("Anaglyph"), gettext_noop("Used in conjunction with classic dual-lens-color glasses.") },
{ "cscope", VB3DMODE_CSCOPE, gettext_noop("CyberScope"), gettext_noop("Intended for use with the CyberScope 3D device.") },
{ "sidebyside", VB3DMODE_SIDEBYSIDE, gettext_noop("Side-by-Side"), gettext_noop("The left-eye image is displayed on the left, and the right-eye image is displayed on the right.") },
// { "overunder", VB3DMODE_OVERUNDER },
I've also got a larger patch which drops the bundled tremor code in favour of using the separate library package (so that security updates to the latter don't require rebuilds of the mednafen package). If you're interested I can post it (it's also available at http://patch-tracker.debian.org/package/mednafen/0.9.19-1 along with the other patches).
Regards,
Stephen
|
|
Re: Mednafen 0.9.19-WIP [message #2411 is a reply to message #2399 ] |
Sun, 05 February 2012 13:41 |
|
For what it's worth, the build failure reported by Themaister is caused by gzFile not being a typedef of voidp anymore in zlib-1.2.6. Ran into this one myself. Here's the fix:
diff --git a/src/file.cpp b/src/file.cpp
index 57f4e13..ec1181c 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -293,7 +293,7 @@ bool MDFNFILE::MakeMemWrapAndClose(void *tz, int type)
goto doret;
}
- while((howmany = gzread(tz, f_data + cur_size, cur_alloced - cur_size)) > 0)
+ while((howmany = gzread((gzFile)tz, f_data + cur_size, cur_alloced - cur_size)) > 0)
{
cur_size += howmany;
cur_alloced <<= 1;
@@ -320,7 +320,7 @@ bool MDFNFILE::MakeMemWrapAndClose(void *tz, int type)
{
int gzerrnum = 0;
const char *gzerrstring;
- if((gzerrstring = gzerror(tz, &gzerrnum)) && gzerrnum != Z_OK && gzerrnum != Z_STREAM_END)
+ if((gzerrstring = gzerror((gzFile)tz, &gzerrnum)) && gzerrnum != Z_OK && gzerrnum != Z_STREAM_END)
{
if(gzerrnum != Z_ERRNO)
{
@@ -365,7 +365,7 @@ bool MDFNFILE::MakeMemWrapAndClose(void *tz, int type)
}
else if(type == MDFN_FILETYPE_GZIP)
{
- gzclose(tz);
+ gzclose((gzFile)tz);
}
else if(type == MDFN_FILETYPE_ZIP)
{
In addition, there is a build failure with --disable-debugger due to one debug line not being properly ifdef'd. Here's the fix:
diff --git a/src/psx/gpu.cpp b/src/psx/gpu.cpp
index 78fb66f..107cab0 100644
--- a/src/psx/gpu.cpp
+++ b/src/psx/gpu.cpp
@@ -1068,7 +1068,9 @@ pscpu_timestamp_t PS_GPU::Update(const pscpu_timestamp_t sys_timestamp)
PSX_RequestMLExit();
}
+#ifdef WANT_DEBUGGER
DBG_GPUScanlineHook(scanline);
+#endif
// printf("[GPU] DTA scanline=%3d --- %8d\n", scanline, DrawTimeAvail);
|
|
Re: Mednafen 0.9.19-WIP [message #2413 is a reply to message #2399 ] |
Sun, 12 February 2012 22:35 |
|
Administrator wrote on Mon, 30 January 2012 01:02 | The following settings have been removed:
|
Appreciate the update (as always), but why was the above option removed? It's necessary for at least some patched PC-FX games. I had to set cdrom.lec_eval=0 to play them, otherwise I get a "uncorrectable data at sector X" error. As of 0.9.19, it's no longer possible to play them.
Can you please reintroduce this option for those of us that'd like to play patched (ie., translated) PC-FX games? or, if there's some reason this option really needs to be removed, rework the logic so that mednafen's more forgiving when dealing with patched PC-FX games?
|
|
Re: Mednafen 0.9.19-WIP [message #2414 is a reply to message #2399 ] |
Mon, 13 February 2012 11:04 |
|
It's not going to be re-added, it's a bad setting that promotes the propagation of broken patches and broken patched games, that will likely not function properly when burned to disc and played on the real thing(or may work with some burners and some burning software, and not others).
I shouldn't have added the setting in the first place, but hindsight is 20/20 and all that.
[Updated on: Mon, 13 February 2012 11:13]
|
|
Re: Mednafen 0.9.19-WIP [message #2415 is a reply to message #2414 ] |
Mon, 13 February 2012 20:26 |
|
That's a fair point, and given I agree wholeheartedly byuu's SNES emulation crusade I can't exactly disagree here. Accurate emulation is definitely better in the long run than sloppy emulation.
but...
There's one big difference here between SNES emulation and PC-FX emulation: until the rest of the hackers come around to seeing the light, there are other SNES emulators available that I can use to play stuff that doesn't work in bsnes (I keep a copy of snes9x installed for this very reason - I only use it for, I think, three games, but it's handy). With PC-FX, however, there are no other options, at least not under Linux (and I'm not even aware of anything for Windows, unless Magic Engine also does PC-FX). Given that, mednafen is my *only* option to play PC-FX games, and as I can't speak or read Japanese, patched games are my only option if I want to actually understand them.
I doubt this is going to change your mind on the option, as you obviously have good reasons for making this decision, but is there anything you can suggest for those of us that were, unfortunately, relying on this functionality? Could it perhaps be an undocumented, but still supported legacy option? or maybe a compile-time option so that only the especially dedicated will bother?
|
|
Re: Mednafen 0.9.19-WIP [message #2420 is a reply to message #2399 ] |
Fri, 17 February 2012 03:06 |
|
Hi,
GLSL Pixel Shaders do not work on Linux or OSX 10.7
I tested a little fix on OSX 10.7.2 w/ NVIDIA GeForce 8600GT and on Linux Debian w/ Opensource Nouveau Driver.
diff -Naur mednafen.orig/mednafen/drivers/shader.cpp mednafen.wip/mednafen/drivers/shader.cpp
--- mednafen.orig/mednafen/drivers/shader.cpp 2012-01-26 04:04:57.000000000 +0100
+++ mednafen.wip/mednafen/drivers/shader.cpp 2012-02-08 10:34:38.000000000 +0100
@@ -70,7 +70,7 @@
switch(ipolate_axis & 3)
{
case 0:
- ret += std::string("gl_FragColor = texture2D(Tex0, gl_TexCoord[0]);\n");
+ ret += std::string("gl_FragColor = texture2D(Tex0, vec2(gl_TexCoord[0]));\n");
break;
case 1:
I did not test the patch on Windows, because I don't have a windows machine available with a decent graphic card, so I do not know if I broke something else
|
|
Re: Mednafen 0.9.19-WIP [message #2421 is a reply to message #2399 ] |
Fri, 17 February 2012 04:16 |
|
Hi all,
I am amazed how good mednafen is cominig out. Especially now that it has Genesis support (quite the fanboy here )
I had MANY genesis roms that were encoded in the old .smd format and since mednafen does not load these roms for now, here's my take on the subject.
The patch is 100% working, albeit a *little* messy.
Attached is also a little tool to convert smd roms into bin formatted roms.
EDIT 1/3/2012:
I spotted a couple of stupid bugs... attached is the updated patch.
Cheers
[Updated on: Fri, 02 March 2012 03:26]
|
|
Re: Mednafen 0.9.19-WIP [message #2449 is a reply to message #2421 ] |
Thu, 22 March 2012 21:54 |
|
I'm not able to get this WIP to build with clang:
Toggle SpoilerIn file included from src/cartridge/cartridge.cpp:1:
In file included from ../../src/snes/src/lib/../base.hpp:29:
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
In file included from interface.cpp:21:
In file included from ../../src/snes/src/lib/../base.hpp:29 friend class traits<C>::type;
^
:
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../system/system.hpp:31:22: note: in instantiation of template class 'nall::property<SNES::System>::readonly<unsigned int>' requested here
../../src/snes/src/lib/../system/system.hpp:31: readonly<unsigned> region;22
: ^
note: in instantiation of template class 'nall::property<SNES::System>::readonly<unsigned int>' requested here
readonly<unsigned> region;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: ../../src/snes/src/lib/nall/property.hppdeclared here:
53:52 template<typename T> struct traits { typedef T type; };:
^note:
declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:50:18: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<bool>' requested here
readonly<bool> loaded; //is a base cartridge inserted?
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:50:18: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<bool>' requested here
readonly<bool> loaded; //is a base cartridge inserted?
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:51:22: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<unsigned int>' requested here
:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:51:22: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<unsigned int>' requested here
readonly<unsigned> crc32; //crc32 of all cartridges (base+slot(s))
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
readonly<unsigned> crc32; //crc32 of all cartridges (base+slot(s))
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:53:18: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Mode>' requested here
readonly<Mode> mode;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:53:18: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Mode>' requested here
readonly<Mode> mode;64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:54:18: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Type>' requested here
readonly<Type> type;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:55:20: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Region>' requested here
readonly<Region> region;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:56:26: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::MemoryMapper>' requested here
readonly<MemoryMapper> mapper;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:57:30: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::DSP1MemoryMapper>' requested here
readonly<DSP1MemoryMapper> dsp1_mapper;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:54:18: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Type>' requested here
readonly<Type> type;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:55:20: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Region>' requested here
readonly<Region> region;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:56:26: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::MemoryMapper>' requested here
readonly<MemoryMapper> mapper;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
../../src/snes/src/lib/nall/property.hpp:64:31: error: elaborated type refers to a typedef
friend class traits<C>::type;
^
../../src/snes/src/lib/../cartridge/cartridge.hpp:57:30: note: in instantiation of template class 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::DSP1MemoryMapper>' requested here
readonly<DSP1MemoryMapper> dsp1_mapper;
^
../../src/snes/src/lib/nall/property.hpp:53:52: note: declared here
template<typename T> struct traits { typedef T type; };
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:4:15: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Type>'
type = TypeUnknown;
~~~~ ^ ~~~~~~~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:5:15: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::MemoryMapper>'
mapper = LoROM;
~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:6:15: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::DSP1MemoryMapper>'
dsp1_mapper = DSP1Unmapped;
~~~~~~~~~~~ ^ ~~~~~~~~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:7:15: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<SNES::Cartridge::Region>'
region = NTSC;
~~~~~~ ^ ~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:10:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_bsx_slot = false;
~~~~~~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:11:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_superfx = false;
~~~~~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:12:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_sa1 = false;
~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:13:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_srtc = false;
~~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:14:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_sdd1 = false;
~~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:15:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_spc7110 = false;
~~~~~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
In file included from src/cartridge/cartridge.cpp:8:
src/cartridge/header.cpp:16:18: error: 'operator=' is a private member of 'nall::property<SNES::Cartridge>::readonly<bool>'
has_spc7110rtc = false;
~~~~~~~~~~~~~~ ^ ~~~~~
../../src/snes/src/lib/nall/property.hpp:62:16: note: declared private here
const T& operator=(const T& value_) { return value = value_; }
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
8 errors generated.
make[2]: *** [interface.o] Error 1
make[2]: *** Waiting for unfinished jobs....
20 errors generated.
I'm using clang 3.1 on Mac OS X, as shipped with Xcode 4.3.2.
|
|