From 822837aefd706afdae4f9170ec5cc8404ba85fe7 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Thu, 25 Jan 2024 12:24:18 +0100 Subject: [PATCH] enhanced and optimized auto-phosphor --- Changes.txt | 2 +- docs/graphics/options_video_tv.png | Bin 4109 -> 4120 bytes docs/index.html | 25 +++--- src/common/PKeyboardHandler.cxx | 1 - src/common/PhosphorHandler.cxx | 25 ++++++ src/common/PhosphorHandler.hxx | 22 ++++++ src/emucore/Console.cxx | 121 +++++++++++++++-------------- src/emucore/Console.hxx | 4 +- src/emucore/EventHandler.cxx | 2 +- src/emucore/FrameBuffer.cxx | 41 +++++----- src/emucore/Settings.cxx | 17 ++-- src/emucore/tia/TIA.cxx | 91 ++++++++++++---------- src/emucore/tia/TIA.hxx | 35 ++++----- src/gui/GameInfoDialog.cxx | 14 ++-- src/gui/StellaSettingsDialog.cxx | 8 +- src/gui/VideoAudioDialog.cxx | 23 +++--- src/gui/Widget.cxx | 4 +- src/os/windows/Stella.vcxproj | 3 + 18 files changed, 256 insertions(+), 182 deletions(-) diff --git a/Changes.txt b/Changes.txt index 9fa07beaf..3dc2b695f 100644 --- a/Changes.txt +++ b/Changes.txt @@ -22,7 +22,7 @@ * Added option to start random ROM. - * Added option for automatic phosphor. + * Added automatically enabled phosphor modes. * Enhanced Game Properties dialog for multigame ROMs. diff --git a/docs/graphics/options_video_tv.png b/docs/graphics/options_video_tv.png index a2a4fe98a6ee73cbf20ad42a3140fae7bd3c8a53..1a44958e70787fae823137223ceddcb5b7ea6e9d 100644 GIT binary patch delta 3431 zcmaJ@c|6k(AE&u*Ekv%asR^4*uJI!!`EJy<(h@U|l~}Ia$K*aM*721iKNY_@V=Ga} z6k&)tH+0D4s^remP&*$|%GPFVM+kSFvAt5=ou+pK^F+xJ} ziJ8$x5QPr~RnM%1X`Qy45oyHhpcZtowH1%4==sjLxJ6};NmEXV2L8iNlu44C@&Rom zwn77h%_HCWx>!u~DS{7eu0LeM7Y;XU_HX$~C3P%@^v&<)=tQ2vg9jwFnEZqqFJCvc z1@4{Id%q(hRuGMzlAnBz-CVHjF_~CNtWck6qX&z%8v~dQjd*H{t(|&*Z{u$?c zd%3^$G5bS%6)KeTAU4#08lu5UlI(bIAHS^3G}9O=KnW8b$RVG3tW$B+$p!u_+h^_A zB^CEM{9T%gJs8~SE==Xk#EK!TEWFP)PMc9LN5`r95pVEoklUTBG->rzVUB#%?jCy^ z@Wb_2?o1EXhFE!XdaBXB?qImGFu@A%CGX3<&F<|LDtop)O~VF?(Zrp z-eg(YfF+l?oAAZXru^WnT>W=bURI-ed{ArXEIukRoOu4*VTXse0$vscRVKPZxRJUc zhxVJpLD9fdP-G4Ug`TZDp?A6ut)s-r#UldGHp$$%bSN5xx$BRrSOKC;x8SLU7MjD; ze!{0j$AsEw%|36k*`vVc@dS*-8&l8g3Zq-mWZ?1;JXLb;#y22lQccA zE_}m%mEMq!O#x#Q%{8wMb7f-w@)ZUS1zG~8T_sxwRCvi{UbEkB@lrt4#5{Ow`1#Vs zbtTu{fl9WtJeFPzjd(_4I& zhBUVwR?y?Cat>4JCnxcp5Old(G4vkSY)!E$UwQ96^718oZ_onFgf{o$X5El9>G{z7 z^OC@JCGL@{%%(n_T~~74qWQVOHWwZ}a2V98v$%bYSD0poo?~^yp-O76Zw8L|>etg7 z#RSXS2WOI$Igp@KlR3PG3FY%l5YoK+)5_r=XOg_oJzI5+=KQ5YB8Y=uC}7r{Yf$=n zu#`2>kd1PG`O_p3j$E0I1$k}>V|>i(`%;sBM3w}OXcSXBE-A`~sok}gr=yx_aOW?q zG5S5x6SSQ7#`{5%?eM1hEyhdjan^foiD_gew>@7*Uw-%HN7y}Ddw-IxohV`Nyah|` zi~Z`HD#bzoA#Rr(IR-%%>&B|?-rMW*bx7gkW9>yGR8|;40(LKmR8)VzGttLyX#Y`T)M(k$}d^-;hAOD z%wHtUq8ZZIeVGq$wTS>{tZ^5S6;D$FWVXjw%s} zv;hL<++*ope+$ec*$~#=3{k)_l0>U@cv(Wez9WDsj5detfOTYR$TB_PN~QVcOX zeL90%M};Pd;tdQnaJMkI`_<=`S?N8k8josn_toIa85Ks(XLExuay;RKEJUXjn;b*e{(&u(b`!;k^DhAs6}mvg$X*ENxyGA# zlUFT1{23xslU;@`Mn9E)@FOPC@=vFiN27;6hdQySyadOa41M{pH^>NhP(IDqL{mii zRsOw(gG;O~u2qPPpDe+Ouq^l}*6nyDFS2Uz=DlQ(=?lRz9gv4q{8(h9d!sSI#KK*>Znw_g!CczTa8y z8Xn(W-4iDq&+u+fDqowtu!hvtg60jd0SAnF^K1rUR%>_xiLopX7`$W4MFN6jU7Ja% zq|hv3+?*I_~Iz+8#%FAXs2svY0oY4M9uCmUzkDf~Sn=AA;lO(zN719^~LL}gmGk1kw z2IMNcg~Vk48SwtmZ`dt+P$opd2eLe2y_yi%SII-`-Gn!NJmZjH7eS=ZNRQKok+j-f z94m1|n9;-Fwzv7e{hXr?6y1!j*cywQ0K>IK=|{J9NOmWt`Fs<-tS#@4pEf{nRwQwQ zG$5^D(jX#?qpG-%T?lHAB!maTI!U{!Nt5_bp5H^;G_RiXn7}9IPX(@ zb&eFJ$wE~SZ_ACXRfci9Q|KB}+BEMSg4jr2Ct@z-fPONU2TK3+>O|bmeqYsL3UX4$ zO}$uwpIOF&SXM;!ndkt?a z&f8P`3^|Xxq`9~~4d>Nu6;_2-}1F|s6Ll1C(eX&Mghe>RH1M(pFr5)jgqrX!7n zJCCF&SU70PAPFAFX4C%#-1TbH1xa3pf*s=qn_=HY;h?(`rzdK@dGRV}W3e_qW$>+= z@xo8)b-2wtS{B*IZ3CeS=u_M+{X3IFT_DWT>3x7=Yvk(>UWg~+0jo2X?=|{!TXBaz z%W;Fx#H~fjk=iqI+q@={3feCQn&D5J$sCOUAynqVWReL^SDgBF&e8hsW5+n zy9&_#!wE}B&xSxDsNu+4g7rGMkAmr{OAdeNU%Iv?1NAvvZ#*&9!YGw?0)XYv1Ca_ zz&eCy7R$I+I)#m}gvqP3BM8U}H%qMQ@8q_{$Y1?Q^L^C28y4yIihz<`XyRuYtki={ zDP1Uq_8F@VxNJ_xb=@cz>pebUt@^Aej^W`NzxLGaf+BlkP^hTDBxDzT=HZSPx@K{0 z8bH@LSW=}!KHc5lR1ky^FJri7b(d(vJd|M#Seg*7*18&1OJJ5GRndHssh<1vj-oFJ z*y6}xFcX9|>?iH#yxj8lq+QE%I#P!RX1(`=0$Iblxc=|oV|2yMn!8^cZ71zOVwpvd zbzjrxN=s*~c~)KhEV;YFvtf|cJ@|TrdgRH7ZxMr(f68FzPoll((f=kw&i?_Gal;KU zsoa0lmG(Dzr$`(v=+Yo(Q(F*)9b>Eg0*h*c4syb?&NXk$e|U&nY;2?qERg_9MYCALq2mq6unOZn3C6HAKp?gkUbpjiYsjBba=FqWSK<2;06Pfix<@$^4);CCOvd)KC^?y8XRv zP`(*ukIPsUY8rDn=HMQL3sAFN-`jg{`2#y?Sh$Z66ZBeA;z)_AUx0Ne0|C!@B0=Ja7 z<0#H!qGfnAwKNwFpiE1{v~#=X+~57(5BL4{ykFk^JTG`4?LcO*Y^R8bY^P{%P}wCB z5xMBBTl!*VF(uFHO-0G}#Xp!m%!IcY@G0-`8AkTi`Mg|2G`l8R6Ldc{`btj=p1u5l4@(K&6 z_IQMfvi>v0y0#4wYUsP`$Q9M*M_~?iHj)Y^E;$zhAoVQ~%P6Y6GBuF#^7Z&k+xOOQ z!~08PzrxB_8bbqjYt~T@c;#)HNeX;BPKWI+Vs=+yBn_|Hn`KkapapMlO*l;mw+vf> zi$Cl~ty~efd2;t5bSsyB+fWd0E(U597?gX5=QrrJv1E*@+XWN<_SCnD%XW)!lTr5< z4;^F&8BfyPaz)SwE!zp&;1}`M15*U6AeC5};38=s*Cr?%phhR02w1LF0Kz9qA+K_^ zZY&NM#?q9AtDt^KI9{fL9+TQO}Q7YD^c!7GQPCk{D7S#IV9f+IhWCR&c@M{L*#EZMoMH`u*_6PwlB zQl|*K>uMNw$MEcaUv$CkF}OAP3bz>y@(%KTZzGQ#44U^YHIt|GkWA2FR?^tkGSgn@nDR&=SV5~}Z*!vedX=IJj3o6l~Y-Plx zb2z5iFV~7_2yQ0qAg=WXJt62kG^l6}+b-%CTcVz5DdTXco|;t`2A=W?XK#^~^0y3t zMi&)jd?kRS{CJf>eXOzAi-*8j$pt6a5bY zlaeEDMMe}6tpQfb^Y3s?Y@~S)p@@bfefx!$ja2i{1O~114N(?z-EqIMS2IW1yzDQ3 zs--EnAXQV{^r5ojy|%*RCd6xzEfl)utiTVlRa_I zfAP#rpCuTpP#(KpS6#~yr6D0)rX#W#(pH;NUc%hyOuieYV|kqCSD|1B-2NG1*rn}@SRN##I^wmb%<@>0Qs?2%CX8U?-%Nrlc3}eFYB(|BFPhY(ZsFeHQQ-u;) z`94hT5*zv=&kvNZlJRfI5|R_fyd<%YpXOhKeF8k>6;|KkPJho~E}l#LaM1u=YLWY4 zkQku!yA0GMdnK_5&pg|cck!FZ0#!%l4?_5KrO&cY>pci7Jdu!rxO980As&=Z9tDZf zo&h6g!1@J-WP~|H?&_j~R6Sxg`9!*;)dbb^+Z?#OdRy~|M2X{qkeoDYPH*QCmL^II zMs98{q>I)REjwg0;Z3YH1$WA+_3@#-A!ua3Z1BwwB$yg8-CUV^<-;tX^wu5Jh41TB z==Jy8cf$H|Htj-^;7iOn3QF2x%cPIi^aXyvW-DY{%`Phr5rm9b^eHcHq+Rp^KSXA1 zktNbGY%t$BvbE;61!iZYVgh_I=j_!x`Dp-OYitc>kE#wGJ(^1O2iZY+-{q8857S?U z9;;O=sCA9A)p>~G;`eoxmQ_WJBl5paGmBOH;6xgd>F!i;1L{g!jGOCTP8D`g=&l z4}c}nDSb4DlfdWsjr=@+U9k}Nyr%dZ+dB%??CJz9$j|bjL@cZLeq!-G(>!aP(adE7YM^YK<4EB%qvnqA|N1qag0gC4&4zLdG{%mCAwO z7|0Il_{okJb;}Qh49tDcE7A^5o84ZlcZwV}yG4W`Dk{rJfd8AFHGezp#OQ=v{#A(` zck?tm!IBf#tPJJ6N~LH@9UvbQC7GiHcyJxDSEY+UWQz+Kc-249i*M)E(cG@jdHUn< z5cmBg^WyUFb7{rf*Iej$5fVm(bON1%5Ys?r-YM}v2V=R6MS!+KhI}&aRU30CKA7hd zYAkBhJXIbtZiF{2jF6}BH>_(~l<{u~LJRf{l%TYMfQ%CZJIM}V=^mQ&m!Aj=Jp>|p z%PB{4J7(M#N%SNSxtfec$Z}I0#lVqi)u{+(ixl@P@z?vDf?cFDKWlLV`h%3_%iVm0>>%*14QlIBCXl+fVw3&{hB0R{!b5fPB`^cAo zW-w9MWuP?^vYTB~aSurJSV?H3_}j_Nt&GP0hNysN(9U;hPzA*jYeGf38l3k9bIf!n zZZelsq+4^BKiQc8UtKYIH6;$2Wwxwh{&Jjl3A+L`CYI+eKCUJ_PC{gBb?rQNab5gW zn-sLsGemW5+LdyK{8JiSC%Tl#@{~c%pWj2QKpc2qFv4ajIXUqBycSn~JGCe8UiWvM zVY8yOt5EK&0iZ3-v{<;%yhoa61$ZBt3%6Hd=Q#l?OYNgkNncvP<6BM_JXj>V{h2R= zW|on^w`!&iXf~$$IC~tvQx}U!)CQ)r64!hxw5VMk8+V9omI(BL3|J0b~BrA|IKfkp2% z+20I8L&zFyqnazVY>yJFtq`jy8qpEMUpv?YV2%|;=yK~}&3)mtFuOFuX-sVeipq|Z z^|455ZPLA}h3%^96NV$a{u152r@cL^syd0jMP){+__wMQy33A_PLv zBzV^+TzAtgq0!|nZ764L$wjLN+lX6T1E5v_PJLSK?vtwY)W_9>wV3ndiA%1eua$Df zk`4RL%4JJl9?q4err+Gdoh9J(5`?v)X!DSdN1&so;=wLq5)=fO*9*h>7p5FVx=6;4 zu+-_)C|guz9C+Ui{ARo@ik_FCRQFZq64Uw?$0Yg*5UdJtI2l&7P!Okc+)a%ol6P`mm|I8EH@7u*c-Nj*;k<|?unEsrhs7^Q-fP?RfeX$quRp(s zY<(p3;-I|6NR7`PhPJ`&f3`6yD|6KDZ-)8L-Tm_n{$CKK!Cn`4$}{|*?U3~Uadz0- zM{gq@+<@Pd4p`K-C-LmS@CVMFTc4*2k8VzR>+zxhs6*G>XxH(P<0CKBxd%rAb0a;d zI>zt$r;hn2RS6?GTU*~p3kP-vNK{CuYJ&#KP0WeIL7(V>((Fuw!=+n6lml`qWK7q? zg39(52&mm=@J4}w4GJ3Ijuy_2BwU-^=Vt3h@a%?wjgkJtJw7jSzC)N1nSFYG12u1U zkKk}2x=_Oz6h0OeFw*kIz|Btz&(WV_XmTYmtrin}-9X=p9)rHzYq1`G_Efn4n&mejlYt4z1X9V{(j%@`)AsX|`4v%Nh%xxPJl5n3it< diff --git a/docs/index.html b/docs/index.html index b61627da9..acd6c8a5d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1310,7 +1310,12 @@ Cmd + 3 - Increase 'phosphor' enabling mode + Select previous 'phosphor' enabling mode + - + - + + + Select next 'phosphor' enabling mode Ctrl-Alt + P Ctrl-Cmd + P @@ -1356,7 +1361,7 @@
- Items marked as (*) will also switch to 'Custom' mode
+ Items marked as (*) will also switch to 'Custom' TV effects mode @@ -2926,11 +2931,13 @@ -
-tv.phosphor <always|auto|byrom>
- Determine how phosphor mode is enabled. If 'always' or 'auto', then - the ROM properties entry is ignored, and phosphor mode is either always - turned on or automatic. Otherwise, the ROM properties determine whether - phosphor mode is used for each ROM. +
-tv.phosphor <byrom|always|autoon|auto>
+ Determine how phosphor mode is enabled. If 'byrom', then the ROM + properties determine whether phosphor mode is used for each ROM. + Else the ROM properties entry is ignored. If 'always', then the + phosphor mode is always enabled. If 'autoon', then the phosphor + mode is enabled automatically. If 'auto', then the phosphor mode + is enabled/disabled on automatically. @@ -3826,8 +3833,8 @@ TV modeDisable TV effects, or select TV preset-tv.filter Adjustable slidersSet specific attribute in 'Custom' TV mode-tv.sharpness
-tv.resolution, etc. PhosphorSelect mode for enabling phosphor-tv.phosphor - Blend (phosphor)Blend level to use in phosphor modes for all ROMs and automatic - (needs to be manually adjusted for your particular hardware)-tv.phosblend + Blend (phosphor)Blend level to use in phosphor modes for all ROMs and automatic ones + (level needs to be manually adjusted for your particular hardware)-tv.phosblend (Scanlines) IntensitySets scanlines black-level intensity.
Note: No scanlines in 1x mode snapshots-tv.scanlines (Scanlines) MaskSets the scanlines mask.
diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index b75d76fa0..cb85ec514 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -660,7 +660,6 @@ PhysicalKeyboardHandler::DefaultCommonMapping = { { Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3 }, { Event::PhosphorIncrease, KBDK_4, MOD3 }, { Event::TogglePhosphor, KBDK_P, MOD3 }, - { Event::PhosphorModeDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL | MOD3 }, { Event::PhosphorModeIncrease, KBDK_P, KBDM_CTRL | MOD3 }, { Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3 }, { Event::ScanlinesIncrease, KBDK_5, MOD3 }, diff --git a/src/common/PhosphorHandler.cxx b/src/common/PhosphorHandler.cxx index 9b16c33f7..b8fd39ddd 100644 --- a/src/common/PhosphorHandler.cxx +++ b/src/common/PhosphorHandler.cxx @@ -46,5 +46,30 @@ bool PhosphorHandler::initialize(bool enable, int blend) return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +PhosphorHandler::PhosphorMode PhosphorHandler::toPhosphorMode(string_view name) +{ + if(name == VALUE_ALWAYS) + return PhosphorMode::Always; + + if(name == VALUE_AUTO_ON) + return PhosphorMode::Auto_on; + + if(name == VALUE_AUTO) + return PhosphorMode::Auto; + + return PhosphorMode::ByRom; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string_view PhosphorHandler::toPhosphorName(PhosphorMode type) +{ + static constexpr std::array SETTING_NAMES = { + VALUE_BYROM, VALUE_ALWAYS, VALUE_AUTO_ON, VALUE_AUTO + }; + + return SETTING_NAMES[type]; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PhosphorHandler::PhosphorLUT PhosphorHandler::ourPhosphorLUT; diff --git a/src/common/PhosphorHandler.hxx b/src/common/PhosphorHandler.hxx index fbe3feb17..a1f3ea289 100644 --- a/src/common/PhosphorHandler.hxx +++ b/src/common/PhosphorHandler.hxx @@ -24,12 +24,34 @@ class PhosphorHandler { public: + // Phosphor settings names + static constexpr string_view SETTING_MODE = "tv.phosphor"; + static constexpr string_view SETTING_BLEND = "tv.phosblend"; + // Setting values of phosphor modes + static constexpr string_view VALUE_BYROM = "byrom"; + static constexpr string_view VALUE_ALWAYS = "always"; + static constexpr string_view VALUE_AUTO_ON = "autoon"; + static constexpr string_view VALUE_AUTO = "auto"; + + enum PhosphorMode { + ByRom, + Always, + Auto_on, + Auto, + NumTypes + }; + + static constexpr string_view DEFAULT_BLEND = "50"; // align with myPhosphorPercent! + PhosphorHandler() = default; bool initialize(bool enable, int blend); bool phosphorEnabled() const { return myUsePhosphor; } + static PhosphorMode toPhosphorMode(string_view name); + static string_view toPhosphorName(PhosphorMode type); + /** Used to calculate an averaged color pixel for the 'phosphor' effect. diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index ecc3e2d50..6285c37f2 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -534,19 +534,21 @@ void Console::setFormat(uInt32 format, bool force) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::toggleColorLoss(bool toggle) { - const bool colorloss = !myTIA->colorLossEnabled(); - if(myTIA->enableColorLoss(colorloss)) + bool colorloss = myTIA->colorLossEnabled(); + if(toggle) { - myOSystem.settings().setValue( - myOSystem.settings().getBool("dev.settings") ? "dev.colorloss" : "plr.colorloss", colorloss); - - const string message = string("PAL color-loss ") + - (colorloss ? "enabled" : "disabled"); - myOSystem.frameBuffer().showTextMessage(message); + colorloss = !colorloss; + if(myTIA->enableColorLoss(colorloss)) + myOSystem.settings().setValue( + myOSystem.settings().getBool("dev.settings") ? "dev.colorloss" : "plr.colorloss", colorloss); + else { + myOSystem.frameBuffer().showTextMessage( + "PAL color-loss not available in non PAL modes"); + return; + } } - else - myOSystem.frameBuffer().showTextMessage( - "PAL color-loss not available in non PAL modes"); + const string message = string("PAL color-loss ") + (colorloss ? "enabled" : "disabled"); + myOSystem.frameBuffer().showTextMessage(message); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -563,12 +565,14 @@ void Console::toggleInter(bool toggle) bool enabled = myOSystem.settings().getBool("tia.inter"); if(toggle) + { enabled = !enabled; - myOSystem.settings().setValue("tia.inter", enabled); + myOSystem.settings().setValue("tia.inter", enabled); - // ... and apply potential setting changes to the TIA surface - myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings(); + // Apply potential setting changes to the TIA surface + myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings(); + } ostringstream ss; ss << "Interpolation " << (enabled ? "enabled" : "disabled"); @@ -623,18 +627,22 @@ void Console::changeSpeed(int direction) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Console::togglePhosphor() +void Console::togglePhosphor(bool toggle) { - const bool enable = !myOSystem.frameBuffer().tiaSurface().phosphorEnabled(); - if(!enable) - myProperties.set(PropType::Display_Phosphor, "NO"); - else - myProperties.set(PropType::Display_Phosphor, "YES"); - myOSystem.frameBuffer().tiaSurface().enablePhosphor(enable); + bool enable = myOSystem.frameBuffer().tiaSurface().phosphorEnabled(); - // disable auto-phosphor - if(myTIA->autoPhosphorEnabled()) + if(toggle) + { + enable = !enable; + if(!enable) + myProperties.set(PropType::Display_Phosphor, "NO"); + else + myProperties.set(PropType::Display_Phosphor, "YES"); + myOSystem.frameBuffer().tiaSurface().enablePhosphor(enable); + + // disable auto-phosphor myTIA->enableAutoPhosphor(false); + } ostringstream msg; msg << "Phosphor effect " << (enable ? "enabled" : "disabled"); @@ -644,42 +652,40 @@ void Console::togglePhosphor() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::cyclePhosphorMode(int direction) { - static constexpr std::array MESSAGES = { - "by ROM", "always on", "auto-enabled" + static constexpr std::array MESSAGES = { + "by ROM", "always on", "auto-enabled", "auto-enabled/disabled" }; - static constexpr std::array VALUE = { - "byrom", "always", "auto" - }; - const string value = myOSystem.settings().getString("tv.phosphor"); - int mode; - - for(mode = 2; mode > 0; --mode) - if(value == VALUE[mode]) - break; + PhosphorHandler::PhosphorMode mode = + PhosphorHandler::toPhosphorMode(myOSystem.settings().getString(PhosphorHandler::SETTING_MODE)); if(direction) { - mode = BSPF::clampw(mode + direction, 0, 2); - if(mode == 0) + mode = static_cast + (BSPF::clampw(mode + direction, 0, static_cast(PhosphorHandler::NumTypes - 1))); + switch(mode) { - myOSystem.frameBuffer().tiaSurface().enablePhosphor( - myProperties.get(PropType::Display_Phosphor) == "YES", - BSPF::stoi(myProperties.get(PropType::Display_PPBlend))); - myTIA->enableAutoPhosphor(false); + case PhosphorHandler::Always: + myOSystem.frameBuffer().tiaSurface().enablePhosphor( + true, myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND)); + myTIA->enableAutoPhosphor(false); + break; + + case PhosphorHandler::Auto_on: + case PhosphorHandler::Auto: + myOSystem.frameBuffer().tiaSurface().enablePhosphor( + false, myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND)); + myTIA->enableAutoPhosphor(true, mode == PhosphorHandler::Auto_on); + break; + + default: // PhosphorHandler::ByRom + myOSystem.frameBuffer().tiaSurface().enablePhosphor( + myProperties.get(PropType::Display_Phosphor) == "YES", + BSPF::stoi(myProperties.get(PropType::Display_PPBlend))); + myTIA->enableAutoPhosphor(false); + break; } - else if(mode == 1) - { - myOSystem.frameBuffer().tiaSurface().enablePhosphor( - true, myOSystem.settings().getInt("tv.phosblend")); - myTIA->enableAutoPhosphor(false); - } - else - { - myOSystem.frameBuffer().tiaSurface().enablePhosphor( - false, myOSystem.settings().getInt("tv.phosblend")); - myTIA->enableAutoPhosphor(true); - } - myOSystem.settings().setValue("tv.phosphor", VALUE[mode]); + myOSystem.settings().setValue(PhosphorHandler::SETTING_MODE, + PhosphorHandler::toPhosphorName(mode)); } ostringstream msg; msg << "Phosphor mode " << MESSAGES[mode]; @@ -1217,16 +1223,17 @@ void Console::changePaddleAxesRange(int direction) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::toggleAutoFire(bool toggle) { - const bool enabled = myOSystem.settings().getBool("autofire"); + bool enabled = myOSystem.settings().getBool("autofire"); if(toggle) { - myOSystem.settings().setValue("autofire", !enabled); - Controller::setAutoFire(!enabled); + enabled = !enabled; + myOSystem.settings().setValue("autofire", enabled); + Controller::setAutoFire(enabled); } ostringstream ss; - ss << "Autofire " << (!enabled ? "enabled" : "disabled"); + ss << "Autofire " << (enabled ? "enabled" : "disabled"); myOSystem.frameBuffer().showTextMessage(ss.str()); } diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 7ab8af4d8..e96e13302 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -214,7 +214,7 @@ class Console : public Serializable, public ConsoleIO public: /** - Toggle between NTSC/PAL/SECAM (and variants) display format. + Switch between NTSC/PAL/SECAM (and variants) display format. @param direction +1 indicates increase, -1 indicates decrease. */ @@ -250,7 +250,7 @@ class Console : public Serializable, public ConsoleIO /** Toggles phosphor effect. */ - void togglePhosphor(); + void togglePhosphor(bool toggle = true); /** Toggles auto-phosphor. diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index d1198a2f7..3d2bdbd3d 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -134,7 +134,7 @@ void EventHandler::initialize() // Default phosphor blend Properties::setDefault(PropType::Display_PPBlend, - myOSystem.settings().getString("tv.phosblend")); + myOSystem.settings().getString(PhosphorHandler::SETTING_BLEND)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 95e27f0cd..0ce5f28f7 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -326,26 +326,31 @@ FBInitStatus FrameBuffer::createDisplay(string_view title, BufferType type, if(myOSystem.eventHandler().inTIAMode()) { // Phosphor mode can be enabled either globally or per-ROM - int p_blend = 0; - bool enable = false; - const string phosphor = myOSystem.settings().getString("tv.phosphor"); + int p_blend; + bool enable; + const int phosphorMode = PhosphorHandler::toPhosphorMode( + myOSystem.settings().getString(PhosphorHandler::SETTING_MODE)); - myOSystem.console().tia().enableAutoPhosphor(phosphor == "auto"); + switch(phosphorMode) + { + case PhosphorHandler::Always: + enable = true; + p_blend = myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND); + myOSystem.console().tia().enableAutoPhosphor(false); + break; - if(phosphor == "always") - { - p_blend = myOSystem.settings().getInt("tv.phosblend"); - enable = true; - } - else if(phosphor == "auto") - { - p_blend = myOSystem.settings().getInt("tv.phosblend"); - enable = false; - } - else - { - p_blend = BSPF::stoi(myOSystem.console().properties().get(PropType::Display_PPBlend)); - enable = myOSystem.console().properties().get(PropType::Display_Phosphor) == "YES"; + case PhosphorHandler::Auto_on: + case PhosphorHandler::Auto: + enable = false; + p_blend = myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND); + myOSystem.console().tia().enableAutoPhosphor(true, phosphorMode == PhosphorHandler::Auto_on); + break; + + default: // PhosphorHandler::ByRom + enable = myOSystem.console().properties().get(PropType::Display_Phosphor) == "YES"; + p_blend = BSPF::stoi(myOSystem.console().properties().get(PropType::Display_PPBlend)); + myOSystem.console().tia().enableAutoPhosphor(false); + break; } myTIASurface->enablePhosphor(enable, p_blend); } diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 0aeba5ed9..00bcbff3a 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -99,8 +99,8 @@ Settings::Settings() setPermanent("pal.gamma", "0.0"); // TV filtering options setPermanent("tv.filter", "0"); - setPermanent("tv.phosphor", "byrom"); - setPermanent("tv.phosblend", "50"); + setPermanent(PhosphorHandler::SETTING_MODE, PhosphorHandler::VALUE_BYROM); + setPermanent(PhosphorHandler::SETTING_BLEND, PhosphorHandler::DEFAULT_BLEND); setPermanent("tv.scanlines", "0"); setPermanent("tv.scanmask", TIASurface::SETTING_STANDARD); // TV options when using 'custom' mode @@ -361,11 +361,12 @@ void Settings::validate() sort(s.begin(), s.end()); if(s != "bgopry") setValue("tia.dbgcolors", "roygpb"); - s = getString("tv.phosphor"); - if(s != "always" && s != "byrom" && s != "auto") setValue("tv.phosphor", "byrom"); + if(PhosphorHandler::toPhosphorMode(getString(PhosphorHandler::SETTING_MODE)) == PhosphorHandler::ByRom) + setValue(PhosphorHandler::SETTING_MODE, PhosphorHandler::VALUE_BYROM); - i = getInt("tv.phosblend"); - if(i < 0 || i > 100) setValue("tv.phosblend", "50"); + i = getInt(PhosphorHandler::SETTING_BLEND); + if(i < 0 || i > 100) + setValue(PhosphorHandler::SETTING_BLEND, PhosphorHandler::DEFAULT_BLEND); s = getString("tv.scanmask"); if(s != TIASurface::SETTING_STANDARD @@ -576,8 +577,8 @@ void Settings::usage() << " -tia.correct_aspect <1|0> Enable aspect ratio correct scaling\n\n" << " -tv.filter <0-5> Set TV effects off (0) or to specified mode\n" << " (1-5)\n" - << " -tv.phosphor When to use phosphor mode\n" - << " byrom\n" + << " -tv.phosphor When to use phosphor mode\n" + << " autoon|auto\n" << " -tv.phosblend <0-100> Set default blend level in phosphor mode\n" << " -tv.scanlines <0-100> Set scanline intensity to percentage\n" << " (0 disables completely)\n" diff --git a/src/emucore/tia/TIA.cxx b/src/emucore/tia/TIA.cxx index 795e10e0b..842610ffd 100644 --- a/src/emucore/tia/TIA.cxx +++ b/src/emucore/tia/TIA.cxx @@ -23,6 +23,7 @@ #include "TIAConstants.hxx" #include "AudioQueue.hxx" #include "DispatchResult.hxx" +#include "PhosphorHandler.hxx" #include "Base.hxx" enum CollisionMask: uInt32 { @@ -187,11 +188,14 @@ void TIA::initialize() myFrontBuffer.fill(0); myFramebuffer.fill(0); + // Prepare variables for auto-phosphor memset(&myPosP0, 0, sizeof(ObjectPos)); memset(&myPosP1, 0, sizeof(ObjectPos)); memset(&myPosM0, 0, sizeof(ObjectPos)); memset(&myPosM1, 0, sizeof(ObjectPos)); memset(&myPosBL, 0, sizeof(ObjectPos)); + memset(&myPatPF, 0, sizeof(ObjectGfx)); + myFrameEnd = 0; applyDeveloperSettings(); @@ -200,8 +204,12 @@ void TIA::initialize() setFixedColorPalette(mySettings.getString("tia.dbgcolors")); enableFixedColors( mySettings.getBool(devSettings ? "dev.debugcolors" : "plr.debugcolors")); - myAutoPhosphorEnabled = mySettings.getString("tv.phosphor") == "auto"; + // Auto-phosphor settings: + const string mode = mySettings.getString(PhosphorHandler::SETTING_MODE); + myAutoPhosphorAutoOn = mode == PhosphorHandler::VALUE_AUTO_ON; + myAutoPhosphorEnabled = myAutoPhosphorAutoOn || mode == PhosphorHandler::VALUE_AUTO; myAutoPhosphorActive = false; + myFlickerCount = 0; #ifdef DEBUGGER_SUPPORT createAccessArrays(); @@ -1407,6 +1415,9 @@ void TIA::onFrameComplete() if(myAutoPhosphorEnabled) { + // Calculate difference to previous frames (with some margin). + // If difference to latest frame is larger than to older frames, and this happens for + // multiple frames, enabled phosphor mode. static constexpr int MIN_FLICKER_DELTA = 6; static constexpr int MAX_FLICKER_DELTA = TIAConstants::H_PIXEL - MIN_FLICKER_DELTA; static constexpr int MIN_DIFF = 4; @@ -1414,37 +1425,34 @@ void TIA::onFrameComplete() int diffCount[FLICKER_FRAMES - 1]; - //cerr << missingScanlines << ", " << myFrontBufferScanlines << " | "; + //cerr << missingScanlines << ", " << myFrameEnd << " | "; //cerr << myFlickerFrame << ": "; for(int frame = 0; frame < FLICKER_FRAMES - 1; ++frame) { - int otherFrame = (myFlickerFrame + frame + 1) % FLICKER_FRAMES; - //cerr << otherFrame << " "; - // TODO: - // - differentiate fast movement and flicker - // - movement is directional - // - flicker goes back and forth - // - ignore disabled objects - diffCount[frame] = 0; - for(uInt32 y = 0; y < myFrontBufferScanlines; ++y) + const int otherFrame = (myFlickerFrame + frame + 1) % FLICKER_FRAMES; + int count = 0; + for(uInt32 y = 0; y <= myFrameEnd; ++y) { int delta; delta = std::abs(myPosP0[y][myFlickerFrame] - myPosP0[y][otherFrame]); if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA) - ++diffCount[frame]; + ++count; delta = std::abs(myPosP1[y][myFlickerFrame] - myPosP1[y][otherFrame]); if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA) - ++diffCount[frame]; + ++count; delta = std::abs(myPosM0[y][myFlickerFrame] - myPosM0[y][otherFrame]); if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA) - ++diffCount[frame]; + ++count; delta = std::abs(myPosM1[y][myFlickerFrame] - myPosM1[y][otherFrame]); if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA) - ++diffCount[frame]; + ++count; delta = std::abs(myPosBL[y][myFlickerFrame] - myPosBL[y][otherFrame]); if(delta >= MIN_FLICKER_DELTA && delta <= MAX_FLICKER_DELTA) - ++diffCount[frame]; + ++count; + if(myPatPF[y][myFlickerFrame] != myPatPF[y][otherFrame]) + ++count; } + diffCount[frame] = count; } //cerr << ": "; //for(int i = 0; i < FLICKER_FRAMES - 1; ++i) @@ -1461,6 +1469,9 @@ void TIA::onFrameComplete() { myAutoPhosphorActive = true; myPhosphorCallback(true); + // If auto-on, disable phosphor automatic (phosphor stays enabled) + if(myAutoPhosphorAutoOn) + myAutoPhosphorEnabled = false; } } } @@ -1481,7 +1492,6 @@ void TIA::onFrameComplete() if(--myFlickerFrame < 0) myFlickerFrame = FLICKER_FRAMES - 1; } - ++myFramesSinceLastRender; } @@ -1619,8 +1629,10 @@ void TIA::applyRsync() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FORCE_INLINE void TIA::nextLine() { + bool cloned = false; if (myLinesSinceChange >= 2) { cloneLastLine(); + cloned = true; } myHctr = 0; @@ -1642,48 +1654,43 @@ FORCE_INLINE void TIA::nextLine() { if(myFrameManager->getY() == 0) flushLineCache(); + + // Save positions of objects for auto-phosphor if(myAutoPhosphorEnabled) { // Test ROMs: // - missing phosphor: - // x Princess Rescue: Lives display (~same x-position, different y-position) // - QB: flicker sprite for multi color (same position, different shape and color) // - Star Castle Arcade: vector font flicker (same position, different shape) // - Omega Race: no phosphor enabled (flickers every 2nd frame) // - Riddle of the Sphinx: shots (too small to be detected) - // - Missile Command: explosions - // - Yars' Revenge: shield, neutral zone (PF flicker) + // x Yars' Revenge: shield, neutral zone (PF flicker) // // - unneccassary phosphor: - // - Gas Hog: before game starts (odd invisible position changes) + // - Gas Hog: before game starts (odd invisible sprite position changes) // x Turmoil: M1 rockets (gap between RESM1 and HMOVE?) // x Fathom: seaweed (many sprites moving vertically) // x FourPlay: game start (???) // x Freeway: always (too many sprites?) const uInt32 y = myFrameManager->getY(); - //const int otherFrame = myFlickerFrame ^ 1; - //cerr << y << " "; - //if(myPlayer0.getGRPOld() != 0) - myPosP0[y][myFlickerFrame] = myPlayer0.getPosition(); - //if(myPlayer1.getGRPOld() != 0) - myPosP1[y][myFlickerFrame] = myPlayer1.getPosition(); - //if(myMissile0.isOn()) - myPosM0[y][myFlickerFrame] = myMissile0.getPosition(); - //else - // myPosM0[y][myFlickerFrame] = myPosM0[y][otherFrame]; - //if(myMissile1.isOn()) - myPosM1[y][myFlickerFrame] = myMissile1.getPosition(); - //else - // myPosM1[y][myFlickerFrame] = myPosM1[y][otherFrame]; - //if(myBall.isOn()) - myPosBL[y][myFlickerFrame] = myBall.getPosition(); - //else - // myPosBL[y][myFlickerFrame] = myPosBL[y][otherFrame]; - //cerr << int(myPlayer0.getPosition()) << " "; + myPosP0[y][myFlickerFrame] = myPlayer0.getPosition(); + myPosP1[y][myFlickerFrame] = myPlayer1.getPosition(); + // Only use new position if missile/ball are enabled + if(myMissile0.isOn()) + myPosM0[y][myFlickerFrame] = myMissile0.getPosition(); + if(myMissile1.isOn()) + myPosM1[y][myFlickerFrame] = myMissile1.getPosition(); + if(myBall.isOn()) + myPosBL[y][myFlickerFrame] = myBall.getPosition(); + // Note: code checks only right side of playfield + myPatPF[y][myFlickerFrame] = (uInt32(registerValue(PF0))) << 16 + | (uInt32(registerValue(PF1))) << 8 | uInt32(registerValue(PF2)); + // Define end of frame for faster auto-phosphor calculation + if(!cloned) + myFrameEnd = y; } } - mySystem->m6502().clearHaltRequest(); } @@ -1705,6 +1712,7 @@ void TIA::cloneLastLine() std::copy_n(myBackBuffer.begin() + (y - 1) * TIAConstants::H_PIXEL, TIAConstants::H_PIXEL, myBackBuffer.begin() + y * TIAConstants::H_PIXEL); + // Save positions of objects for auto-phosphor if(myAutoPhosphorEnabled) { myPosP0[y][myFlickerFrame] = myPosP0[y - 1][myFlickerFrame]; @@ -1712,6 +1720,7 @@ void TIA::cloneLastLine() myPosM0[y][myFlickerFrame] = myPosM0[y - 1][myFlickerFrame]; myPosM1[y][myFlickerFrame] = myPosM1[y - 1][myFlickerFrame]; myPosBL[y][myFlickerFrame] = myPosBL[y - 1][myFlickerFrame]; + myPatPF[y][myFlickerFrame] = myPatPF[y - 1][myFlickerFrame]; } } } diff --git a/src/emucore/tia/TIA.hxx b/src/emucore/tia/TIA.hxx index 811c80c64..1db52d95c 100644 --- a/src/emucore/tia/TIA.hxx +++ b/src/emucore/tia/TIA.hxx @@ -301,29 +301,16 @@ class TIA : public Device /** Enables/disables auto-phosphor. - @param enabled Whether to enable or disable auto-phosphor mode + @param enabled Whether to use auto-phosphor mode + @param autoOn Whether to only ENABLE phosphor mode */ - void enableAutoPhosphor(bool enabled) + void enableAutoPhosphor(bool enabled, bool autoOn = false) { myAutoPhosphorEnabled = enabled; - if(!enabled) - myAutoPhosphorActive = false; + myAutoPhosphorAutoOn = autoOn; + myAutoPhosphorActive = false; } - /** - Answers whether auto-phosphor is enabled. - - @return Auto-phosphor is enabled - */ - bool autoPhosphorEnabled() const { return myAutoPhosphorEnabled; } - - /** - Answers whether auto-phosphor is active. - - @return Auto-phosphor is acitve - */ - bool autoPhosphorActive() const { return myAutoPhosphorActive; } - /** Answers the current color clock we've gotten to on this scanline. @@ -998,13 +985,17 @@ class TIA : public Device /** * Auto-phosphor detection variables. */ - bool myAutoPhosphorEnabled{true}; - bool myAutoPhosphorActive{true}; static constexpr int FLICKER_FRAMES = 1 + 4; // compare current frame with previous 4 frames using ObjectPos = BSPF::array2D; + using ObjectGfx = BSPF::array2D; + + bool myAutoPhosphorEnabled{false}; + bool myAutoPhosphorAutoOn{false}; + bool myAutoPhosphorActive{false}; ObjectPos myPosP0, myPosP1, myPosM0, myPosM1, myPosBL; - int myFlickerFrame{0}; - int myFlickerCount{0}; + ObjectGfx myPatPF; + int myFlickerFrame{0}, myFlickerCount{0}; + uInt32 myFrameEnd{0}; onPhosphorCallback myPhosphorCallback; #ifdef DEBUGGER_SUPPORT diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index e1bd070b7..35d2f836d 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -160,7 +160,7 @@ void GameInfoDialog::addEmulationTab() // Phosphor ypos += lineHeight + VGAP; myPhosphor = new CheckboxWidget(myTab, _font, HBORDER, ypos + 1, - "Phosphor (auto-enabled for all ROMs)", kPhosphorChanged); + "Phosphor (auto-enabled/disabled for all ROMs)", kPhosphorChanged); myPhosphor->setToolTip(Event::TogglePhosphor); wid.push_back(myPhosphor); @@ -804,13 +804,14 @@ void GameInfoDialog::loadEmulationProperties(const Properties& props) myFormatDetected->setLabel(""); // if phosphor is always enabled, disable game specific phosphor settings - const bool alwaysPhosphor = instance().settings().getString("tv.phosphor") == "always"; - const bool autoPhosphor = instance().settings().getString("tv.phosphor") == "auto"; + const string mode = instance().settings().getString(PhosphorHandler::SETTING_MODE); const bool usePhosphor = props.get(PropType::Display_Phosphor) == "YES"; myPhosphor->setState(usePhosphor); - if (alwaysPhosphor) + if (mode == PhosphorHandler::VALUE_ALWAYS) myPhosphor->setLabel("Phosphor (enabled for all ROMs"); - else if (autoPhosphor) + else if (mode == PhosphorHandler::VALUE_AUTO) + myPhosphor->setLabel("Phosphor (auto-enabled/disabled for all ROMs)"); + else if (mode == PhosphorHandler::VALUE_AUTO_ON) myPhosphor->setLabel("Phosphor (auto-enabled for all ROMs)"); else myPhosphor->setLabel("Phosphor"); @@ -1195,7 +1196,8 @@ void GameInfoDialog::updateMultiCart() myFormat->setEnabled(!isMulti); // if phosphor is always enabled, disable game specific phosphor settings - const bool globalPhosphor = isMulti || instance().settings().getString("tv.phosphor") != "byrom"; + const bool globalPhosphor = isMulti + || instance().settings().getString(PhosphorHandler::SETTING_MODE) != PhosphorHandler::VALUE_BYROM; myPhosphor->setEnabled(!globalPhosphor); myPPBlend->setEnabled(!globalPhosphor && myPhosphor->getState()); diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx index 734125b3f..0c5ebafb5 100644 --- a/src/gui/StellaSettingsDialog.cxx +++ b/src/gui/StellaSettingsDialog.cxx @@ -235,7 +235,7 @@ void StellaSettingsDialog::loadConfig() myTVScanIntense->setValue(valueToLevel(settings.getInt("tv.scanlines"))); // TV phosphor blend - myTVPhosLevel->setValue(valueToLevel(settings.getInt("tv.phosblend"))); + myTVPhosLevel->setValue(valueToLevel(settings.getInt(PhosphorHandler::SETTING_BLEND))); // TV overscan myTVOverscan->setValue(settings.getInt("tia.fs_overscan")); @@ -274,10 +274,10 @@ void StellaSettingsDialog::saveConfig() myTVMode->getSelectedTag().toString()); // TV phosphor mode - instance().settings().setValue("tv.phosphor", - myTVPhosLevel->getValue() > 0 ? "always" : "byrom"); + instance().settings().setValue(PhosphorHandler::SETTING_MODE, + myTVPhosLevel->getValue() > 0 ? PhosphorHandler::VALUE_ALWAYS : PhosphorHandler::VALUE_BYROM); // TV phosphor blend - instance().settings().setValue("tv.phosblend", + instance().settings().setValue(PhosphorHandler::SETTING_BLEND, levelToValue(myTVPhosLevel->getValue())); // TV scanline intensity and interpolation diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx index 50b74ad6a..afe0f4dcc 100644 --- a/src/gui/VideoAudioDialog.cxx +++ b/src/gui/VideoAudioDialog.cxx @@ -381,11 +381,12 @@ void VideoAudioDialog::addTVEffectsTab() // TV Phosphor effect items.clear(); - VarList::push_back(items, "by ROM", "byrom"); - VarList::push_back(items, "always", "always"); - VarList::push_back(items, "auto", "auto"); + VarList::push_back(items, "by ROM", PhosphorHandler::VALUE_BYROM); + VarList::push_back(items, "always", PhosphorHandler::VALUE_ALWAYS); + VarList::push_back(items, "auto on", PhosphorHandler::VALUE_AUTO_ON); + VarList::push_back(items, "auto on/off", PhosphorHandler::VALUE_AUTO); myTVPhosphor = new PopUpWidget(myTab, _font, xpos, ypos, - _font.getStringWidth("by ROM"), lineHeight, + _font.getStringWidth("auto on/off"), lineHeight, items, "Phosphor ", 0, kPhosphorChanged); myTVPhosphor->setToolTip(Event::PhosphorModeDecrease, Event::PhosphorModeIncrease); wid.push_back(myTVPhosphor); @@ -760,8 +761,8 @@ void VideoAudioDialog::loadConfig() loadTVAdjustables(NTSCFilter::Preset::CUSTOM); // TV phosphor mode & blend - myTVPhosphor->setSelected(settings.getString("tv.phosphor"), "byrom"); - myTVPhosLevel->setValue(settings.getInt("tv.phosblend")); + myTVPhosphor->setSelected(settings.getString(PhosphorHandler::SETTING_MODE), PhosphorHandler::VALUE_BYROM); + myTVPhosLevel->setValue(settings.getInt(PhosphorHandler::SETTING_BLEND)); handlePhosphorChange(); // TV scanline intensity & mask @@ -895,9 +896,9 @@ void VideoAudioDialog::saveConfig() NTSCFilter::saveConfig(settings); // TV phosphor mode & blend - settings.setValue("tv.phosphor", myTVPhosphor->getSelectedTag()); - settings.setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off" - ? "0" : myTVPhosLevel->getValueLabel()); + settings.setValue(PhosphorHandler::SETTING_MODE, myTVPhosphor->getSelectedTag()); + settings.setValue(PhosphorHandler::SETTING_BLEND, myTVPhosLevel->getValueLabel() == "Off" + ? "0" : myTVPhosLevel->getValueLabel()); // TV scanline intensity & mask settings.setValue("tv.scanlines", myTVScanIntense->getValueLabel()); @@ -1035,7 +1036,7 @@ void VideoAudioDialog::setDefaults() myTVMode->setSelected("0", "0"); // TV phosphor mode & blend - myTVPhosphor->setSelected("byrom"); + myTVPhosphor->setSelected(PhosphorHandler::VALUE_BYROM); myTVPhosLevel->setValue(50); // TV scanline intensity & mask @@ -1215,7 +1216,7 @@ void VideoAudioDialog::handleOverscanChange() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void VideoAudioDialog::handlePhosphorChange() { - myTVPhosLevel->setEnabled(myTVPhosphor->getSelectedTag() != "byrom"); + myTVPhosLevel->setEnabled(myTVPhosphor->getSelectedTag() != PhosphorHandler::VALUE_BYROM); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/Widget.cxx b/src/gui/Widget.cxx index 76fcd7118..1281f8dda 100644 --- a/src/gui/Widget.cxx +++ b/src/gui/Widget.cxx @@ -314,7 +314,7 @@ string Widget::getToolTip(const Common::Point& pos) const const string hotkey2 = instance().eventHandler().keyHandler().getMappingDesc( _toolTipEvent2, _toolTipMode); - if(hotkey2 != EmptyString) + if(hotkey != EmptyString && hotkey2 != EmptyString) { // Merge hotkeys if they only differ by "-Shift" const string mod = "-Shift"; @@ -333,6 +333,8 @@ string Widget::getToolTip(const Common::Point& pos) const else hotkey += ", " + hotkey2; } + else + hotkey += hotkey2; if(hotkey == EmptyString) return _toolTipText; diff --git a/src/os/windows/Stella.vcxproj b/src/os/windows/Stella.vcxproj index b00039f86..b116d90e1 100755 --- a/src/os/windows/Stella.vcxproj +++ b/src/os/windows/Stella.vcxproj @@ -98,6 +98,7 @@ MultiByte v143 false + PGOptimize Application @@ -486,6 +487,8 @@ CompileAsCpp NoListing $(IntDir)asm\windows\%(RelativeDir) + MaxSpeed + Default SDL2.lib;SDL2main.lib;SDL2main.lib;%(AdditionalDependencies)