From 2b821936747c8e28ceb2190f464fd22c2e14f5db Mon Sep 17 00:00:00 2001 From: rogerman Date: Fri, 17 Aug 2012 06:56:35 +0000 Subject: [PATCH] Cocoa Port: - Rewrite the display code to be much more flexible (the OpenGL blitter now uses cached vertices instead of calculating the vertices per frame). - New feature: The DS screens can now be arranged horizontally as well as vertically. - New feature: The order of the DS screens can now be set. - Misc. code cleanup. --- desmume/src/cocoa/DefaultUserPrefs.plist | Bin 5064 -> 5051 bytes desmume/src/cocoa/cocoa_globals.h | 14 + desmume/src/cocoa/cocoa_output.h | 4 + desmume/src/cocoa/cocoa_output.mm | 30 + .../English.lproj/MainMenu.strings | Bin 263600 -> 270260 bytes .../translations/English.lproj/MainMenu.xib | 910 +++++++++++++++++- desmume/src/cocoa/userinterface/displayView.h | 30 +- .../src/cocoa/userinterface/displayView.mm | 367 +++++-- .../cocoa/userinterface/emuWindowDelegate.h | 2 + .../cocoa/userinterface/emuWindowDelegate.mm | 47 +- 10 files changed, 1295 insertions(+), 109 deletions(-) diff --git a/desmume/src/cocoa/DefaultUserPrefs.plist b/desmume/src/cocoa/DefaultUserPrefs.plist index 5a3c4c0ce01534c50f4a7dee7926ea4357bd3918..6b32facf2728947ce9d234658467de007e425745 100644 GIT binary patch delta 1089 zcmYjL3rv+|7(V|w|NnmX|N9OXQ9v}su!*MAVTW3XLPA72ZjLk#2hMMtdEn3i61Enk z8(G@2{*^W7^42B|Et9eY5k?{oZR9GlC`Pb#*`ykCEA7SsYkrsaeZTLyyzf9tXUe{v zPk0>Zj>t`Sq)l&+Bh#^d=AAwB@0qDRjz=8%xA6!w!jIq)MfS8}R_W1-Z)-AVaF4d- zmC-GU30Z-<+MutgBw+3E7S~xNR=7S;=?fM%)l}N|Y4hzm?Qm+`ourb0-wHhx2-aI+ zuX5)UXL$=OU$7`pZEXmKDz~3r=S^wvn~J@W#`#u#RmksEbMEN7Ayi!v@;(-xcC#n-I6KNn zv(Fjvc8;-PQE6m~Sw|HcG0Cl&o~||&^wkGKH4$t34P!Ci`oDk3Z+~v&I59b$1WTxv zZfB`yB_K=EA_LTO#c0lXUMztwtlrz=l?u6zR*D==_*JrNZ^cX!& ze^|Hlu>OMnw%(-=>J$1cW1(@ck!yI3CS#Xz!00vxjq3n_fkG5SLkz^i9EgLtFc0D( z5t3j5EQCd{7?NQL+zlzP6js4LI0(m~9o~lzpc8uG5_}3nFbvn=n`ZbHzK03;875&0 zZon-Bh$D$o(OR?)<)O`}5>=x{^ddTn+R?k{6zW3f(GVIzKcFe}H+JAC9E<1T<=BI> za6T@@e!LAg;#RyH@4<&~J3fPZ@MS!V$M6*X1OG)F#7*XtrDP4sAUUM@aZ*NnZckDz=?H!*(;9y~W;PCs_~cWBqKHjkC#Sc9R<% z@p(LvFW@Wr1AHSdWmq=IM){gNB-><%?2(t{ zmvT%_DXN5$Dqbb2yVQd!S8Y<8RfVcoEo!fNQyo#qRh#-qeXP!^PSvH(scv;%^{77e aiMpWrlhs8v;FwuX=WN!t&gTE38vhsLXeR*x delta 1141 zcmZWnZA=_R7{0yRot@9!IdZneLZLwU&`NDhpJdPr! z@suBa;771)>qj+8G-<5VAH4>unEF*(3Sw&s#SoKz?06G#L!0bKDoRovo<#N} zl#5>FNfdV3+(N_4mmW-Cwplmyh(Dxx9@CrJqk3Jfx7MgJ{Q+x(kZrXIy{nyD>MON6 z-5=T>Y}G45X44*xFRcu=g+u<%9YMWA+Yt=tW>qj0)g$q{>;;0=<;bgDR&9jaqgsV& zL?dP>q({8|a5!i@(x!1%*qz^#=`KQ$*K|s$iro zY7IE%x9;}cSFiaxjV7-iZ8ifMcP$=L-W~{=snTl(^aTAsx6S@=!@tc5jrF%!V%;MZ z=V<(OWOK>iaJ?D7OG2obTToGMjskl>Y6`vIkh<)O) zI4RCcl9VQuN>x&Wv{!mbdQBRXCZwx?gEZg*86Xp^09ha#tOPkA7vzC_PzZ{^Enqdc z4HSbl;C8SUtOFat8{jZF2KvD#;8QRJM!`7v7EFO@Fav&!fuF#yU>;ln*T4d}E=w|( zm&oaIiCivkmFs1{+$wj-UGgjPQMq6KNFJ0=%V*^&c~<^iUVso{m;tk34lIQg@LqU7 zY=Q<1!!FnZ_rnA52<(TS!x4B9PQy94fE-9h7%fKyXdT*ws!<(^1yD2EgPue$pjXj5 zs1FUGK{STO(IlEebLc9zV+E(?d!L_sMZ`f{c(ca-K|+-^jHX6{$*{G?(Vn zBI>49bQ^7?&Gd1)kH%;ZeUl!hae9)Trx)l1ouz-!1%{Z5WwEtvJ=?&lSv`A*g;)pc zWY4n~Sr6-FN7)H>ik)NMuo*VXeqnzpKyfOWN}+P6QmfP{^-7DfS9wb5Rt_q$UgbmO zGi68_Rz{WYl%JK$%5@d1R9&I2RP)sJYPnjYKA<+KE$Tisrgo`st4GwhdQu%xFRI_G zbLs+j@ufVS=kY>*E8oI>d>8lgP~sDI^Mm|d-p7yeIRAow$xrbiewv@*!~85C;iLR3 aKE}V!=jZqZK5k15yL}Ob#znl5`TRd?6+Gzx diff --git a/desmume/src/cocoa/cocoa_globals.h b/desmume/src/cocoa/cocoa_globals.h index f789bfd86..ed71c96c3 100644 --- a/desmume/src/cocoa/cocoa_globals.h +++ b/desmume/src/cocoa/cocoa_globals.h @@ -346,6 +346,8 @@ enum MESSAGE_REDRAW_VIEW, MESSAGE_SET_GPU_STATE_FLAGS, MESSAGE_CHANGE_DISPLAY_TYPE, + MESSAGE_CHANGE_DISPLAY_ORIENTATION, + MESSAGE_CHANGE_DISPLAY_ORDER, MESSAGE_CHANGE_BILINEAR_OUTPUT, MESSAGE_CHANGE_VERTICAL_SYNC, MESSAGE_CHANGE_VIDEO_FILTER, @@ -381,6 +383,18 @@ enum DS_DISPLAY_TYPE_COMBO }; +enum +{ + DS_DISPLAY_ORIENTATION_VERTICAL = 0, + DS_DISPLAY_ORIENTATION_HORIZONTAL +}; + +enum +{ + DS_DISPLAY_ORDER_MAIN_FIRST = 0, + DS_DISPLAY_ORDER_TOUCH_FIRST +}; + /* DS GPU TYPES */ diff --git a/desmume/src/cocoa/cocoa_output.h b/desmume/src/cocoa/cocoa_output.h index 052b027c1..98b3299b5 100644 --- a/desmume/src/cocoa/cocoa_output.h +++ b/desmume/src/cocoa/cocoa_output.h @@ -104,6 +104,8 @@ - (void) doResizeView:(NSRect)rect; - (void) doRedraw; - (void) doDisplayTypeChanged:(NSInteger)displayTypeID; +- (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID; +- (void) doDisplayOrderChanged:(NSInteger)displayOrderID; - (void) doBilinearOutputChanged:(BOOL)useBilinear; - (void) doVerticalSyncChanged:(BOOL)useVerticalSync; - (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID; @@ -164,6 +166,8 @@ - (void) handleRedrawView; - (void) handleChangeGpuStateFlags:(NSData *)flagsData; - (void) handleChangeDisplayType:(NSData *)displayTypeIdData; +- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData; +- (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData; - (void) handleChangeBilinearOutput:(NSData *)bilinearStateData; - (void) handleChangeVerticalSync:(NSData *)verticalSyncStateData; - (void) handleChangeVideoFilter:(NSData *)videoFilterTypeIdData; diff --git a/desmume/src/cocoa/cocoa_output.mm b/desmume/src/cocoa/cocoa_output.mm index 1dd477052..5ff0d3ff9 100644 --- a/desmume/src/cocoa/cocoa_output.mm +++ b/desmume/src/cocoa/cocoa_output.mm @@ -1053,6 +1053,14 @@ GPU3DInterface *core3DList[] = { [self handleChangeDisplayType:[messageComponents objectAtIndex:0]]; break; + case MESSAGE_CHANGE_DISPLAY_ORIENTATION: + [self handleChangeDisplayOrientation:[messageComponents objectAtIndex:0]]; + break; + + case MESSAGE_CHANGE_DISPLAY_ORDER: + [self handleChangeDisplayOrder:[messageComponents objectAtIndex:0]]; + break; + case MESSAGE_CHANGE_BILINEAR_OUTPUT: [self handleChangeBilinearOutput:[messageComponents objectAtIndex:0]]; break; @@ -1181,6 +1189,28 @@ GPU3DInterface *core3DList[] = { [delegate doDisplayTypeChanged:*theType]; } +- (void) handleChangeDisplayOrientation:(NSData *)displayOrientationIdData +{ + if (delegate == nil || ![delegate respondsToSelector:@selector(doDisplayOrientationChanged:)]) + { + return; + } + + const NSInteger *theOrientation = (NSInteger *)[displayOrientationIdData bytes]; + [delegate doDisplayOrientationChanged:*theOrientation]; +} + +- (void) handleChangeDisplayOrder:(NSData *)displayOrderIdData +{ + if (delegate == nil || ![delegate respondsToSelector:@selector(doDisplayOrderChanged:)]) + { + return; + } + + const NSInteger *theOrder = (NSInteger *)[displayOrderIdData bytes]; + [delegate doDisplayOrderChanged:*theOrder]; +} + - (void) handleChangeBilinearOutput:(NSData *)bilinearStateData { if (delegate == nil || ![delegate respondsToSelector:@selector(doBilinearOutputChanged:)]) diff --git a/desmume/src/cocoa/translations/English.lproj/MainMenu.strings b/desmume/src/cocoa/translations/English.lproj/MainMenu.strings index f66e4b31cf2abe76b1933cbba90aa5154f146f12..6fe6537a942f80de34119f952a1229120eebc986 100644 GIT binary patch delta 1366 zcmcJPO-NKx6vyv<=cOq$JwLMXjf~F(6%?7&n$bnfNVbxkv5-i!)TXk9+9(+jG08xX z5Tge?5G|@rn+ge6E-JMTON(&VA~1ty5rqjY`hxD7=6Lu2PMr{ZNPD9E0w(DO%DB zb4jCM1XP-?gQO*ez0g9A6;Q#+9CRuIIh6ehbkcp$X1dsR49cVhDP52)eQ+mbUF9}( zms+5S1!!c5SL1_{GD_HDVA3?j`ZO6WZnqEJgPAnh3C$1lkxJgfN*W%Schk#v ziXG=~@0NDpiY19l={mJHK_fbcTppQ9pK#)PjMAeg4qaWsy_DY0N@iB7?{q7B^7c?&K7fC`aNZ44P+cyGh@ zZ|$2r0)Ie&?_tN8pFBa)+_ULis~%)0L{S1_7}0{rZ$ImjJJDhpqEP)}9uTL|Sy*G% zoGqi*T#JtX&`{|#C$D@x0TQc34pAuoAFQiWiVB|mXXYGhs4 zlhyF2EIL@HpmAEVl0+msbCtpahqfkg_`dLUas0cuF(g3^D#u2+N`?Q;XAUCa9k$>yWX delta 17 Ycmdn8UtmMGKtl^-3sVd87M2aH06?1tP5=M^ diff --git a/desmume/src/cocoa/translations/English.lproj/MainMenu.xib b/desmume/src/cocoa/translations/English.lproj/MainMenu.xib index 6f77ed66c..b96457829 100644 --- a/desmume/src/cocoa/translations/English.lproj/MainMenu.xib +++ b/desmume/src/cocoa/translations/English.lproj/MainMenu.xib @@ -12,9 +12,9 @@ YES - + + - YES @@ -991,6 +991,70 @@ + + + Display Orientation + + 2147483647 + + + submenuAction: + + Display Orientation + + YES + + + Vertical + + 2147483647 + + + + + + Horizontal + + 2147483647 + + + 1 + + + + + + + Display Order + + 2147483647 + + + submenuAction: + + Display Order + + YES + + + Main Screen First + + 2147483647 + + + + + + Touch Screen First + + 2147483647 + + + 1 + + + + YES @@ -5095,7 +5159,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {1.79769e+308, 1.79769e+308} {256, 408} - + 256 YES @@ -5197,7 +5261,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {256, 408} - {{0, 0}, {1920, 1178}} {256, 476} @@ -7022,7 +7085,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA InputPrefsView - + 268 YES @@ -7036,7 +7099,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 1 - + 256 YES @@ -7430,7 +7493,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - {{6, 127}, {431, 116}} + {{6, 187}, {431, 116}} {0, 0} @@ -7450,8 +7513,498 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 2 NO + + + 12 + + YES + + + 274 + + YES + + + 12 + + YES + + + 274 + + YES + + + 268 + {{18, 14}, {100, 38}} + + YES + 2 + 1 + + YES + + -2080244224 + 0 + Vertical + + + 1211912703 + 0 + + + + 200 + 25 + + + 67239424 + 0 + Horizontal + + + 1 + 1211912703 + 0 + + 549453824 + {18, 18} + + YES + + YES + + + + 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 +AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA +AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1 +cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD +AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH +SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF +hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8 +vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt +7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq +Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo +aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e +n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX +2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW +FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O +Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6 +ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt +rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA +AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA +AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl +A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq +DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU +HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8 +MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v +UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/ +eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj +rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn +5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh +AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK +CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY +GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95 +MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S +UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2 +d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV +pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK +0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf// +AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw +BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA +FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H +LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh +Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ +h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp +svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb +1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX +8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE +AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg +QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA + + + + + + + + 400 + 75 + + + {100, 18} + {4, 2} + 1151868928 + NSActionCell + + 67239424 + 0 + Radio + + 1211912703 + 0 + + 549453824 + {18, 18} + + YES + + YES + + + + TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw +IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/ +29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5 +dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA +AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG +AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/ +0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/ +7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/ +5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/ +3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD +AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns +AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/ +6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/ +/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/ +///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl +YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA +AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD +AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu +AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB +AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES +AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABIAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS +AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + + + + + + + 400 + 75 + + + + + + + + {{1, 1}, {194, 62}} + + + + {{15, 10}, {196, 78}} + + {0, 0} + + 67239424 + 0 + Display Orientation + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + + + + 12 + + YES + + + 274 + + YES + + + 268 + {{18, 14}, {150, 38}} + + YES + 2 + 1 + + YES + + -2080244224 + 0 + Main Screen First + + + 1211912703 + 0 + + + + 200 + 25 + + + 67239424 + 0 + Touch Screen First + + + 1 + 1211912703 + 0 + + 549453824 + {18, 18} + + YES + + YES + + + + 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 +AAAAAF1KAAA0kQAACCVYWVogAAAAAAAAdCAAALRgAAAjPVhZWiAAAAAAAAAlbAAAFyoAAKfDWFlaIAAA +AAAAAPNSAAEAAAABFs9zZjMyAAAAAAABDEIAAAXe///zJgAAB5IAAP2R///7ov///aMAAAPcAADAbGN1 +cnYAAAAAAAAAAQHNAABjdXJ2AAAAAAAAAAEBzQAAY3VydgAAAAAAAAABAc0AAHZjZ3QAAAAAAAAAAAAD +AQAAAQACBAUGBwkKCw0ODxASExQWFxgaGxweHyAiIyQmJygpKywtLzAxMjM1Njc4OTs8PT5AQUJDREZH +SElKS0xOT1BRUlNUVVZXWFlaW1xdXl9hYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gIGCg4SF +hoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnZ6foKGio6SlpqanqKmqq6ytra6vsLGysrO0tba3uLi5uru8 +vL2+v8DBwcLDxMXGxsfIycrKy8zNzs7P0NHS0tPU1dbW19jZ2drb3Nzd3t/g4eLi4+Tl5ufo6enq6+zt +7u/w8fHy8/T19vf4+fr7/P3+/v8AAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR8gISIjJCUnKCkq +Ky0uLzAxMzQ1Njc4OTo7PD0/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaWltcXV5fYGFiY2RlZmdo +aWprbG1ub3BxcnN0dXZ3d3h5ent8fH1+f4CBgoKDhIWGh4iIiYqLjI2Oj5CRkpOUlJWWl5iZmpucnZ2e +n6ChoqOkpaamp6ipqqusra6vsLCxsrO0tba3uLm5uru8vb6/wMHCw8TFx8jJysvMzc7P0NDR0tPU1dbX +2Nna29ze3+Dh4uPk5ebn6err7O3u7/Hy8/T19vf5+vv8/f7/AAIDAwQFBgcICQoKCwwNDg8QERITFBUW +FxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODg5Ojs8PT4+P0BBQkNDREVGR0hJSUpLTE1O +Tk9QUVJSU1RVVVZXWFhZWltbXF1eXl9gYWFiY2RkZWZnZ2hpaWprbGxtbm5vcHFxcnNzdHV1dnd4eHl6 +ent8fH1+fn+AgYGCg4SEhYaHiImJiouMjY6Oj5CRkpOTlJWWl5iZmZqbnJ2en6ChoqOkpaanqKmqq6yt +rq+xsrO0tba3uLq7vL2+wMHDxMbHycrMzs/R0tTW19nb3d7g4uTm6Ors7vDy9Pb4+vz+/wAAbmRpbgAA +AAAAAAY2AACXGgAAVjoAAFPKAACJ3gAAJ8IAABaoAABQDQAAVDkAAiuFAAIZmQABeFEAAwEAAAIAAAAA +AAEABgANABcAIwAxAEAAUgBlAHsAkwCrAMUA4gD/AR8BPwFhAYUBqgHQAfgCIAJLAncCpQLSAwIDMwNl +A5gDzgQFBD0EdQSvBOsFKQVnBacF6AYqBm4GtQb8B0UHkgfkCDkIkAjnCT4JmAn0ClAKrQsLC2sLygwq +DIwM8Q1XDcAOKA6SDv4PbA/bEE0QxBE7EbQSMRKwEzITuRREFNAVYBXxFocXHhfAGGIZBBmsGlQa+RuU +HC4czh1yHhQeux9jIA0gvCFoIhkizyOJJEEk+SW6JnknOygFKMspkypiKzIsASzXLawuhy9gMD4xGzH8 +MtszvzSgNYY2cjdcOEw5OTorOxs8CD0EPfU+6z/nQOFB2ELUQ9VE00XcRttH5EjxSgBLCUwdTTFOUE9v +UI9Rt1LdVAVVNlZsV6VY4FohW21ct135X09goGH0Y0tkqGYFZ19oxGova5ptCG54b/BxbnLsdG119Xd/ +eQh6knwqfcV/W4D4gpSEO4Xih4CJKorYjIqOOY/jkZuTWJUOlsyYiZpSnB6d4Z+soX+jWqUvpxOo+6rj +rMuuwLC4sra0rra0uL+60LzfvwDBHcLdxLXGhchYyi7MCs3lz7rRmtOA1WPXR9kq2xPc/97s4M/iveSn +5o3obupT7ELuLPAM8fLz0PW396H5f/tZ/T3//wAAAAEAAwALABYAJQA3AE0AZQCBAJ8AwQDlAQsBNQFh +AZABwQH1AisCZAKfAtwDHANfA6MD6gQ0BH8EzQT1BR0FcAXEBhsGdAbPBy0HXAeMB+4IUgi4CSAJVAmK +CfYKZArVC0cLgQu8DDIMqw0mDaIOIQ6hDyQPqRAvELgQ/RFDEc8SXRLuE4AUFRSrFUMV3RZ5FxcXthhY +GPwZoRpIGvEbnBxJHPgdqB5bHw8fxSB9ITch8iKwJDAk8yW3Jn4nRigQKNwpqSp5K0osHCzxLccuoC95 +MFUxMzISMvMz1TS5NaA2hzdxOFw5STo4Oyg8Gj4DPvs/9EDuQepD6ETpRexG8Uf3SP9LFEwhTTBOQE9S +UGZSklOrVMVV4Vb/WB5ZP1phW4Vcq13SXvthUmJ/Y69k4GYSZ0dofGm0au1tZG6ib+FxInJlc6l073Y2 +d396FXtjfLJ+A39VgKmB/4NWhK+GCYjCiiGLgYzjjkePrJESknuT5Ja8mCuZm5sMnH+d9J9qoOGiWqPV +pVGmz6eOqE6pzqtRrNSuWq/gsWmy8rR+tgu5Kbq6vE294b93wQ7Cp8RBxd3He8kZyrrLisxbzf/Po9FK +0vHUm9ZF1/HZn9tO3Cbc/96x4GTiGePQ5YjnQegf6Pzquex27jbv9/G583z0X/VC9wj40Pqa/GX+Mf// +AAAAAQADAAsAJQA3AE0AZQCBAJ8AwQELATUBYQGQAcEB9QIrAmQCnwLcAxwDXwOjA+oENAR/BM0FHQVw +BcQGGwZ0Bs8HLQeMB+4IUgi4CSAJign2CmQK1QtHC7wMMgyrDSYNog4hDqEPJA+pEC8QuBFDEl0S7hOA +FBUUqxVDFnkXFxe2GFgY/BpIGvEbnBxJHPgdqB8PH8UgfSE3IfIjbyQwJPMltydGKBAo3Cp5K0osHC3H +LqAveTEzMhIy8zS5NaA2hzhcOUk6ODwaPQ4+Az/0QO5C6EPoROlG8Uf3SglLFEwhTkBPUlF7UpJUxVXh +Vv9ZP1phXKtd0mAlYVJjr2TgZhJofGm0au1tZG6ib+FxInJldO92Nnd/eMl6FXyyfgN/VYCpgf+Er4YJ +h2WIwoohi4GOR4+skRKSe5PklVCWvJgrmZubDJx/nfSfaqDholqj1aVRps+oTqnOq1Gs1K2Xrlqv4LFp +svK0frYLt5m5Kbnxurq8Tb3hv3fBDsHawqfEQcUPxd3He8hKyRnKusuKzFvN/87Rz6PQdtFK0vHTxtSb +1kXXG9fx2MjZn9tO3Cbc/93Y3rHfiuBk4hni9ePQ5KzliOZk50HoH+j86drqueuX7HbtVu427xbv9/DX +8bnymvN89F/1QvYl9wj37PjQ+bX6mvt//GX9S/4x//8AAGRlc2MAAAAAAAAACkNvbG9yIExDRAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAABIAAAAcAEMAbwBsAG8AcgAgAEwAQwBE +AABtbW9kAAAAAAAABhAAAJxOAAAAAL5zkQAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABDb3B5cmlnaHQg +QXBwbGUgQ29tcHV0ZXIsIEluYy4sIDIwMDUAAAAAA + + + + + + + + 400 + 75 + + + {150, 18} + {4, 2} + 1151868928 + NSActionCell + + 67239424 + 0 + Radio + + 1211912703 + 0 + + 549453824 + {18, 18} + + YES + + YES + + + + TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAADwRERGLJycnySsrK/A1NTXw +IyMjyRwcHIsJCQk8AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFFRUVdVBQUOCoqKj/ +29vb//n5+f/6+vr/2tra/6qqqv9UVFTgHx8fdQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUZGRl5 +dXV198PDw//8/Pz////////////////////////////U1NT/fHx89yUlJXkAAAAFAAAAAAAAAAAAAAAA +AAAAAxEREUZqamrmtbW1/+3t7f/+/v7//v7+//7+/v/9/f3//f39//39/f/39/f/xMTE/3d3d+YZGRlG +AAAAAwAAAAAAAAAAAAAACkJCQqGtra3/xsbG/+vr6//y8vL/9fX1//X19f/z8/P/9fX1//Ly8v/u7u7/ +0tLS/6+vr/9KSkqhAAAACgAAAAAAAAAAAAAAF3h4eN2/v7//z8/P/93d3f/q6ur/7+/v/+/v7//w8PD/ +7e3t/+3t7f/i4uL/zs7O/8XFxf98fHzdAAAAFwAAAAAAAAADAAAAJKSkpPjOzs7/2dnZ/+Dg4P/i4uL/ +5eXl/+bm5v/n5+f/5eXl/+Li4v/e3t7/2tra/9DQ0P+srKz4AAAAJAAAAAMAAAADAAAALrCwsPrW1tb/ +3t7e/+Tk5P/p6en/6+vr/+zs7P/p6en/6+vr/+fn5//k5OT/4ODg/9nZ2f+zs7P6AAAALgAAAAMAAAAD +AAAALp2dnezg4OD/5eXl/+rq6v/u7u7/8PDw//Dw8P/x8fH/8PDw/+7u7v/q6ur/5ubm/+Hh4f+ZmZns +AAAALgAAAAMAAAADAAAAJG5ubs/l5eX/6enp/+/v7//y8vL/9vb2//r6+v/5+fn/9/f3//b29v/x8fH/ +6+vr/+Tk5P9ra2vPAAAAJAAAAAMAAAAAAAAAFy4uLpPCwsL67Ozs//Pz8//5+fn//v7+//7+/v/+/v7/ +/v7+//v7+//19fX/8PDw/8LCwvosLCyTAAAAFwAAAAAAAAAAAAAACgAAAENfX1/S5OTk/vn5+f/+/v7/ +///////////////////////////8/Pz/5ubm/l9fX9IAAABDAAAACgAAAAAAAAAAAAAAAwAAABcAAABl +YmJi3NLS0v3////////////////////////////////V1dX9ZGRk3AAAAGUAAAAXAAAAAwAAAAAAAAAA +AAAAAAAAAAUAAAAfAAAAZTMzM8KAgIDwv7+//O3t7f/t7e3/v7+//ICAgPAzMzPCAAAAZQAAAB8AAAAF +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAFwAAAEMAAAB3AAAAnwAAALMAAACzAAAAnwAAAHcAAABD +AAAAFwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAAAXAAAAJAAAAC4AAAAu +AAAAJAAAABcAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAwAAAAMAAAADAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQEAAAMAAAABABIAAAEB +AAMAAAABABIAAAECAAMAAAAEAAAFugEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES +AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABABIAAAEXAAQAAAABAAAFEAEcAAMAAAABAAEAAAFS +AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + + + + + + + 400 + 75 + + + + + + + + {{1, 1}, {194, 62}} + + + + {{218, 10}, {196, 78}} + + {0, 0} + + 67239424 + 0 + Display Order + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + + + {{1, 1}, {429, 98}} + + + + {{6, 69}, {431, 114}} + + {0, 0} + + 67239424 + 0 + Combo Display Layout + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 0 + 2 + NO + {{10, 33}, {443, 355}} + Display Views @@ -7460,7 +8013,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 2 - + 256 YES @@ -7802,7 +8355,6 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA {{10, 33}, {443, 355}} - Video Output @@ -8317,18 +8869,19 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - + 0 YES YES YES - + {489, 425} + NSView @@ -19254,6 +19807,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeLogPath versionString dateString + DisplayViewCombo_Order @@ -19530,6 +20084,11 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES + + YES + DisplayViewCombo_Orientation + DisplayViewCombo_Order + YES @@ -28302,6 +28861,70 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 6167 + + + changeDisplayOrientation: + + + + 6175 + + + + changeDisplayOrientation: + + + + 6176 + + + + changeDisplayOrder: + + + + 6178 + + + + changeDisplayOrder: + + + + 6179 + + + + selectedTag: values.DisplayViewCombo_Orientation + + + + + + selectedTag: values.DisplayViewCombo_Orientation + selectedTag + values.DisplayViewCombo_Orientation + 2 + + + 6226 + + + + selectedTag: values.DisplayViewCombo_Order + + + + + + selectedTag: values.DisplayViewCombo_Order + selectedTag + values.DisplayViewCombo_Order + 2 + + + 6230 + @@ -28562,6 +29185,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + @@ -30614,6 +31239,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA YES + @@ -38689,6 +39315,144 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA + + 6168 + + + YES + + + + + + 6169 + + + YES + + + + + + + 6170 + + + + + 6171 + + + YES + + + + + + 6172 + + + YES + + + + + + + 6173 + + + + + 6174 + + + + + 6177 + + + + + 6180 + + + YES + + + + + + + 6182 + + + YES + + + + + + 6183 + + + YES + + + + + + 6184 + + + YES + + + + + + + + 6185 + + + + + 6186 + + + + + 6187 + + + + + 6188 + + + YES + + + + + + + + 6189 + + + + + 6190 + + + + + 6191 + + + @@ -40584,6 +41348,37 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA 6161.IBAttributePlaceholdersKey 6161.IBPluginDependency 6162.IBPluginDependency + 6168.IBPluginDependency + 6169.IBEditorWindowLastContentRect + 6169.IBPluginDependency + 6170.IBPluginDependency + 6171.IBPluginDependency + 6172.IBEditorWindowLastContentRect + 6172.IBPluginDependency + 6173.IBPluginDependency + 6174.IBPluginDependency + 6177.IBPluginDependency + 6180.IBEditorWindowLastContentRect + 6180.IBPluginDependency + 6180.IBViewBoundsToFrameTransform + 6182.IBPluginDependency + 6182.IBViewBoundsToFrameTransform + 6183.IBPluginDependency + 6183.IBViewBoundsToFrameTransform + 6184.IBPluginDependency + 6184.IBViewBoundsToFrameTransform + 6185.IBAttributePlaceholdersKey + 6185.IBPluginDependency + 6186.IBAttributePlaceholdersKey + 6186.IBPluginDependency + 6187.IBPluginDependency + 6188.IBPluginDependency + 6188.IBViewBoundsToFrameTransform + 6189.IBPluginDependency + 6190.IBAttributePlaceholdersKey + 6190.IBPluginDependency + 6191.IBAttributePlaceholdersKey + 6191.IBPluginDependency 627.IBEditorWindowLastContentRect 627.IBPluginDependency 627.IBWindowTemplateEditedContentRect @@ -41357,7 +42152,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{712, 677}, {489, 425}} + {{858, 521}, {489, 425}} com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -42070,7 +42865,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA P4AAAL+AAABBiAAAwswAAA - {{475, 1136}, {512, 20}} + {{757, 1136}, {512, 20}} com.apple.InterfaceBuilder.CocoaPlugin {74, 862} @@ -42085,7 +42880,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA P4AAAL+AAABBiAAAw6WAAA com.apple.InterfaceBuilder.CocoaPlugin - {{749, 883}, {315, 253}} + {{1031, 843}, {315, 293}} com.apple.InterfaceBuilder.CocoaPlugin {{475, 832}, {234, 43}} com.apple.InterfaceBuilder.CocoaPlugin @@ -43731,7 +44526,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - AUDAAABDUwAAA + AUDAAABDbwAAA com.apple.InterfaceBuilder.CocoaPlugin @@ -44520,6 +45315,75 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{1322, 1033}, {123, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{1346, 1013}, {178, 43}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{1069, 398}, {431, 174}} + com.apple.InterfaceBuilder.CocoaPlugin + + AUDAAABC8gAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + AUFwAABCUAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + AUNQAABCxAAAA + + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABDdgAAwzcAAA + + + ToolTip + + ToolTip + + If the display orientation is vertical, the main screen will be arranged above the touch screen by default. If the display layout is horizontal, the main screen will be arranged left of the touch screen by default. + + + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + If the display orientation is vertical, the touch screen will be arranged above the main screen by default. If the display layout is horizontal, the touch screen will be arranged left of the main screen by default. + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + P4AAAL+AAABCWAAAwy4AAA + + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Arranges the DS screens where one screen is to the left of the other screen by default. + + + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Arranges the DS screens where one screen is above the other screen by default. + + + com.apple.InterfaceBuilder.CocoaPlugin {{609, 360}, {400, 100}} com.apple.InterfaceBuilder.CocoaPlugin {{609, 360}, {400, 100}} @@ -44899,7 +45763,7 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA - 6167 + 6230 @@ -45418,6 +46282,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeCoreEmuFlags: changeCoreSpeed: changeDisplayMode: + changeDisplayOrder: + changeDisplayOrientation: changeFirmwareSettings: changeRomSaveType: changeRotation: @@ -45520,6 +46386,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA id id id + id + id @@ -45539,6 +46407,8 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeCoreEmuFlags: changeCoreSpeed: changeDisplayMode: + changeDisplayOrder: + changeDisplayOrientation: changeFirmwareSettings: changeRomSaveType: changeRotation: @@ -45637,6 +46507,14 @@ AAMAAAABAAEAAAFTAAMAAAAEAAAFwgAAAAAACAAIAAgACAABAAEAAQABA changeDisplayMode: id + + changeDisplayOrder: + id + + + changeDisplayOrientation: + id + changeFirmwareSettings: id diff --git a/desmume/src/cocoa/userinterface/displayView.h b/desmume/src/cocoa/userinterface/displayView.h index 608a1cb63..cfaed29f8 100644 --- a/desmume/src/cocoa/userinterface/displayView.h +++ b/desmume/src/cocoa/userinterface/displayView.h @@ -38,6 +38,8 @@ - (void) doResizeView:(NSRect)rect; - (void) doRedraw; - (void) doDisplayTypeChanged:(NSInteger)displayTypeID; +- (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID; +- (void) doDisplayOrderChanged:(NSInteger)displayOrderID; - (void) doBilinearOutputChanged:(BOOL)useBilinear; - (void) doVerticalSyncChanged:(BOOL)useVerticalSync; - (void) doVideoFilterChanged:(NSInteger)videoFilterTypeID; @@ -58,38 +60,31 @@ NSSize normalSize; NSMutableDictionary *bindings; - OSSpinLock spinlockGpuStateFlags; - OSSpinLock spinlockDisplayType; OSSpinLock spinlockNormalSize; + OSSpinLock spinlockGpuStateFlags; OSSpinLock spinlockScale; OSSpinLock spinlockRotation; OSSpinLock spinlockUseBilinearOutput; OSSpinLock spinlockUseVerticalSync; + OSSpinLock spinlockDisplayType; + OSSpinLock spinlockDisplayOrientation; + OSSpinLock spinlockDisplayOrder; } @property (retain) NSView *view; @property (retain) NSPort *sendPortInput; @property (retain) CocoaDSController *cdsController; @property (readonly) NSSize normalSize; +@property (assign) UInt32 gpuStateFlags; @property (assign) double scale; @property (assign) double rotation; @property (assign) BOOL useBilinearOutput; @property (assign) BOOL useVerticalSync; @property (assign) NSInteger displayType; +@property (assign) NSInteger displayOrientation; +@property (assign) NSInteger displayOrder; @property (readonly) NSMutableDictionary *bindings; -- (void) setGpuStateFlags:(UInt32)flags; -- (UInt32) gpuStateFlags; -- (void) setScale:(double)s; -- (double) scale; -- (void) setRotation:(double)angleDegrees; -- (double) rotation; -- (void) setUseBilinearOutput:(BOOL)theState; -- (BOOL) useBilinearOutput; -- (void) setUseVerticalSync:(BOOL)theState; -- (BOOL) useVerticalSync; -- (void) setDisplayType:(NSInteger)theType; -- (NSInteger) displayType; - (void) setVideoFilterType:(NSInteger)theType; - (void) setRender3DRenderingEngine:(NSInteger)methodID; - (void) setRender3DHighPrecisionColorInterpolation:(BOOL)state; @@ -125,12 +120,16 @@ @interface OpenGLDisplayView : NSOpenGLView { DisplayViewDelegate *dispViewDelegate; - NSSize lastFrameSize; GLint glTexRenderStyle; GLenum glTexPixelFormat; GLvoid *glTexBack; NSSize glTexBackSize; + GLuint swRasterizerDrawTexture[2]; + GLfloat swRasterizerMainTexCoord[4][2]; + GLfloat swRasterizerMainVertex[4][2]; + GLfloat swRasterizerTouchTexCoord[4][2]; + GLfloat swRasterizerTouchVertex[4][2]; } - (void) drawVideoFrame; @@ -138,6 +137,7 @@ mainBytes:(const GLvoid *)mainBytes touchBytes:(const GLvoid *)touchBytes; - (void) renderSWRasterizer; +- (void) setupSWRasterizerVertices; @end diff --git a/desmume/src/cocoa/userinterface/displayView.mm b/desmume/src/cocoa/userinterface/displayView.mm index a9177a74a..1715d0a11 100644 --- a/desmume/src/cocoa/userinterface/displayView.mm +++ b/desmume/src/cocoa/userinterface/displayView.mm @@ -40,11 +40,14 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; @synthesize isHudEnabled; @synthesize isHudEditingModeEnabled; @dynamic normalSize; +@dynamic gpuStateFlags; @dynamic scale; @dynamic rotation; @dynamic useBilinearOutput; @dynamic useVerticalSync; @dynamic displayType; +@dynamic displayOrientation; +@dynamic displayOrder; @synthesize bindings; - (id)init @@ -64,13 +67,15 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; } view = nil; - spinlockGpuStateFlags = OS_SPINLOCK_INIT; - spinlockDisplayType = OS_SPINLOCK_INIT; spinlockNormalSize = OS_SPINLOCK_INIT; + spinlockGpuStateFlags = OS_SPINLOCK_INIT; spinlockScale = OS_SPINLOCK_INIT; spinlockRotation = OS_SPINLOCK_INIT; spinlockUseBilinearOutput = OS_SPINLOCK_INIT; spinlockUseVerticalSync = OS_SPINLOCK_INIT; + spinlockDisplayType = OS_SPINLOCK_INIT; + spinlockDisplayOrientation = OS_SPINLOCK_INIT; + spinlockDisplayOrder = OS_SPINLOCK_INIT; normalSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2.0); sendPortDisplay = nil; @@ -218,7 +223,7 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; - (void) setDisplayType:(NSInteger)theType { - NSSize theSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); + NSSize newDisplaySize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); NSString *modeString = @"Unknown"; switch (theType) @@ -232,8 +237,17 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; break; case DS_DISPLAY_TYPE_COMBO: - theSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2); modeString = NSSTRING_DISPLAYMODE_COMBO; + + if ([self displayOrientation] == DS_DISPLAY_ORIENTATION_VERTICAL) + { + newDisplaySize.height *= 2; + } + else + { + newDisplaySize.width *= 2; + } + break; default: @@ -246,7 +260,7 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; OSSpinLockUnlock(&spinlockDisplayType); OSSpinLockLock(&spinlockNormalSize); - normalSize = theSize; + normalSize = newDisplaySize; OSSpinLockUnlock(&spinlockNormalSize); [CocoaDSUtil messageSendOneWayWithInteger:self.sendPortDisplay msgID:MESSAGE_CHANGE_DISPLAY_TYPE integerValue:theType]; @@ -261,6 +275,60 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; return theType; } +- (void) setDisplayOrientation:(NSInteger)theOrientation +{ + OSSpinLockLock(&spinlockDisplayOrientation); + [bindings setValue:[NSNumber numberWithInteger:theOrientation] forKey:@"displayOrientation"]; + OSSpinLockUnlock(&spinlockDisplayOrientation); + + if ([self displayType] == DS_DISPLAY_TYPE_COMBO) + { + NSSize newDisplaySize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT); + + if (theOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) + { + newDisplaySize.height *= 2; + } + else + { + newDisplaySize.width *= 2; + } + + OSSpinLockLock(&spinlockNormalSize); + normalSize = newDisplaySize; + OSSpinLockUnlock(&spinlockNormalSize); + } + + [CocoaDSUtil messageSendOneWayWithInteger:self.sendPortDisplay msgID:MESSAGE_CHANGE_DISPLAY_ORIENTATION integerValue:theOrientation]; +} + +- (NSInteger) displayOrientation +{ + OSSpinLockLock(&spinlockDisplayOrientation); + NSInteger theOrientation = [[bindings valueForKey:@"displayOrientation"] integerValue]; + OSSpinLockUnlock(&spinlockDisplayOrientation); + + return theOrientation; +} + +- (void) setDisplayOrder:(NSInteger)theOrder +{ + OSSpinLockLock(&spinlockDisplayOrder); + [bindings setValue:[NSNumber numberWithInteger:theOrder] forKey:@"displayOrder"]; + OSSpinLockUnlock(&spinlockDisplayOrder); + + [CocoaDSUtil messageSendOneWayWithInteger:self.sendPortDisplay msgID:MESSAGE_CHANGE_DISPLAY_ORDER integerValue:theOrder]; +} + +- (NSInteger) displayOrder +{ + OSSpinLockLock(&spinlockDisplayOrder); + NSInteger theOrder = [[bindings valueForKey:@"displayOrder"] integerValue]; + OSSpinLockUnlock(&spinlockDisplayOrder); + + return theOrder; +} + - (void) setVideoFilterType:(NSInteger)theType { [bindings setValue:[NSNumber numberWithInteger:theType] forKey:@"videoFilterType"]; @@ -348,6 +416,21 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; NSPoint touchLoc = GetNormalPointFromTransformedPoint(clickLoc, self.normalSize, [[self view] bounds].size, [self scale], viewAngle); // Normalize the y-coordinate to the DS. + if ([self displayType] == DS_DISPLAY_TYPE_COMBO) + { + NSInteger theOrientation = [self displayOrientation]; + NSInteger theOrder = [self displayOrder]; + + if (theOrientation == DS_DISPLAY_ORIENTATION_VERTICAL && theOrder == DS_DISPLAY_ORDER_TOUCH_FIRST) + { + touchLoc.y -= GPU_DISPLAY_HEIGHT; + } + else if (theOrientation == DS_DISPLAY_ORIENTATION_HORIZONTAL && theOrder == DS_DISPLAY_ORDER_MAIN_FIRST) + { + touchLoc.x -= GPU_DISPLAY_WIDTH; + } + } + touchLoc.y = GPU_DISPLAY_HEIGHT - touchLoc.y; // Constrain the touch point to the DS dimensions. @@ -527,6 +610,26 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; [view doDisplayTypeChanged:displayTypeID]; } +- (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID +{ + if (view == nil || ![view respondsToSelector:@selector(doDisplayOrientationChanged:)]) + { + return; + } + + [view doDisplayOrientationChanged:displayOrientationID]; +} + +- (void) doDisplayOrderChanged:(NSInteger)displayOrderID +{ + if (view == nil || ![view respondsToSelector:@selector(doDisplayOrderChanged:)]) + { + return; + } + + [view doDisplayOrderChanged:displayOrderID]; +} + - (void) doBilinearOutputChanged:(BOOL)useBilinear { if (view == nil || ![view respondsToSelector:@selector(doBilinearOutputChanged:)]) @@ -790,12 +893,11 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; } dispViewDelegate = nil; - lastFrameSize = NSMakeSize(GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT * 2.0); glTexPixelFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV; glTexRenderStyle = GL_LINEAR; - UInt32 w = GetNearestPositivePOT((UInt32)lastFrameSize.width); - UInt32 h = GetNearestPositivePOT((UInt32)lastFrameSize.height); + UInt32 w = GetNearestPositivePOT((UInt32)GPU_DISPLAY_WIDTH); + UInt32 h = GetNearestPositivePOT((UInt32)(GPU_DISPLAY_HEIGHT * 2.0)); glTexBack = (GLvoid *)calloc(w * h, sizeof(UInt16)); glTexBackSize = NSMakeSize(w, h); @@ -888,6 +990,24 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; } } + swRasterizerMainTexCoord[0][0] = 0.0f; + swRasterizerMainTexCoord[0][1] = 0.0f; + swRasterizerMainTexCoord[1][0] = (GLfloat)(textureSize.width / w); + swRasterizerMainTexCoord[1][1] = 0.0f; + swRasterizerMainTexCoord[2][0] = (GLfloat)(textureSize.width / w); + swRasterizerMainTexCoord[2][1] = (GLfloat)(textureSize.height / h); + swRasterizerMainTexCoord[3][0] = 0.0f; + swRasterizerMainTexCoord[3][1] = (GLfloat)(textureSize.height / h); + + swRasterizerTouchTexCoord[0][0] = 0.0f; + swRasterizerTouchTexCoord[0][1] = 0.0f; + swRasterizerTouchTexCoord[1][0] = (GLfloat)(textureSize.width / w); + swRasterizerTouchTexCoord[1][1] = 0.0f; + swRasterizerTouchTexCoord[2][0] = (GLfloat)(textureSize.width / w); + swRasterizerTouchTexCoord[2][1] = (GLfloat)(textureSize.height / h); + swRasterizerTouchTexCoord[3][0] = 0.0f; + swRasterizerTouchTexCoord[3][1] = (GLfloat)(textureSize.height / h); + // Main screen glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, glTexPixelFormat, glTexBack); @@ -906,81 +1026,157 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; - (void) renderSWRasterizer { NSInteger displayType = [dispViewDelegate displayType]; - GLfloat w = (GLfloat)dispViewDelegate.normalSize.width; - GLfloat h = (GLfloat)dispViewDelegate.normalSize.height; glClear(GL_COLOR_BUFFER_BIT); - if (displayType == DS_DISPLAY_TYPE_COMBO) + // Render the main screen + if (displayType == DS_DISPLAY_TYPE_MAIN || displayType == DS_DISPLAY_TYPE_COMBO) { - GLfloat texRatioMainW = (GLfloat)lastFrameSize.width / (GLfloat)GetNearestPositivePOT((uint32_t)lastFrameSize.width); - GLfloat texRatioMainH = (GLfloat)lastFrameSize.height / (GLfloat)GetNearestPositivePOT((uint32_t)lastFrameSize.height); - GLfloat texRatioTouchW = (GLfloat)lastFrameSize.width / (GLfloat)GetNearestPositivePOT((uint32_t)lastFrameSize.width); - GLfloat texRatioTouchH = (GLfloat)lastFrameSize.height / (GLfloat)GetNearestPositivePOT((uint32_t)lastFrameSize.height); - - // Main screen glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[0]); glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 0.0f); - glVertex3f(-(w/2.0f), (h/2.0f), 0.0f); - - glTexCoord2f(texRatioMainW, 0.0f); - glVertex3f((w/2.0f), (h/2.0f), 0.0f); - - glTexCoord2f(texRatioMainW, texRatioMainH); - glVertex3f((w/2.0f), 0.0f, 0.0f); - - glTexCoord2f(0.0f, texRatioMainH); - glVertex3f(-(w/2.0f), 0.0f, 0.0f); - - glEnd(); - // Touch screen + for (unsigned int i = 0; i < 4; i++) + { + glTexCoord2f(swRasterizerMainTexCoord[i][0], swRasterizerMainTexCoord[i][1]); + glVertex2f(swRasterizerMainVertex[i][0], swRasterizerMainVertex[i][1]); + } + + glEnd(); + } + + // Render the touch screen + if (displayType == DS_DISPLAY_TYPE_TOUCH || displayType == DS_DISPLAY_TYPE_COMBO) + { glBindTexture(GL_TEXTURE_2D, swRasterizerDrawTexture[1]); glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 0.0f); - glVertex3f(-(w/2.0f), 0.0f, 0.0f); - - glTexCoord2f(texRatioTouchW, 0.0f); - glVertex3f((w/2.0f), 0.0f, 0.0f); - - glTexCoord2f(texRatioTouchW, texRatioTouchH); - glVertex3f((w/2.0f), -(h/2.0f), 0.0f); - - glTexCoord2f(0.0f, texRatioTouchH); - glVertex3f(-(w/2.0f), -(h/2.0f), 0.0f); - + + for (unsigned int i = 0; i < 4; i++) + { + glTexCoord2f(swRasterizerTouchTexCoord[i][0], swRasterizerTouchTexCoord[i][1]); + glVertex2f(swRasterizerTouchVertex[i][0], swRasterizerTouchVertex[i][1]); + } + glEnd(); } +} + +- (void) setupSWRasterizerVertices +{ + NSInteger displayType = [dispViewDelegate displayType]; + GLfloat w = (GLfloat)dispViewDelegate.normalSize.width * [dispViewDelegate scale]; + GLfloat h = (GLfloat)dispViewDelegate.normalSize.height * [dispViewDelegate scale]; + + if (displayType == DS_DISPLAY_TYPE_COMBO) + { + NSInteger displayOrientation = [dispViewDelegate displayOrientation]; + NSInteger displayOrder = [dispViewDelegate displayOrder]; + + if (displayOrientation == DS_DISPLAY_ORIENTATION_VERTICAL) + { + if (displayOrder == DS_DISPLAY_ORDER_MAIN_FIRST) + { + swRasterizerMainVertex[0][0] = -w/2.0f; + swRasterizerMainVertex[0][1] = h/2.0f; + swRasterizerMainVertex[1][0] = w/2.0f; + swRasterizerMainVertex[1][1] = h/2.0f; + swRasterizerMainVertex[2][0] = w/2.0f; + swRasterizerMainVertex[2][1] = 0.0f; + swRasterizerMainVertex[3][0] = -w/2.0f; + swRasterizerMainVertex[3][1] = 0.0f; + + swRasterizerTouchVertex[0][0] = -w/2.0f; + swRasterizerTouchVertex[0][1] = 0.0f; + swRasterizerTouchVertex[1][0] = w/2.0f; + swRasterizerTouchVertex[1][1] = 0.0f; + swRasterizerTouchVertex[2][0] = w/2.0f; + swRasterizerTouchVertex[2][1] = -h/2.0f; + swRasterizerTouchVertex[3][0] = -w/2.0f; + swRasterizerTouchVertex[3][1] = -h/2.0f; + } + else // displayOrder == DS_DISPLAY_ORDER_TOUCH_FIRST + { + swRasterizerTouchVertex[0][0] = -w/2.0f; + swRasterizerTouchVertex[0][1] = h/2.0f; + swRasterizerTouchVertex[1][0] = w/2.0f; + swRasterizerTouchVertex[1][1] = h/2.0f; + swRasterizerTouchVertex[2][0] = w/2.0f; + swRasterizerTouchVertex[2][1] = 0.0f; + swRasterizerTouchVertex[3][0] = -w/2.0f; + swRasterizerTouchVertex[3][1] = 0.0f; + + swRasterizerMainVertex[0][0] = -w/2.0f; + swRasterizerMainVertex[0][1] = 0.0f; + swRasterizerMainVertex[1][0] = w/2.0f; + swRasterizerMainVertex[1][1] = 0.0f; + swRasterizerMainVertex[2][0] = w/2.0f; + swRasterizerMainVertex[2][1] = -h/2.0f; + swRasterizerMainVertex[3][0] = -w/2.0f; + swRasterizerMainVertex[3][1] = -h/2.0f; + } + } + else // displayOrientation == DS_DISPLAY_ORIENTATION_HORIZONTAL + { + if (displayOrder == DS_DISPLAY_ORDER_MAIN_FIRST) + { + swRasterizerMainVertex[0][0] = -w/2.0f; + swRasterizerMainVertex[0][1] = h/2.0f; + swRasterizerMainVertex[1][0] = 0.0f; + swRasterizerMainVertex[1][1] = h/2.0f; + swRasterizerMainVertex[2][0] = 0.0f; + swRasterizerMainVertex[2][1] = -h/2.0f; + swRasterizerMainVertex[3][0] = -w/2.0f; + swRasterizerMainVertex[3][1] = -h/2.0f; + + swRasterizerTouchVertex[0][0] = 0.0f; + swRasterizerTouchVertex[0][1] = h/2.0f; + swRasterizerTouchVertex[1][0] = w/2.0f; + swRasterizerTouchVertex[1][1] = h/2.0f; + swRasterizerTouchVertex[2][0] = w/2.0f; + swRasterizerTouchVertex[2][1] = -h/2.0f; + swRasterizerTouchVertex[3][0] = 0.0f; + swRasterizerTouchVertex[3][1] = -h/2.0f; + } + else // displayOrder == DS_DISPLAY_ORDER_TOUCH_FIRST + { + swRasterizerTouchVertex[0][0] = -w/2.0f; + swRasterizerTouchVertex[0][1] = h/2.0f; + swRasterizerTouchVertex[1][0] = 0.0f; + swRasterizerTouchVertex[1][1] = h/2.0f; + swRasterizerTouchVertex[2][0] = 0.0f; + swRasterizerTouchVertex[2][1] = -h/2.0f; + swRasterizerTouchVertex[3][0] = -w/2.0f; + swRasterizerTouchVertex[3][1] = -h/2.0f; + + swRasterizerMainVertex[0][0] = 0.0f; + swRasterizerMainVertex[0][1] = h/2.0f; + swRasterizerMainVertex[1][0] = w/2.0f; + swRasterizerMainVertex[1][1] = h/2.0f; + swRasterizerMainVertex[2][0] = w/2.0f; + swRasterizerMainVertex[2][1] = -h/2.0f; + swRasterizerMainVertex[3][0] = 0.0f; + swRasterizerMainVertex[3][1] = -h/2.0f; + } + } + } else { - GLfloat texRatioW = (GLfloat)lastFrameSize.width / (GLfloat)GetNearestPositivePOT((uint32_t)lastFrameSize.width); - GLfloat texRatioH = (GLfloat)lastFrameSize.height / (GLfloat)GetNearestPositivePOT((uint32_t)lastFrameSize.height); - GLuint drawTexture = swRasterizerDrawTexture[0]; + swRasterizerMainVertex[0][0] = -w/2.0f; + swRasterizerMainVertex[0][1] = h/2.0f; + swRasterizerMainVertex[1][0] = w/2.0f; + swRasterizerMainVertex[1][1] = h/2.0f; + swRasterizerMainVertex[2][0] = w/2.0f; + swRasterizerMainVertex[2][1] = -h/2.0f; + swRasterizerMainVertex[3][0] = -w/2.0f; + swRasterizerMainVertex[3][1] = -h/2.0f; - if (displayType == DS_DISPLAY_TYPE_TOUCH) - { - drawTexture = swRasterizerDrawTexture[1]; - } - - glBindTexture(GL_TEXTURE_2D, drawTexture); - glBegin(GL_QUADS); - - glTexCoord2f(0.0f, 0.0f); - glVertex3f(-(w/2.0f), (h/2.0f), 0.0f); - - glTexCoord2f(texRatioW, 0.0f); - glVertex3f((w/2.0f), (h/2.0f), 0.0f); - - glTexCoord2f(texRatioW, texRatioH); - glVertex3f((w/2.0f), -(h/2.0f), 0.0f); - - glTexCoord2f(0.0f, texRatioH); - glVertex3f(-(w/2.0f), -(h/2.0f), 0.0f); - - glEnd(); + swRasterizerTouchVertex[0][0] = -w/2.0f; + swRasterizerTouchVertex[0][1] = h/2.0f; + swRasterizerTouchVertex[1][0] = w/2.0f; + swRasterizerTouchVertex[1][1] = h/2.0f; + swRasterizerTouchVertex[2][0] = w/2.0f; + swRasterizerTouchVertex[2][1] = -h/2.0f; + swRasterizerTouchVertex[3][0] = -w/2.0f; + swRasterizerTouchVertex[3][1] = -h/2.0f; } } @@ -1104,8 +1300,6 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; - (void)doProcessVideoFrame:(const void *)videoFrameData frameSize:(NSSize)frameSize { - lastFrameSize = frameSize; - CGLLockContext((CGLContextObj)[[self openGLContext] CGLContextObj]); [[self openGLContext] makeCurrentContext]; @@ -1163,6 +1357,8 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; [[self openGLContext] update]; CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]); + + [self setupSWRasterizerVertices]; } - (void)doRedraw @@ -1176,7 +1372,12 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; CGLUnlockContext((CGLContextObj)[[self openGLContext] CGLContextObj]); } -- (void) doBilinearOutputChanged:(BOOL)useBilinear +- (void)doDisplayTypeChanged:(NSInteger)displayTypeID +{ + [self setupSWRasterizerVertices]; +} + +- (void)doBilinearOutputChanged:(BOOL)useBilinear { glTexRenderStyle = GL_NEAREST; if (useBilinear) @@ -1185,7 +1386,22 @@ NSOpenGLContext *OSXDefaultOpenGLContext = nil; } } -- (void) doVerticalSyncChanged:(BOOL)useVerticalSync +- (void) doDisplayOrientationChanged:(NSInteger)displayOrientationID +{ + [self setupSWRasterizerVertices]; +} + +- (void) doDisplayOrderChanged:(NSInteger)displayOrderID +{ + [self setupSWRasterizerVertices]; + + if ([dispViewDelegate displayType] == DS_DISPLAY_TYPE_COMBO) + { + [self doRedraw]; + } +} + +- (void)doVerticalSyncChanged:(BOOL)useVerticalSync { GLint swapInt = 0; @@ -1213,11 +1429,8 @@ void SetupOpenGLView(GLsizei width, GLsizei height, GLfloat scalar, GLfloat angl glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0.0, width, 0.0, height, -1.0, 1.0); - - glTranslatef(width / 2.0f, height / 2.0f, 0.0f); + glOrtho(-width/2.0, width/2.0, -height/2.0, height/2.0, -1.0, 1.0); glRotatef((GLfloat)CLOCKWISE_DEGREES(angleDegrees), 0.0f, 0.0f, 1.0f); - glScalef(scalar, scalar, 0.0f); } bool OSXOpenGLRendererInit() diff --git a/desmume/src/cocoa/userinterface/emuWindowDelegate.h b/desmume/src/cocoa/userinterface/emuWindowDelegate.h index 29a5df3b9..e6feddbc0 100644 --- a/desmume/src/cocoa/userinterface/emuWindowDelegate.h +++ b/desmume/src/cocoa/userinterface/emuWindowDelegate.h @@ -189,6 +189,8 @@ - (IBAction) changeBilinearOutput:(id)sender; - (IBAction) changeVerticalSync:(id)sender; - (IBAction) changeDisplayMode:(id)sender; +- (IBAction) changeDisplayOrientation:(id)sender; +- (IBAction) changeDisplayOrder:(id)sender; - (IBAction) changeVideoFilter:(id)sender; - (IBAction) change3DRenderMethod:(id)sender; - (IBAction) change3DRenderHighPrecisionColorInterpolation:(id)sender; diff --git a/desmume/src/cocoa/userinterface/emuWindowDelegate.mm b/desmume/src/cocoa/userinterface/emuWindowDelegate.mm index e1900404c..dbf217693 100644 --- a/desmume/src/cocoa/userinterface/emuWindowDelegate.mm +++ b/desmume/src/cocoa/userinterface/emuWindowDelegate.mm @@ -869,6 +869,21 @@ [self resizeWithTransform:[dispViewDelegate normalSize] scalar:[dispViewDelegate scale] rotation:[dispViewDelegate rotation]]; } +- (IBAction) changeDisplayOrientation:(id)sender +{ + [dispViewDelegate setDisplayOrientation:[CocoaDSUtil getIBActionSenderTag:sender]]; + + if ([dispViewDelegate displayType] == DS_DISPLAY_TYPE_COMBO) + { + [self resizeWithTransform:[dispViewDelegate normalSize] scalar:[dispViewDelegate scale] rotation:[dispViewDelegate rotation]]; + } +} + +- (IBAction) changeDisplayOrder:(id)sender +{ + [dispViewDelegate setDisplayOrder:[CocoaDSUtil getIBActionSenderTag:sender]]; +} + - (IBAction) changeVideoFilter:(id)sender { [dispViewDelegate setVideoFilterType:[CocoaDSUtil getIBActionSenderTag:sender]]; @@ -1709,6 +1724,34 @@ } } } + else if (theAction == @selector(changeDisplayOrientation:)) + { + if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) + { + if ([dispViewDelegate displayOrientation] == [theItem tag]) + { + [(NSMenuItem*)theItem setState:NSOnState]; + } + else + { + [(NSMenuItem*)theItem setState:NSOffState]; + } + } + } + else if (theAction == @selector(changeDisplayOrder:)) + { + if ([(id)theItem isMemberOfClass:[NSMenuItem class]]) + { + if ([dispViewDelegate displayOrder] == [theItem tag]) + { + [(NSMenuItem*)theItem setState:NSOnState]; + } + else + { + [(NSMenuItem*)theItem setState:NSOffState]; + } + } + } else if (theAction == @selector(openEmuSaveState:) || theAction == @selector(saveEmuSaveState:) || theAction == @selector(saveEmuSaveStateAs:)) @@ -1985,10 +2028,12 @@ // Set the display window per user preferences. [self setShowStatusBar:[[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayView_ShowStatusBar"]]; - // Set the display mode, sizing, and rotation. + // Set the display settings per user preferences. double displayScalar = (double)([[NSUserDefaults standardUserDefaults] floatForKey:@"DisplayView_Size"] / 100.0); double displayRotation = (double)[[NSUserDefaults standardUserDefaults] floatForKey:@"DisplayView_Rotation"]; [dispViewDelegate setDisplayType:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayView_Mode"]]; + [dispViewDelegate setDisplayOrientation:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayViewCombo_Orientation"]]; + [dispViewDelegate setDisplayOrder:[[NSUserDefaults standardUserDefaults] integerForKey:@"DisplayViewCombo_Order"]]; [self setContentScalar:displayScalar]; [self setContentRotation:displayRotation];