From 269b27425785826b8e63734bb524f1cb58be22b6 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Mon, 10 Aug 2015 21:19:13 +0200 Subject: [PATCH 01/25] updated aros rom, added log_autoscale option --- ChangeLog | 6 +- doc/options/log_autoscale | 7 + doc/options/uae_gfx_linemode | 26 +-- libfsemu/src/log.c | 4 +- share/fs-uae/aros-amiga-m68k-ext.bin | Bin 524288 -> 524288 bytes share/fs-uae/aros-amiga-m68k-rom.bin | Bin 524288 -> 524288 bytes src/fs-uae/main.c | 4 +- src/fs-uae/options.h | 2 + src/fs-uae/video.c | 227 ++++++++++++++++----------- src/memory.cpp | 6 +- src/od-fs/libamiga.cpp | 14 +- src/od-fs/stubs.cpp | 7 +- 12 files changed, 180 insertions(+), 123 deletions(-) create mode 100644 doc/options/log_autoscale diff --git a/ChangeLog b/ChangeLog index 90fc3b86d..c4e3e0752 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ +Version 2.5.39dev: + +* Updated AROS kickstart replacement to ver. 2015-05-20 from WinUAE 3.1.0. + Version 2.5.38dev: -* Several new and update joystick and gamepad configs. +* Several new and updated joystick and gamepad configs. * Built-in configs for Xbox 360 / One pads on OS X (requires driver). * Changed default stereo separation setting to 70%. * Windows builds are digitally signed again. diff --git a/doc/options/log_autoscale b/doc/options/log_autoscale new file mode 100644 index 000000000..634ba5579 --- /dev/null +++ b/doc/options/log_autoscale @@ -0,0 +1,7 @@ +Summary: Log Autoscale Changes +Type: boolean +Default: 0 +Example: 1 + +This option will cause changes in autoscale coordinates to be logged to +the log file *and* stdout. diff --git a/doc/options/uae_gfx_linemode b/doc/options/uae_gfx_linemode index 4be386855..db56a13e1 100644 --- a/doc/options/uae_gfx_linemode +++ b/doc/options/uae_gfx_linemode @@ -2,23 +2,23 @@ Description: Controls how lines are doubled and interlaced modes are handled Example: double2 Type: choice -Value: none ("Single / Single") +Value: none (Single / Single) -Value: double ("Double / Double Frames") -value: double2 ("Double / Double Fields") -Value: double3 ("Double / Double Fields+") +Value: double (Double / Double Frames) +value: double2 (Double / Double Fields) +Value: double3 (Double / Double Fields+) -Value: scanlines ("Scanlines / Double Frames") -Value: scanlines2 ("Scanlines / Double Fields") -Value: scanlines3 ("Scanlines / Double Fields+") +Value: scanlines (Scanlines / Double Frames) +Value: scanlines2 (Scanlines / Double Fields) +Value: scanlines3 (Scanlines / Double Fields+) -Value: scanlines2p ("Double Fields / Double Frames") -value: scanlines2p2 ("Double Fields / Double Fields") -Value: scanlines2p3 ("Double Fields / Double Fields+") +Value: scanlines2p (Double Fields / Double Frames) +value: scanlines2p2 (Double Fields / Double Fields) +Value: scanlines2p3 (Double Fields / Double Fields+) -Value: scanlines3p ("Double Fields+ / Double Frames") -Value: scanlines3p2 ("Double Fields+ / Double Fields") -Value: scanlines3p3 ("Double Fields+ / Double Fields+") +Value: scanlines3p (Double Fields+ / Double Frames) +Value: scanlines3p2 (Double Fields+ / Double Fields) +Value: scanlines3p3 (Double Fields+ / Double Fields+) Single: Non-interlaced lines are not doubled. diff --git a/libfsemu/src/log.c b/libfsemu/src/log.c index 866ea899c..d5b41f2f7 100644 --- a/libfsemu/src/log.c +++ b/libfsemu/src/log.c @@ -41,7 +41,7 @@ static void initialize() log.initial_path = g_build_filename(dir, "fs-uae.log", NULL); log.file = g_fopen(log.initial_path, "w"); if (log.file) { - printf("logging to %s\n", log.initial_path); + // printf("[LOG] %s\n", log.initial_path); } g_free(dir); } @@ -60,7 +60,7 @@ void fs_config_set_log_file(const char *path) } log.file = g_fopen(path, "w"); if (log.file) { - printf("logging to %s\n", path); + printf("LOG: %s\n", path); if (log.initial_path) { FILE *f = g_fopen(log.initial_path, "r"); if (f) { diff --git a/share/fs-uae/aros-amiga-m68k-ext.bin b/share/fs-uae/aros-amiga-m68k-ext.bin index 905cd25b3789a1c2d58d4a8eb48c13b798bd230f..89ac6a4f90512d04cf52d42d35f6941f5ae65dfa 100755 GIT binary patch delta 47990 zcmb@v4Oo=L8b3TU&jYN8h=_=YxFRC*wTOs_gb1jJM5t(}sH-C27ZQ;nk)RQJ$iiH6 zJmxX;n39^X#gRb*}gSUhnndH9KGT+;h*& zJ@?#m&&*?axwgDqyLMEk!NZ3S4UGsNJoNR^L!2YR!@`G#iJ0LT&y?4{t?q;rTSD!8 z`lTa#A>D9sptpv!r5z;J7t(p-35P)5aL=K$VU?yod;Sb>z30%w@R=r5K(=bakyPu~ zX(nUU>9s36ua*4PlJx3PzmT<_H5!um3)$N984V#+rz0skCU904)kb!$VCBtpgs;MBRw-ymo!CGP(+eS?Lw;C$C_jgD~=$v79_hA#x5!2td6Vr2<#5Cp( zF^#eiQ=$hkolGXCcVuE(e}I^3;oeCirs);L^zIpAnzf&pcK8$1H`j=%tdW?uBdsP7 zE*7rX5a}_3W*Q1S#?NaYrk9F{snUm-R<0+e>I`DqbBmac0nbaviD~K)V%moCjldPR znwa)!h$#!{VW6%io0tZ{t&b!o1In!fZD}sV^nM62eZHQUjslP20x^BrV$k;JJ-UdP zR>74c<=r}BI<*^q82kd1Jc<@BLW_{L46X#!7*R_$;FCRwX*2o}f2O@!LwS$hRAboO zV^|kZzW)rU*pAjm8%#ZV_sazR<-{}|klz$2CDcErkMayYp8Z4PiRoLE$piic7Bv8A ziro!&ku*Kw3Kt2=>t1i2Zuru(r;1g6^z`Xmc1J1KM6%#h(nQX~mq-)!htHHe@zX?; zm2eYnfDbr&6F%U4W8kacm>sUqIvbqNRVBa4C&C8by9B;Wn!Jy|cOXq=-p&X(lBQl0 z;X9EguTAhZq^YN7K>AqejRKN3C~+5HgwuJGgGyOAdM z^YFXDFM{t*n!4SC-yOan%!4$!orT|nlr0+x-D$_CSE$A87Xj?fxLUA7uA~?S6>e54HPY zc3)@r!|ncHyB}fqhuHl{yZ^*cdmzg053~Exc7Hf&>T(4=5Mz&zu=}yXuZ{KJD%qrs z7T&tRF`D8OAs>n}3~7O$+GXUaUx-Ued2Wf$HMy8j#VsQy&jVxc66^D43>AS1qWJN^ z2#6p)W#3GNLjXLtv2|dv`1@ZbxM4$t1g9jrC!RC)9w<}AC9%> zLY}1bf*~MmBCELASwQ*`6$5yLj!D7xKX(QQS3ZDn{UplkOH_HuNq zPEW56A^xdLNl+}Yt}ZfM7}hF^or;cPtBYzKhlk2E&Jg*;->A2t{)uHyv1pv>!VyEm z{1}62p@ZSYxb^+*X=rI6Xd9zVN!!!jik7!@Kx4@@JY`zy56vJ@&FoPI5l}7 zes516PH!8+r}XRVg~C4CB_z^TKae=(conH3rLqslX7oaJCAAV7WfDw6f)~`jjZ)t62!#(NO!uCBYF0CQ<#d8O#|+Vd~TV#sSv6`3eoR2#FZLHLHYzYXXV zPQnM364ULX+Mucc3EG8W;;VYL`i^1WtBXVhey`o76}3Lqzf07`;BL@^Sqw#nGDL0} zW(v;9SieZ&rz3By7xOoB!xyxZo1(IqI=0pZZ2X0F^3rvI@Ilnz`(}R(Y{Hv^DcV)E zIZ{xyYcqtyRl~V|{0qN3x3ma>vhJ-N>~DF7n61~HN^A^Z2z%Q{)SdeF6OcPqZ@;LB zho=p*w)s5-c_1Rb+!l`9JKJ9BZ!i3R;hq;CVrU&XvUc`%FGg<~N_OZ)`!DSH8Uw%c z-D=u(Y4T!gE4o)mn5JQswPW7Hln5|v-Ss^6H+a1t>0VuwUL8PkeK8MZF$7@$neX=y z98uSwWNGzlMA+aSjm61Rp?{?`s?ZMXa@PAT2R?ecP9o8lt}q6kRjt+pnB7PuhSYP7eW4&S?Sk z+GzmQ?m0bO!s6h3wm*0v>?~%cA@%GmtSr0F&J_!c+qo`cRr3AMlZY((PbY@R(*MrJ z@45eeg`{m4KBqvFb8(RH)?OM7&v4c>3z4X%1ym5Q&71(Q_KG=9bb}$_axA#okbQYB zbu=8mti$h}%d_!2?aKG~4gc|~hY$eTMOb^p)N`|UXIM)u?X5}M0M7G>CJ@10bPgj) zLTu+iJD`LcBv38q%%3JJ~QC30YWMWc3yz&*kDTx+QKSfc9 z*Abng=u?~8;1_B=siQh4TZ%E;fqp|BPWmk-8m{R?`x+-Z(GMy6{f^PG6a9eF6u!@y z{)?6vD>_q+sDi)dLNkPKaiK%0g?o3Q&6MztF7!(p&5yZKBQ594yTUszyaZnCMxUc@ z{DvEnGWm{fG?%t=S9iLMF6FD;={%7qyj?t_I}*eBsqXYex|h54plN)Q2MXU1;m>Ih zKhp!WmGBBrcqe#dPx?K*#htzAyEIkQoWO5+0en4Q&GK+l9R6{ws1NKyQlB~2$1{C1Bya4%~kgpKs;zEj%?~MFXk>A;ulq0`0@+(B#c?(&M zd>7=ev6o+q{4U5}FXDY?l8wlBMgC?H*I3HPRseJbz;=6qodD1o=L?cq)sylRFRWPdhN@je-8ui$XdX69&*1 zD2?a!0d$U-KYjygjgVga%pjUB{D2_3Mfk^p=(FIkm|!}LZsCQ&G?7N|{lRoB_2M1D zv=~o{{uDO51qD zP&%Kk=0Q=IF>S_mQS@nw=+$BLJ4EZF={!a&x&H|8Z6!ZBg3eb~*9R<$)s-j3(kGF( zE|w0)+&CIbb@VE~6-x)uIo$gRI{I8~!Rbj;BK#@X7EVkhO_>Pi6v4N^-weNzG|ej@O}QC} zuO>~iQFc-*;CCaAw5k3{r0MB!1OPZeI3zxu4Y!^&Wt&M;2KKX~H=-hJD<>j60Z7MX zVpoTqeI}4ReStKkX2L?iXT{MTk4yyo#W?B}yp=S?HLQr}6c7J(xFsU46c#_&c|M_6 zVoeEd#)dfhZ$?A7+d#*DotomjglvQXYUU5rTN9_X$6$^c#JeO=m!Z2C6LQ<%Ibi{q zR=w@Z5PE2C@ngHjrZ~NA*Qi*pbWL&TX$GBZ!n^iOWm8;ynn8?0Se23@wwue)_gh6F zkWl`$Lyrkfae)euo2{VLDnR0*ZFv8LF4>OmHBp5fGE=~y%){-eA%0LVZvEP!GxtfP zU3$3}3<_C>&XBPOJU1Yo1mxx<-X%>V`x_GyA&O}pZ%Cp;Xeqyygjtfr3r5pd=^5TJ znhvLR#^^B=DnlI~GnOu)tBw1|g6$#GJ;%`%NZmLNLV7jNPoal<)CB|)ufPRF7E5{% z3ydXAg{yhOctE&uuT=VU??%zGk#WeeW_xOr($)gfEex?NnOCLK33Lj-kc!zgmusJ- zwS8XkPfA;-9pgV9*1p)lgpfrfC~c2*lY+#^Tc4y)&_*7XhBo}ncc)P;i+A9s(&&JG zo@s9g8nmEbWOT~=M3dvFgoo&eC>%eCdpt$op;7$MQ<+fF5Tut7~3?R@+%AcGV8J zXd-I3pz(w@W4kojxyt89qpn|SLaI*CRblQK{R zmfKU<-od*$na=B8iX#5lK)GVQSHKs#^957rD3G^%3WV5Cq)w8)ic!ZsN)Cx?C5n9;K+s*`CJDvjOdtWA6jaT!^D`W7u5! zF)cfz(~Q20$-gFT9j4MtOEjWjwue4C<)z$dN;q8~lCmNvekHlyV!Uxwnv4p6jOMLG?~MDC$bDPQ4_fucub?IrHeR)WkD#Fmh*jV-DKvCb+$q zF)^3E$V3+&nNQ2mu7m|peoV&V1+*Wf8;qM4QWr&r?_5NKSe9%&vxsIX>qo>A^h30< zWC?wX((~N=8TttZ?CdkN&UK{1YoneA8G>!L7SfTJYNkRukd_)X&qC^>U_p^>r0+dP z|MhT)p(xwN3qyQiDOQO*KIVBy_fo#}c{-V9@srPEYUXjrVrAOK6w^K!(#&EStt>(7 zmeKLF$arxXoh4yV<6guNNAV*s()R^ZET@Z+cwspPb2U#ZqfJN*FQ==Jc%U3pX*G|+ z#4fv#OqwqElcvwy;5-yjDt?-Ngp|GuseN}l93=F8SQ*<3h?yQIX0{RTBr(euh*`6m zm^--Vx9y9naRXFHHnyKZYE|ufaaVf<~$V2D|S=5IDMJ zzW#c@vL+b8&F;rZ(;t<@oZEoTbc1UIod9!K3%V|#TBLg+>|KmbWf;90!2}q2pk26~ zm>pYy?u;$%CsggO1c`aU8g%MWC1Nfu0;%C3?+n^~%a%4j$c31T%E1zXh@#h9C%?Yc zjrTq7;K-XRXpf0Qw1E##j|O#dCiC-)o||7Ze@TAWqWN5J3W+um9|LJg;Hb6%QS{MfBFy7^eL2!dS~NnmGtWf{^>y)(EaHp zg$w7*%b%M^o?Z6r{JD!}Kl`lli$nA^$1;?M8U6$e(O;c`14|sg2Z!bz2MZk4lcpmu zLVq@sG<{hEmqwb7wZc`xfuJvT0p>Jm`urwb1srf40ZV;$5_z$9LSf#&lnUG^_Z3F$ zE8so84{i+bO+5z$-Y9Sj4hX+o0Otbad*HylUjX?R*??IMs!~z`?$b3haF#cK#o*eAF@OPaPG| zzU~h}UH=Mtu8!9n1HtYJtdoxomTx&uJ=wWi-W8tq z1@g`o+w!7#&6hNQ*L*=8oDu}U{wQAe1@&g%@8##dpyQpMQW6umg7JGm3QC@`Q9Z*} z01XWKE7fNv+F)ncVDlcrru-H5yKEb5o(;C}A?*JczSF5T*g`>hC{}=rUxM6kxA6F{ zX~W+uw%O92KTfqy%LUGl?<>6q_3A^>`O8&}U#sL_;Vxf^l7t6-g~tEG zo~U&7sYAAk|6%LS_f>iH8~*xNK={5b>!2!&owSd_K~Y%<`}hiPI6-~biKBuzU*2{C z{dt9J5oRYQinOeL7B6TwonSi>3Q@D=xX`NfA&*j8jGulD9j5F%KQ-LP?q@f(Q8Jc?iPMLb9qPeI(<77r4=bLlD)oF4(0TJ)sj z-lKTa2E?y&{TUcy{7%u71t(L~opy4&(rHDH3VcKK*Hp23{l!PI(@fu}iaF|!sAA6g zeX5wNeuq-&hJVr21;?`0bsnq#bDdvbRoD6T4RxJgdaLXFa-zD<6HC=~etpGWCpZ0z zR+R0DS68}clZ`vbwns$nxvl1o5BI3K<8X?aJ3c3B?)coK=8mKL)ZB4wik&-pDco^v znwmR~&BS1ph<+KsKkY0B_HXXorY6$WO(9an>aJ^e{ns>%Z~B&oglG7ufivbPz_E|o zlToMc#>s9x{yauqdz!|?^_!wD>b*uOs^U8zKXp;9Mm++)Yq-gd$bo-(nhr_xUjIL^ zWj-RL+bK0RuhVL59x>|i^j@n!BKkwepZ|_7DVrLnMm+Vwm{mMNJuOc?X46dSF`K?c zJ!V-c>M@(4QIFZoIQ5v#T&~|x(?&=xAKOV@zOdQRq^3e+lPjtz(m7e(JjXnB^E7AG z&2!$VX4g(c&90qJ*w{5tjF1C=;d?rM+KsiUn$16FD8rQVu=VC&N>w$RZ^o%=Hn&bw z)olLNOI5S^Hy^G&OS8f^9aZChQ`xWTA90X*!y+~QO$%%sboMMwnEE%hur>e9#z895 zs}^M-<%B#EFy^;wR3mSGJ6$#M=C_Mf zBX52uT{ZINcQRBXZ+<6JHS*?nQth*KxR|Zxcd}Ho)%=cL%+^Pp|IQ-B7pUUJh)=W4 z=05+SJvG^_3e~>6;cJ+sFlD>&=l(V{%UjflW=~WQspjD95;daP+ti3=n^o-AJjYkXZq0Kd)pKx83ithi4tLrtcJmKx zhYh#vvGN~iq|awAiwOi(Cxu;S!j&4m>gU@mliWIk*Nw>3hk z?zQA)kC_oY`SNbED{s9BOY?CacZo)_b6a@PC0b3t=dy`L_jvz;a{I+6WfwV;KXS>8AxMc#^=H!wnK0*NEb&J_mBrv2AM-7tRVd0Oaz zfxm@_3px4$@s2wab~)}A)g7Srl#56)D=BV#j)nH`>H7fJ*sD^qIE%#TZ}a>@zS%;P z{7m^1POs61k}xodN6l^$hO_R@I4mOq!rw(q zIT2UP-c09$RP*#21tNrmJ%rIJhxN^IZrt)Cjqeect#|)RDL%Y~2D7JD@|+f0MOX1( zTj&q){`C{AVAJ^Ut8|7qT-kV)9%MbzJ1z$1k+1_;kaPU>nqaWZfplZeb-JD6{Fl4@ zLKB3a{tNw<&f^|LLPsU9uYX@-)Nv>J`1~r!M@0E{4Pyl z2WIj3-)X9*Dq7gAfo%Qnw9fsvqqw&eYIW3wcAOM#{cR(ka~lV;*ZIG1(?rjo_or9m z@W5RgL_Bg!l}-{x!~dXz=rTU-59%k#TK)%}?DR5pgmh>5lSE_vvXCF^A{3(b+?fgGq?a zC0Ve*SGF23L~eRQH-w~uRc;55x86klV(Z1^k`8ek(hO8`J6*u~n|VPyUC(B%=Z+n8 zBE#@c>%cAysEa#jwD9+K(04jDSu^a#^j2CTk}p_k0PDZy4Vn3)^cz78honc}*a9!g z+2~GL6lEPJcnV{cg8tKtg+)dvim5UcZiB4Wl$AMNI%gb|$O-QX?6!Pd8zQ9AHoInp z@kog!v6&}%iNr!gy*nkA8Ff%&y)&YeXsm4sq1FyKE3kNg9~WC2g$$U!USXZFC?Y=#C!@!2J;-8#S{9l7}3ki`>+eR5XG~6 znU6TcEWsw6irU9$S%hHJ5-n30^@x_miFDSF75a|#(IyG2l65I2%y<%lE0TdY{fNaC z$>zlUd|f}31+mBav88l3f5MLqWXP0ZYSe}>x;2%I0l$|;*y&$9-ynK(rHWFQ;JbjjQ@kc|)4C;vDyCOEl$ zO<-D37|9CGCmHRB@SE9Q2wsU+cqL8rJbEoNkc9_{b3P5xg|@E|eHt+bP+AcKPn{ER zt1<Ic_BEyUB6#+pgXK+q(@hVx!wg1_S)U-kS+;}+Y5@R-ck5GCWs9hq|YVP{}Gwg ztKiu&1eT`eQ^#xp@|Ag$tUL99QPUTrYzT{aeV zR3&`Sz7uXc+*ZU_D|A#Ml!ugTxXlF&eYUZX29IiA`Nj#PEQebUw-j!zp2!inyXB?d zptMM{)YhLb`GJT6-v>lm!xG-7rxKE&W*7RoxvW43#_+meHni6<2)%VmLVvVjvl8;p zA<`c19Kr_Rup>N#4IVW`PuNN&Z&)s2Gv~M};V8hxB8MokXq3O8goY#CAL(G4GeQmFq1G!b-r71M z-g>1R$b^sdouUrwHH5Y(AsCnFdZk|2t!R}JT8dD)zz&WlbSbXz$>^qhvX}seQtFnT zl+l?AFh-tcC?L*cF(pbRNo;Y4RSCsB$RTb@Jcuo}{-T7mO6m0|?P;sPt$-|+QC{IZ z7}ZFJEuFL$I10`~%C(2s%B^K+4Y>exWda>J?T>cBKcS$-c#wt%!0`%Eq=qd%tPn+Z zC~eCJ%w{FD8=-Ydxy=ZzRzlhO<)Zx44awyr;@c}HE^e>XFH)tfE<@64{WJx5tA3*5 zZ`Y?N{!V>@3bYE4Rr+ux<;&z%6UXZP0|G&;ufO>9QbFbcGEeVV$S}t?j=F9WE09)= z!q%Td?qAavlv**{_AaHtWr^*3l&;z>LqR~@oOLOy$|YnMW_)&zV}Z4%GB*tCDby`U451j9-C{%H zg+>EO=bz~G89By4QIX{ZjB*A74Q%gOli=U2zt2BVAf|+p&&&eq)`AUNLUCF)#fHGweBy^ zQ4XOGJ}cIVY|qSU7^QKjD@t@dque6#5g4@bxzT*m^4QJip|S(HQ)glqARzH?1Sq{UA()Y{VS3@rlI*Xcum-si ze~~9%N)UPtSh5qZTRjV+MIOOU$)0nXpNL?Cd#ub2DwOwr(7rO)eJL9SB>NHOZbMk8 z1oC;p5H?H+EFZ##1TXLpwcf(|HYQ}THAPtx{d5kZN3h6=J0UK(O&eoN;pc|1RJX2Y z2F6oMdUb9oZgXVj6!XYPHmR>aI#t}{ZTiCnw}L&vV%f?n;Z~qDns1L}|AdH79?JUk zTVB9Kv)dQ>lU$-Hz+$e^IcwvS^N5ca0H_m{L)lmft>mYMvL%_WdiP>*R(n3WEIULx z0Njh~0~{g#Oc)ckWNE21#t|V+zH@SePb{HLd!|-KmJ&HGv^_uh%izTJMTs|elJ8D@ z_tke_CH~|PmUwF;sjr;NUyp*s?LLfohF2A6YN~Q-0z%st!E~Upn({N3Yf8KMC;E;3 z?o0er6|6(`i$qax$wQmMYoeH^OQFZ!N|bg+lb7=7VQgTZrGZkoyGy*)nsYihrG06D zjI8CkF3=7Zw=d_V!`K|L#V`$H&-EXwS2gA!_P}R$PPYmnX`(=z}1;|`k;2j)qJroj5t6o1YHuVQz=B5}{iYq}g zMzD(jkBw#GhB7aSWh?15-X6<(`3#6eHEw8M8rI4KCXV@(*)}WM(DwbQ*R$H%qtj-j zJ@-(m{{Jjg6O#1gS2wo!J{BH`Xsl|jW$Wy$Nps2F3c;c|HT z!ao^1f=WkhZIT~MnZEh5l?3(8cc3Jg?;6RD3MITCp2aKs=)I#@o7nQzB(O1JCxER* zzwsnc_yhCsS}wvqdz%B3xkn<)7n*uSB1WN?3suhc? z)vtFRrc4ZeJ6T6yb#%5?X#4W1$vdZ2^BbnHhWv%f`^vE6@_zS_!=-PXQrRUl6~#oKG3Y zQXEjbzJR|oj*SXLCElpS*IuOtWc~4wEVoLKMRpeaa;%)YrZAs$6ifoyW9-mOA63wf z>sX=@g4{r03VMji8<>3TF*o4-MenM_KyAeeeN4fnqvghu6qZc25pytkY&LG(*lTaq z6HQDZ-8(+VN7%IvRvXRZA&bPM9FvCK{K3ETHEFDzMU)y{pJFZ&gCO#m$lh>jwa>SP zSmwb`PGqgZNL4=x`(12FqcT`j85s3I@{i$Q)BxAfzYs4lYNW!bK{{u#@yEL~SPvB| zs0*Hgc__mf1REqHU32AvNIfeEhXL)uW@jy4jKt^?NV4V^Kn&D}0cR?3D$9B0Oc)^y z*u!QhxkJD){ajGMxq#`!_3i|ciRZ~)!Ww6d#I;*t7fa@?li6lL?rT$6f&0OK5?rD# z$Nr8S5GKuo`?%ZFY-*?c2b)@B;nOUg3izX$*htSjX_Tk3Fk#O!Mowb^6gMQNPiIdF zfZfyCN^!wBJWFhUf84~&XRw}9Gd(5(URd|aX0TrLCI0srY^2lF4A`E{Q~9MCjKh%j z{7m*??7@26#)Ep2woVsJN=2_7G%4X2#3Mxf5boFcEhI6Rvk|&(IETRdEhT*@pEHZ? z1ftG*Rz|1uSM+Qi%ROMcsb_ncux;#^%iI{d<;oAtgIyr4YJU!dFPpcOSLCt^&7tBn zthq38xaGkDkh6;?=L$1b7+sf`Ws7F zyynnZdn~GeMTZ^2CQdF^8>v5Wx8-MwCjxkeIQE)cZy&C3j_s=#27&J{U_-F~y;{KH zMKt6Y7NGeg+>UtKGps=KiQP=iPa{vT{=H{dh|l~&Fo}myv7|$|oVrN9i1khwP@5NI z@PtAZ81;$$Dkb3D9y9T}CoggcOU5XDvdUHu9@)qVNwzV?bwifGKB+NU3K?EAeq!PG zo`p@L?x8K&R!JUi5l~NcYwHs2L}wH+KTX|qdu%ykL3Jg1_tDoJ9*2L;29a4El9c{h z5fPIP1AC%~`D*I6*-N(;p_l58bLZ!nHmT11poBJQc)G)0NTj`X3Lu-3(V$Q10|?}8 zP*eA5UpvP9=UAlX(_!}5E+sb49=q}!3(VzB0_a4s)nMVk5qdusVISl=*so0qXDP5o?p z>dX?>lmEJm&C}EiW0B|pBxP#qjrLf53DYu|>`f)ilVN1fTxk>((nLdFqQ`DOem|dl8d*I)C>?_Pnt6X_vz=2e!{z4l^k1ZB@%zj!3_` zT(PMc1ImQK4;IU)a#Rf?T4p($hUYZ3Xk!-!^#cy z!>)G916HzA0{`umkl4UK?Im;oYk!@sj!QQm74 z%b|3KvFuIuH0}CIWY|iyK~l`V<{ie%n_)Mm8;wp|SpUxK@K7G|9y6nK*IjJ7=M*Sd zuxSzM6%c}lE#eKMI3XzC#X`{T4|cH`z}xwK_6K#`*%lE*WWM!7=E;3OU_o>zANK(p z4X^qGmI&{=57;<(efF@o@W$%XJ#1X}UAG|{?_mEVgB}Lt=AHcO8rFwLeTb#veLmqs z1p)t%y^Gk$8m5Ewbx93MevtN;l17y5O6dpuzaO!AE?MGozu2B>{hl=fwu`#yG^e#BRO49ogQ#&cCXC;j12BFkIrD@AY@%z_E@eOk ziOo^x`L+XK`NT-xaR6)tf6hTjN|dQO$ToQ-n!q3qX@}a@D?Uo3hw$h_*b!{yIfpRE zu})MTVtzvW?mEPhU5EJNj4sqVQy`D6-|z{W$eu{z8K1B<+9+qe56icfL7W31U^Ldd zB)E8m(XfJUsAExVxQR#CF@LX@kL$Mzu!MINKpT+xsvj?^Lv0{$V;!6E#L5EVMjOk+ zM`#?=?i1GMh({sS_-rC!eF}RO_bF8W^SLAbi4+o{q#xlCpQ6QRz=ls*0A4HWg0Qzw zikJ`jI;9!XtHrr7jPGYYWy`vk=slp_U!6-d7Wmd2;*-bq^ol)l}o&8B0J-Emo^@PUMAggh}RY#bc9Xlm0Hks3^^i9Jde>i zvYf9!!Uj=iUVnsn2EHtA{Xv25c~t>(!Xljqr%|Lpvt6>0o+o+R5loboe9Y%)BM2+~ zob~S(SS%e7_Mbh44r24u(~H-9&iv7~?>}dQ*vRq?M_GcO4Ts+tHvg~{FEvRQ8$qHo z#luU%3fV_l3QB!=lg9(VYbFW4yB!cAYmjJ}S`$DrwAI7*M958-b*#)`$<@%R$ECB!SfWEXvt zoUw^3NU6+?3>ky1To`dHbZS^ptUNBVM8soKdB-Vm8D>Vnzo7iVzxXefihN^8 zBS^3h9E6ptcI?DF(yDhXC3?~+OV~H9xTDi)B47F~TS!}s=5JXK+I_!U_(qak{@IaX zIPwrXmC8fh`8(zvvno?5(jjD@o;a-!SZtk{vQUo9Ax;S?Y>{_LWsZ;NU8j!;()Q5VAPwDOXNig)uGmU#l9ev+hUnKJ}Kn{ zUV4`G9dx>Yh$G03IXFiRc4(MXJ}};)0ruM(msThAlJr!+u)b{T^m@S-hc3F0s=vbATfZ5!N)miEQE41Dv3DHri3Ip z+l0^`NyyCuhG4Kb@IWKzoD7Zjuw7HtlNKMo?>u{IR94Cd*1{ZeDZ?M=w4?itAt88H zz9`q(cF;X9Gqc)nw01uANmvW3qR01NfIVDrI6fb{S!fGbye+g>B-eR zzTv+%i(JwLcH3kBDdHYHp1AfdB@v{PIPX4O$WgoZt+z%OF*5v z$|3+oe^#LS|IC8L*>L*LEDu`7!Ji?X&E?$kGs{MF+%>53yQBDOKxv$8D$j@fr)zA2 z*cZoMXBP!q_}pNPf_S^036k#IV8_t@BHqvnExNkMc%zjSQTB6&G5aPPL&Z9_`!{x* zU5e)0Z^7gTNq_Ga+vvJGDs2N6Q+vz!*56r_uels75SZ`*@zZ;ve*&=r2|1_0fQVba zV_SOF&p72aOJsQ6zUdA&j39|E?i~WAX*uo?o1xa4Av>XG#WoZJ+{3J_hlDVUW$2dq&B5;IPIY=`F zaaSFr{leeoC>8h(J&AXmxcH!mMlT)HCO&MsvW>-(AL%4TY1W3@S*y@V%21l%B*km0 zit(|BW;uhqX{2Iy_#eh9jg*Y93KbjAI7_{#Qh#e_wBa2-)I}NvL24{^k)W4DqMq)8 zHUhG(i&UU!p!r>;XXr_8>M8|^Et-p)w293>z<0VyW5hj{RyS!ceB<_R5|e}>X{U#D zOk67{=pl)_4aPK2X&)Z-6>+(jlnU8roY+f(=>?mfmEKal$Vlj|Wbn1UC4Z5=zqhnY z_;Y-uH9}an`k)msgDmJHO{4KU+t4W<;tWa$@nW?KOExsSI57yTG6etFFH8v@v1uxS zVQT;pCgMOV_mvt2foJkGNMTC0UVV_^87xM zCr|U2KBVV(hrcu^v?1}Te5Jtap}b!!*0xpWklOLrRGu+FDiHm5YygJh@D}bCAWc)g zNri8rWZ7;rftHd0DOTOYkcJ}FfigLhDrIN#+Ybu z8PfMfOAQPcjFt|Ue1!~oBSxAG4gBXAsW;ulokmE9yY6gDUP3bQX%$5by~DpBA#vQt z;`y=CI&A&u6VeQ5Y)1VPQjqKsxk)*F@xaP^K`DT%dd4lI1exIN3kl$T81RA;rEEXj z>M5219d7t3TW7JKz_)Mg;q$yEQHuAfDo(E^3*zxHJh2mfATl9TG)X}F9v__~^^Jm# z7(XJxdJEs@xh+^b>?LeM&2}-}9ObN&5bwa6e@~#-DVGjM;mTVQ_!OG~m(h>|ATVk) zCMDXIHCkHl8*>Dh+=9egHgQTwFsn3hvX~~g2)1G{&^sv`M__=) z8Cr8vT?k&4POlM?6H3j*6v(Dqu15FqQY83E=E$xii(+Dj;Nor* z!1JIva)J~Ad1%a=Ak{%cTX;YQSQa+w4H?oE$|i2)%cn@`@QsaAq>JM77`$exbbw86 z;|r!?YEEu5ZkQ%rltsqUS<-3Yr|6{=@62d%fUjr&IHi%HIY0OuRC8v7agScwF9eS< zXO478lr;L~NjMkBHo`=m z<>_708A&@K3=l$pashiO_a-L^I;0jV32TfJ zzR1$ZwFjV5?BvT1NKcCB@dHvEqD}{;XW_kYP#P;zj~V(lX1{{WX5d!<){xHb~c)Um<_(GsL0u)qf^gM11=ZFctjMN2EC6 zyMJ!;Cw>kohWMt>ZTZJPmtsZS@uo`O!`ojcK=WLD?q`^DoJ$r)#3^?nIr zpbnqoX^jxw;DX{tDTXp6?E6+K^r{B0Yey#+;PR!A!a9;IuHt@ui^rXoPO-!1jjrEG z{h8$EH^CV5y#zJ=bh&ZmS?Pu&ENI5UAEftWdWZX%rCOR~Y&1*L7!SED-D8I@@W3k& zXl6d?iu8sM3|Fs6yXeoxH-3~lIkLmIj9afu3CfX?xrFm)OK_UC#iqD4^yX>5NfSLp8!p8AN$Xz5$G8;BGWuuVZ&*Sh zsn{(n*g_)s{Vsj|;Ho*WkGT!ToWc*@mWH$6j`CZ#p%?%v=nrU34a8XVhqRHp{B{&; zps*O@+PTr|t~7&ox?n%d$>z)NNmXpM3wORRji8(PnETSnDK7rR()kLpxMY%Ms~54j zEh3hltBJ)ok65~A6N^_SvGjF;L%2@^(v#tmh@}_OdilVGAWl#&kXSrX&Z`k_`|Gdw zk}Q1+)GzmcX_Hi6^5tFIrC!1J{7Lh@q!oiY5%}Fn^W9%W9BYT|ZzodRl%S=HaZ3EzbNSCMS!c_eIf8r))(dB&BEo zii!u^e=Zs(igw~FBwNw1B^1@v*@`k*DLNQM#cTXO7mX4{HGG0>EBdC4qD~pMqNi;| z1;PKTXq+hO$oo0iiY|0OQHM-h(QOV7+Zy#hY8@kr%KTS*(GiX)Dy_E_Ep(LEmA#p& zhe;cgTD+pOY!<3I3~Kmt*~7H$D^-v8ESoA-kM}H_Q&o@mEL*my9`9M+_ESCHv%FoQ zdc0@ZR;hZn8OYyvl1GeR)1ap0HQQx{M=w(?)l*c@#w=^oRL{mNYY(ZOjak<7!5W#D zy`+AiYk65*4*yfrUf!#2T4kfUX{)BFn^qN}Zd#RI-L$H6>ZYy1yF}$qgLsizmRojG z-Kz2{3K5SU!&zS3uWnUYrn*%tqSdWhv0e2T&a%=)^%&0b5)XBj%cd3HQCC)Kdm#Sk zp{J#2sk*Y~rl>1hwn$ysbM@-ViZ_cls5(BhvphI_UY5F&+?`5`9=&n2%#T-Bl9wXh zI1UtVrU&^=k5(6*QKJ-n^kmvHGs*U3I?6?kjGMDm4V=AP0e&MB3s zxHlt1T}fJ?x{?Y0>PjZ_ey;NDC&p>j2vc4E-29XxHNx>3YJ}tYVOM#C=I%zJ;NWd! zW2-#4Q**~1dlZi&`|%lFWpAWi6W0U8ch9=YfmwGC2$RtB;_2gXh*~`QfsIp~J~!Vz zZh!uG@Ikursk7$0=K%ZY?P7CBx&3{k0*8_hKY_;UewA@Z?j{GbW-EWvP44;dBjDmK zW{*zIcTKk1#cRx-;msZUY^2$qR$|+jq52wI^WDbB-e)%7<=?u=9zM-h`2jpO&1)Yc zjni&&_l&#tkBZ~o(4()yiT2sP3is$UZlZ1KcbTGXN_S!;e8OH+w+)|nQ{H9v@@{S) z0n7A*%S+b*vWNU0zII~ukb5`|42Oi?$xS_E56moG54l&*z?Dck4>2A>Jh3<5sc1NsAU>;y z+|x1W1~TzNSHK7J*8$%noCJFbEts2grM=wtuB!bi!E;EmBTjA_AQCY&mWNh#>_0(SdRX z#Q|-vL2|A0J=;rBVZuKTZW*?_%P)+k+6=UpNuWTU^Yog#Nq;_2h%z^+2qjwDNIfpt6> zC7!PuFTaWb?U9OazyZmaRQYXz{IA zgD=aG|ATf<%9RIDm$pbya=^wM#)>=)s&iY`Lx!uHFOL#Mtn)GIz>~E=E))aOxB!y^ z@m&k$3ZT+0!lZ+t;H|~-iaw(IaYrR+Z~P(_PW@*E%u0I>S1o0s3ohhO8feSGb%gtOJdBrtc!YXIzdOuOw2N$hS_Cd+={JqBlU~ z-Hmc6T5SycyPV|U+}5U8UxbWVxOy0@-iNuc3v% zy$wlBH}WU`i5U{WyKR?02bA&bc6pmJ1SLBlAj+=aB$n&@h~-8A{2Hw5kN;g(MJ>Nx zAeTuNx!fm;$kYpU>3Rd};1EPC_-PLD_7n$@bXt*6S6qWoPB z$$Aic=wA*w@i6=#a5+pEdmsP1tc!R&0kO-vhkf=i?{e_zhhcjlgItdIAAmyy)sO#O z9&Dpnoq9Q3{2w`w|6L9~z?1jMaeZpeAp>>+r6+{n)gE>umKy%geRBUnd;RSo;qYOV zcnBT=5K&xoVw3>?WuM%;%fqBGBB|%c^7PP$NuH__-uAGB(&GQ>5m@|0k+(jUN8+>0 zmp+y!<lzupb_-%&tKGii_#)BohKfBwb|`AxsDCl%uoFWa}z!pa`iV^ zKd!|w;W1U8c`K^ErN#4c6`#50rb5NHwD=Vae5jdVYrxzU)gSW8a7#Xz(lT1tNo;^# zIjL;5lvjR4+(8l-{4Fixaa{p-8-ADL zoLlVQ6u^z;i@(dB0WI0U6@jJelz>`&2e>@+zBb$Pxsi zbqB9o3Aw3s>Se!^_-v23`Do^@jt>3tX=dAhrE)pwcpy&N6ePHCCD7;z*_cuR&??+z zDweJ*|8vXbz9yxA@l;Rw|1s3Wh=Y#H+C738<+7nZC4_|Iot<8k$3d<*guU!%8y}Qs z_@+&^tu>SO*k9zzy~LS`?I`53-##4uk^fWJ*T7X-WdA?+ff7>LQsLncGz(ms&;F%vdvXjeLvyh=_XpW!@n=6&YO%$b=pXH=6vZdWQ;jH(u?uwt|&MlYf2M?z4B8p@=K z3u?}ZK>R?8rqC5u!8@^SfgNf1QW{XGeGka7g0eKuTO8@c5<)0F8FK=3R6|9LUSoR2 zpgTk%odEEH=t+;bv0iHEL6Pdl64gFf$GEXUgQ&ES+B=!b3m~W07AF7aBu&Rvr3UDr zhz@nbWu>HuN0kAiUdu2#lz-dN+CH7xIMrNfvvy`RZfc(hWWHv9)S& zp=j*Ivb;;nu}whgpB`0wCBKq38le5hymeUlp=o%#C6d9XvF|#G!AJs*;f*@NHvJ?~5z?5cDVrGGz z>YDY2`nQ?&Qy;AqSIsOjkOn`ClIL1poEA@UTyRgwPxy_3;fBZf`x!2N)QZCUS(0Ik z`09SpDjKBWezu;*q{YFkG&+H_dw8LzlKw8Q^vR<>P%1MfKoq_VW*bFBLV_V8=y5v6wDp)p9yBd;6&yFx7( zruL64>_4ihQOpTpiwW{jmP5ndtWdVrSX$A(7BP-8JuZ8ERw#{ia;Sl?@CR6l;ez<) z0d_CsX+*;V%&PV-5aYvGQqU8ggY>h70IC+M(}*sZvt*50Q$@ATia8;C8}r`ub43*AH!hC1Z6zHl9d2ES!Z~E-b@M zN9YltcD^u&#Gi2cq=BXx%E}hU**yq*K{#trN2nq%g82lFD8?8UgsHt zk|ldD84#?Del;9Ts>?-8s}PluEM1*q6_);Npl=_Gg(?tRT1shHOo0ON6MMfwqM$#^ zQm0ke&h%$SLmXz(RVd&MhsVuSz>kxqxXukd+9}QChO9t?69ipvMB;Ubysp)Y>WZ+Z z2ik&O0E{!!AjW< z4&PLDkV-*8A>J)w2C#9F9hEVj;>sIZy$v(8!_TxdJiA0;EbSr{sD`QmEJ)2;DzpJ? z2oCfkr@`F~O@Sv1@a@+AZB|wvBAx+0hd;y?dZOHzt~$~_@erHy2b?W+Aj5*VkHzLX zh(#IH3)>(K!~8_@U>4brx>}VF= zV?smQUTovo2P|&;68goe^qhVcEo1yKn)xH*U!z&C5Q@M!GHFFvj8QVGJ9g&bWs){} zt_=){VNa@JXw(Bg@`xY^3_-ku@=F0Du@6!;S#UVp)HHzr?b$0RC~T zH;o`e<5;}=ga(MFAx96kiluQZ*dGadB&|lWkL9`IMG+{xY75j8`YMjyhtL<|SYLo{ z!x&vZ6T|d68OGj%?TO(Gk41^x;q0NFw<0o)FjC(4Itn|S-3ve8!%x3I@guWfd@L*m zp-PF;^^k){uwfX>UKzpu*ZIQURDJLe&&RV2ntTq%v%~;75XXexll)o)T^zu)uTN<- z?2crksT~%KWDB}3PLaHecWM%KiVL>x3G8{fS6c8W+erivItm01DjYS6alDl$o_vhG zNccmKu>guidyEy3eL^B8X4qR2S-j7V8aXM^wK83%*`6>~BtMSv8tiH1Rtn}q9d!=7eW4C+$@#lUBnW!~6rp^AxzO;bIoB6SK~B9%JOO`a)GIYgze ze@l09C^`eLhm07d%Nmf`I@F_!w5^M9eH5K}NkYe>$Jy^X_|1V|Rr=k4I8E(qBWG{# z!COLyH_`SC>*-(rF?>5bgSb6zIY*3VJ^R<&oSl^#nZQ0&wK)l6*j=(MUL4P!npb}$ z)#_B1qp1^}Y{ye+C~7a~2dQyRwv(v?I?8-nubU+aXewIfkx*TGsM9zNyk+|gnXy0h zsf89z(Ph6P{(m(PZyE%O3G_WZSR9lVrV~sukCsWzqLNRofm9>O%uh zuM$shs0o!L+n5P#nhLL#6IihN)Tg3u0xOtTPimXa(S%w*3tuPX*ED=V4;gS%@U>5V zJ%_J7@@ovf%H`MN_$uwlid=g*Wr6F93fT)wP$7G+Z8j#!-g(@y2uL!DAD(0Wl&O~I zz)=DEO=L#D`o(%Tt$$6AT%WCx<>ZNMRAl`nFv+RV9^faZ1pBx4*!m%!>-X+v>ZAT2E@#X)Lbno!>|T>l$Es*49#Zo1oN}m3iZ=q;hMvuX=yP$hmAFucNeBY(w_c^BtH$N(n9-G#P*84SlRy9?LMWclg}MHI{g7mR#;ITLHB z-B{7gWa|hnp2bEHEPs(bCVJx^S#n+k`QDgm9_9C_9g1( zkvR-o?4OG_US^*WI=&D|0j_eubA@cE;S`=dq}6pIETYr0R%uREO;! z^Vm}cpMQ>3jBy_*7OWV|>27^7&Hgh-c+O`h>7GRWe74c!KnsXpt`tDtYZrh+v7Qr$ z79a<&REnDm*bpMNA+NG>wXoLK@G8c9LL|I~jt`jk8f#V;oDt~@*=+UI6me!Di_;U` zibS_kqF6*wq61$?)UPfOnXiLviWS?A*BK5tQI%P5u&gdCQu2 z4=8^5_nGJ8y@M6`hO_UZXtyP57?-gW z=q!3^8T$*l?O2A%7qpbPoGtD8NeNc_osrG4v~K!LoL|l&;J4=r_AJ1R6`&~8Smg>f z+yCNv%C%cDs6I2ln|Zzo%8qHTqC!0R7NZB-zI}^5(slh>$L(8LEf;OQS2AHhRJ-41 zPXKgY#UARmer?hkXI~BCiB(`y8pPYHz=!QkwAHL)lMRLj+aqh(3_$UTU~d3Cyq10A zjn3$a>#-zqFH4P*1igbjtOhal9Z*k$_}4q^_jX?-obT{uJF*T;36|gAK$ftc zMH`3!7QM@^l0)GJ5CjgWS~j3J_TF<9cg#>Jd!VH*H8`&gBDB$D|2#^^SJ=KPVPCka zCDpcN|6uzJMq;D>yVZ9y?n(w2N204oCg56s!c2$AZnDVV!WMx2v9)Yr>sXi1L`aoNWDp-S)D#d;*uTN|Ik+7uQ0zYrfE{sECm;^E zpQ(XABk+jhn{qlQ!3o)$twGP#I}D`QNPZM04KvdOm@tp@@EKD z?E7ZPPy0bvvGgE&!F}u#Pb4OfepDHjXuE!py=?IMYbiv2%0&C;K>wC~fX)o|pp z{SXUqJFw7U!?TtH0uOA!5y`bbQB80Biut(h55ILF;v2p{=(h6^`+m>6oQK#CtfVj` z&Gi-YP2SgX$8m^#Ki6aZLu|fx9EaHV2a}(Kmu?;Iv>%6@SI>Kky2EUicU?1R6v~ra zn!&YT?BBoHmiIMFQq}52QTYukQx7+YtZJ}m`#%*+tJx|Xo!CtOWt9e>{SG}W7-+(D zVIC}2T8?6x1~h%kqWmrum}BGubO>F~0bP;kj=gTKuzt%1c+_pg08ZNq_DdVYwr`Qd zd1yiS7JSzw+!_6r1sYWC@D`8nm_daH&*LD&Ixi7=91PX|8j%F(vt)oVK50eD^5B?p zOWrw5%#}7u6dz|*;Z>@B`mi_=OaA^64jE+S#J68r)GH?}#<3e4*`A1`uCRV>*F@1tR9RIgvHm2>nup!|0$dfK zXSnQDUBj{r!C2#!VBIm%y&7-VwQZLRAf+;LpB69+f6 zO5SsA!$7&4mF`996Py2=o5XmS7|s*Q;)db>R=7cBN|MW-8x3OI4`9!*^j`Y|Gr6N> z*2r4!F82KZo>b3hqDZR&$5GW)Y_DM>@l;kz4GZ_E^2a_?6pDy#U=jHv2F~hgG44n9 zreUI}{gFkw!vifs$T{c~Tk2Uw7r`JBLob6S%@ox?u>f)O6nKj2L|f8nmV%R^wYIXe zEYjdsH9+?&&YZ&#LB}u2zs1Qdzr1(~u8O@0(@E1UCy`{&lHh{}omKYbs2dV*h=(V!sKF;J0mxX7Et#xYweQ zl+le8z*@!L2EVPq|K1EgR%)hyUuQv1%~XG#8RLHSMr={@Es#60x7>jFhV0JG)G|PC zreF2uGAQ=zy3CV;rG))DF3R`C8`k!g*+ly7t@rD2hpnUa)L$ovBR9YYv{X8`R7?5o zE!9$Tx0d=f*}0`!7D+$1wN%U6yR}qH*_|!bvWr>@uOa@%R;t%S#qd@Z>V4e@nlvVu z;vx&%YOqIRzit#ot;}cMb+`6@?{KAE9s9Ko0ZRvVuf*2;!S61KZTJIrhs0L=0lQ6N z58uM#oV!<;=>9wFrrsDzG!-b~erLYwjXc}<-x*#Z_^nvv+{AXnZ~Mgdn;02d%{I?A z_K?BF{`-X0@%%#<`%RD4E&QK=@L}M)UF>ZjIh7X@iPfpROoa^fN*6v_Ra%AS!h=b~ z)6G@NpOv;&>?aWJRhHD7mC+}8ihV!7yf0Mm~ znu38zkv7dGO9V0==w`4w2qlK`C^tjFEwbq?{>J#dZiYe!YA@r#frh0W%}l~>w*>Sx z!}>Lx`}!L25)pWGI3>Jvi*plUoR11pEf_y;=+CI%pP-m-TpC$WyUSj>0RP`z9lYf0Vk>obq`~>IQkdgB&%P;k&Y#T|`kQ&c}5= zu4tXtDw?}H;3`G)^j0)ne50S{cqq5nG#@5OqLSq^D9!B=|xRhCn=DI@KH20&5 z)+rRujST>&QoGQeCw4mcmMlM`0>QQ8h5_j&>2y@3VZ*&AdQ@7f#g5s*Q16D6M9RpotbrJg)oRl7_S$G!Ls zHLX@0?Z%^nIq8VixSV_>|B8JFiJ2z<7g2SA6C3Ew)93Lm5?7()!0WdA{Ym0~zJ-s6 zOVadbmXlUrtN^r50nYMmP!lo>tftl}L~hbUg+2}qy&zkmv9eiG`RL-5)M!&&YCJf9 z(!WE>s^3nYw>)_ ze7K)q=U#;C{1<9|=mU`GAr*iS22fCkm?%4-M_UM$x)sH0pi`W~`$5u7|;B z<%iL#$2CRkiTv~gC*$WPDt-7&CpIOz2M-MM-lJ&VCyPTmF90lsnMZaE2>LG+!`n6a zsrjrF3w!Xfo;_+DZU!WLZ5DMLh5`eOY=^a9jyCs=MIKE-qFFFa_ZE< zyi@M%U^2^p(!rAbI9I*vMT#GvnB;w(s)AmM81-sK3Uo@3rRMC8i{4mCVW~)RTcF)& z2Ud01!|{d#9>~B^#V+a6O^*c%jQB*q?tT9dI#T-SE9UqUS5hFZ`SSwz?xFh13(L`2 z0X)U8dq4dsv?EQ~$-DOxS^&@V>mC{5Le&FT5MW1+B1QVWJRvxsQPBd*742RVAjm7| zu%a13YQ{Qzrz%=6xbJKfK8)r8D;&Ng@%c~qGvf2N zO5*b`yesh$r=tdxiIN~NDzisXl(QYYjlX1D+IbuQg4>DBKTQ%_z64J;4l{$XaYHfD=Ha`pLD(fWK#_6`a<2+Ra&)66yESTHhm ze=9AiOm2M~obTJG`uca)`V>lAsf^UkS|eP>i3n z0eV}8HtW&cPC6El(jVL2vhS{KzdW3uRztSh@*;RKWN-^aOC&eZIZZ%+J^{}YiP`=6 zdNsr*e4}_Y3HOeR;zl*(KepLXd=_&LiPB~EaDZ~{FMNO+9%c(4#0MHYLZTs%(n$4# zW4FA)Jl&w;YT}6@e1H!c%C`rJaQNImN(sQ}q&9G;F#eU#@eUb}{bLLyAxUz6(Zbh? zZGYuk&C9D3W_Mc!-0I}zbg&BXG8&Gw!Ffq<`xMb^w<6LuXDBxs=wxaA!yMXsmXljsnTPWULt_tS$LPD}?TsHJU!SD@Osx$vG|OWIExr!A%x_&}*J2Keis9UB zj2(@g5l=Hc%N3Vr#PAG_q!^Tkm}97JW7^h?;Ksn%(a=uYXh=4Z5E=HfshVRCQ~Nw` z5kp5{T#ikL7BqrkqHqKTTG%T`@Cr3{shAtjn@zC;A$|v?JYmz6@O0edCO$iMDb$vn zuqc#JY?N3vk|&b-`*R}^E;&(@B=AV}$s%zyfm;Z+Ch!_dEU7x#9!%Mdk#W3BabO0B z%7`@53%5sQY-`ty;yLPQH(TB)OqXixhqj7DKG#K!-EJG2%r{7R@tP<3MA|ADI-29k zC#2Cv^KweJa13a4MXJ~^M&`pdVJwH5v$uzfl~3_K1e3<`Sx}XgynIlh@Y2Hj7CO(CS5&0FQ@KP7` zDGyuV1b#|(sn+NCTG|d?Gm&pppJ}xXd7f`p$;X*V2%;_?Bs|l2sOR&Z5RufLuf#oP zZM>H)K8-`+&(mu~`V=1Tws;U6N#Fa z+{I2an4j{Hr|}-R(a{)|tI)+1l0w&F%M)_sF-_a+kv7jvj?F4a_nW42KZ6?ksTi7t zYC%qW;`W-NP5lw(6GfZR>KItHX|0O(BAq&7 z$hG!@iBq)Mvth?@Y#j`Pxq1%mN|1dz%=?N~XoMXDzI7ptP0{8SJKQk`TaPQ+JmTEQ z|93F+eglG%Bg73w%l1^XqB7l{-34~c1@mc+fO~cy7;JsKb`W-CDEnV9nxZXC)!lQz zB;+7NuO~R{m~C>A$wk;rr=5vE6-|wI|Bp~%tuM{F~hz~IY5B?=U`q@v<-o+UlGY}OpUz0_JuMX`52gra1xyJ{IZUNY5&sgzJF|FC zw;9*)=2&oElsNMNHyJ@_c!7<^jj5Td4`D1Tz1!?Mbu(R90UsT`jr-12awXavgK-jM)_CRyQub=el+`!aAJr%^Rpa0T1hc{iNqP7-FscMDWWPudRbc%F8?`z=}6`Zw8Yd z=~Ttw6()CVDO1*XvEpUy9xS2j51MtH*#0ulvslOH8D!>CFkvMaACo>O;0Xcmd=*;q z{T!HykV3;8W1S?@3;8kCIz<$%LWWXb;qKfzy})>ExkyFis&%GV^a?+&T4#&YxhM(j zE9UayZi@wom@)y(JaLDugI0*@`9 zrO+NyD^@(|zG#Xu)09RXzw$ zGE;he@0mjMRd!1%$VlG0dIVobp z8(4$nOx2_ETg-#}a%Re?aKDfu%X!%m*$*OVF{mJCrpR2(gS~Uk&oUoh4xbxLjG8Iu zimhZZcQ-i5DCepqBXM#GcOQ~-)9l{fxE5kgoSHXxFr`*N)OI*rb_Cdcg5@xjJJc4m zlxFJOL=pWaPgQdVi;_1%M1U1=lzsw%D;(0$4%zzitO>)bc07xTU)Dt1}E(FZsN>Z zJ{(Di;CIkrrw8f8weTGt7%&}s8lY1}^)<#o22YzFu9MgFZ$!mA$o=$CapE1Eg-yRt zMs-$rufw2A{bU^&yXj{|!#X|(zHFI)BffLGCN`|+1J&t2>uJc*cY2%NQS!S8)4RM{ z&F?0f-^I|7?<>MLpb7K+^r2_Z2JRV{Z~n6;$sa6gH=xtz$B0pXN9WHUA=dmIbppFj z2}X?kC-pQ_OEBW+Kj%m@Ml349YA!#E(g^9imWq)-tH4J@F5~{tM&k1x+A9B5G5kFc zSN>*^^&UT}=6@-oH=>;R-#8T`{|85uXT;u(U>fr^F=rFXntxI3*o4lIf5|!h>$>L| zOr&l``ZGL5$z}|bGXiv~m~pSD-^@+kGkO&$G+ejFr}|R2oslSl{=ru}t(+?U!2^6Z z4OFyE<6Ogt|J-C&w2k14-ZzVefAE2$x4hfVMd(mf6m1K3rMG+p-3X4K#C;6h?hc$m z;ywfJi*{d%Dslf71*JTA-j>5~`)`Mvt91Le!%iP~*b;tfZo`4g0`4c6#*VanB(4cK zbV$dqhs52Kw)TAb60QvFT3HWeUOTd6vE2e( z|2xB$p_0oWN~*ieQ~Jrk!+?Aotfl@VRUcXz*1pa^>F;UaCm6ap@KF*+r;Liyj(d=5 zs|@Q&=bwzv3jFjAEa{F$rf1+E9zb!RAC|~Dz!i7kq9tx2aI3}eGH!}118J0r4)+-8 z{tj@PJ8-cQ2l6N@@4&@L+z#MA6J>}ewCr=4YJ1x8(*3|~xRDa~Ut4n-|58=A=7|+} zNm+g0C{BLBEk@9&gLU1w^Uqn=jZMz1>qdH9(TR24SbaCv^?jfJi*?<&>rU2ng>~IncL(cQw~dEImacO?W3xb#E~5QZU;DtEw3~JoqyQjYfz?V&#qbaL0PoU| z5DJf7{(izNS=`bu#NrS6_^i?|oMSU9xP{@Gp{Q1xXG*_zb_>RZKXt6cpLWJ0gd1Fj zNSDiha3PfeMsnGrh@|b<&qhAN+C@2jKY_45kR5K2KDzuNEZ&8#x^~Jcrs$&kDfx**a83nriXd&zt*wb|T_o=W) z!ai2FpNg~veZ(y;>V$Gz!VYYnsM}ZB@^|u^E~YL0pn}zi1jiu3@nE(C8h>E=q+4Q= zhPGv-9s>8mT`RaLjAEqiMoh!Z`gUfn%c?D-N*1kL|ng5!X!U*Ny_8CBhsFK+I~uJo2MVq6s_ zqfK~7wTh>Zy{-yu{iX%B-~)VxtKWyv-X`zg?rEr{OU+WuRNFpT9Qlf08@PL}VoY_z z9T06d^y%pSno3Bmgi>P;Q`~UfDg_Hjxs`?j%BnyCTMzRQhBKU7+CcI7K_P1_m1rr>ceZEUNibvsiqVFP(RKmZJT-%MhaA4B*@-80>(w80FZk z6v;gf?HNGqm1uJST>%9kCRObNKn_>|h|L=9C?IxiwR%9vx}0Z#?tt9@A?tEJ0uVb* z=TiXv0BMSXb}a4uVtin;<@|a;Y{H!13Wx;HR{$cx^M?VE;Q7;lNa*|}KqPej1|Slu z!`wj$)zJilgzEYLdI3HJ*bQ(Ppf}(c!0v#wdE)~(lhW^jkJo`P0U<@Gb0>uJS#^M0m08zjT4F6HU3!Z=|;D!4DQNRli zQTb8A3y%YV5?-L3p-L~j0*I1cplvCX^g;gfqLN1&4wvb zw4Y%ADH8_vT7)HhEo!575zJbc5}0zBT`-mN90AGGL6~ZoGca{9O^RkmWHMs7|No%f z5B`lXgZ}@1JK}oEDPnsJ0w=>1!63ICo}B#rUpV^;gj)+!BD7lGhorw8-9gq8s>x`O z?NA>Mh<2z?0z^C1r_PtvU;h#ys=s~>@TmU!PXXNkj{>6l>zm+?s=nv~JF5R;Z$O-F zTpR|7ZN`h~fS~Y;O8~o~YA=@J!waxd=0Ll6VF3_|*5C>Vf@ruG5D7Ls42T39#sMOs zhCDzd)bJW05^8uCFcNSFNF50_90Ejw4K)i4-XOq+%c|mv_%0EFA^uB|uNq|6x}>v~ z+NDXwvgDWM78|JKm)?bUl>E{GKoH=i)4+oOFWrDYWT>$l?8s2#1AwT3#(3b7vBpf; zk+H^wfXG;53Gm2J<7a@#P~&Mp)Ij6!#Yn%aqFpw+${M&F3y8jWd8(en%PSplM<-bm zm%r{Lo8SHQ10rKhX@JOB(;Pr#tZ6AAGS(zI zp=%*$O&-lJr(J!;NB8hIhkZ{E-Tps7G{sd%AO86s-Tmj_-qQW&SU|Y{JjsDC za=`VGy1Qfl{O4mI>-L8J5;nU4B3yH9Uwoh{n;-jF5><1i9zpXW2P|AIwI1Kcm%pl0AFIqH3+fUKQqQAWGY~jM$aErWW^N#eM8v(-&EXxaeQmS_d1SJ z?X6c?|T_332rv$aN F{XcC5Hyi)} delta 48633 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 diff --git a/share/fs-uae/aros-amiga-m68k-rom.bin b/share/fs-uae/aros-amiga-m68k-rom.bin index b3c581dd49cc4fbf7bc73bc0195dc22446d0c8b9..e0f946fc0833aba1ca59a126e4af1ebabbfa51f5 100755 GIT binary patch delta 92772 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�u-zrHj#Jx+H3DQ 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 m-v%n;3~7e6bC{CB6P_RMkFJb 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 diff --git a/src/fs-uae/main.c b/src/fs-uae/main.c index b1a50f4fc..4e40822b0 100644 --- a/src/fs-uae/main.c +++ b/src/fs-uae/main.c @@ -776,7 +776,7 @@ void ManyMouse_Quit(void); const char *ManyMouse_DeviceName(unsigned int index); static void list_joysticks() { - printf("# FS-UAE VERSION %s\n", PACKAGE_VERSION); + printf("# FS-UAE %s\n", PACKAGE_VERSION); printf("# listing keyboards\n"); printf("K: Keyboard\n"); printf("# listing mice\n"); @@ -898,7 +898,7 @@ static const char *overlay_names[] = { NULL, }; -#define COPYRIGHT_NOTICE "\nFS-UAE VERSION %s\n" \ +#define COPYRIGHT_NOTICE "FS-UAE %s\n" \ "Copyright 1995-2002 Bernd Schmidt, 1999-2015 Toni Wilen,\n" \ "2003-2007 Richard Drummond, 2006-2011 Mustafa 'GnoStiC' Tufan,\n" \ "2011-2015 Frode Solheim, and contributors.\n" \ diff --git a/src/fs-uae/options.h b/src/fs-uae/options.h index 16e4850fd..5620f4633 100644 --- a/src/fs-uae/options.h +++ b/src/fs-uae/options.h @@ -23,6 +23,7 @@ #define OPTION_GRAPHICS_CARD_MEMORY "graphics_card_memory" #define OPTION_JOYSTICK_PORT_0_AUTOSWITCH "joystick_port_0_autoswitch" #define OPTION_LINE_DOUBLING "line_doubling" +#define OPTION_LOG_AUTOSCALE "log_autoscale" #define OPTION_LOW_RESOLUTION "low_resolution" #define OPTION_MOTHERBOARD_RAM "motherboard_ram" #define OPTION_MMU "mmu" @@ -31,6 +32,7 @@ #define OPTION_SLOW_MEMORY "slow_memory" #define OPTION_SOUND_CARD "sound_card" #define OPTION_STEREO_SEPARATION "stereo_separation" +#define OPTION_THEME_ZOOM "theme_zoom" #define OPTION_UAENATIVE_LIBRARY "uaenative_library" #define OPTION_WORKBENCH_DISK "workbench_disk" #define OPTION_ZORRO_III_MEMORY "zorro_iii_memory" diff --git a/src/fs-uae/video.c b/src/fs-uae/video.c index 9ecb154fc..643f6fb31 100644 --- a/src/fs-uae/video.c +++ b/src/fs-uae/video.c @@ -12,11 +12,7 @@ #endif #include #include "fs-uae.h" - -//#define MAX_ZOOM_MODES 5 -static int g_zoom_mode = 0; -static int g_zoom_border = 0; -static double g_last_refresh_rate = 0; +#include "options.h" typedef struct zoom_mode { char *name; @@ -44,8 +40,6 @@ static zoom_mode g_zoom_modes[] = { { NULL, NULL, 0, 0, 0, 0 }, }; -int g_fs_uae_video_zoom = 1; - struct WindowOverride { int sx; int sy; @@ -55,7 +49,6 @@ struct WindowOverride { int dy; int dw; int dh; - int ssx; int ssy; int ssw; @@ -65,19 +58,23 @@ struct WindowOverride { static struct WindowOverride* g_window_override = NULL; static struct WindowOverride* g_last_window_override = NULL; - +int g_fs_uae_video_zoom = 1; +static int g_zoom_mode = 0; +static int g_zoom_border = 0; +static double g_last_refresh_rate = 0; +static bool g_fs_log_autoscale = false; +static int g_remember_last_screen = 0; +static int g_use_rtg_scanlines = 0; +static int g_last_seen_mode_rtg = 0; static int g_frame_seq_no = 0; #ifdef FS_EMU_DRIVERS static fs_emu_buffer *g_buffer = NULL; #else static fs_emu_video_buffer *g_buffer = NULL; #endif -static int g_remember_last_screen = 0; - -static int g_use_rtg_scanlines = 0; -static int g_last_seen_mode_rtg = 0; -static int read_window_override_int(const char* s, int* pos, int* out) { +static int read_window_override_int(const char* s, int* pos, int* out) +{ char temp[4]; int read = 0; while(s[*pos] == ' ') ++(*pos); @@ -99,11 +96,12 @@ static int read_window_override_int(const char* s, int* pos, int* out) { *out = atoi(temp); return 1; } - // read failed + /* read failed */ return 0; } -static int read_window_override(const char* s, int* pos) { +static int read_window_override(const char* s, int* pos) +{ while(s[*pos] == ' ') ++(*pos); int sx, sy, sw, sh; int dx, dy, dw, dh; @@ -129,8 +127,8 @@ static int read_window_override(const char* s, int* pos) { if (!read_window_override_int(s, pos, &dy)) return 0; if (!read_window_override_int(s, pos, &dw)) return 0; if (!read_window_override_int(s, pos, &dh)) return 0; - fs_emu_log("viewport transformation: %3d %3d %3d %3d => %3d %3d %3d %3d\n", - sx, sy, sw, sh, dx, dy, dw, dh); + fs_log("viewport transformation: %3d %3d %3d %3d => %3d %3d %3d %3d\n", + sx, sy, sw, sh, dx, dy, dw, dh); struct WindowOverride* wo = (struct WindowOverride*) malloc(sizeof(struct WindowOverride)); wo->sx = sx; @@ -150,15 +148,15 @@ static int read_window_override(const char* s, int* pos) { if (g_last_window_override == NULL) { g_window_override = wo; - } - else { + } else { g_last_window_override->next = wo; } g_last_window_override = wo; return 1; } -static void init_window_overrides() { +static void init_window_overrides() +{ const char *s = fs_config_get_const_string("viewport"); if (s == NULL) { return; @@ -167,22 +165,21 @@ static void init_window_overrides() { while (1) { int result = read_window_override(s, &pos); if (!result) { - fs_emu_log("error parsing wiewport transformation\n"); + fs_log("error parsing wiewport transformation\n"); + } + while(s[pos] == ' ') { + ++(pos); } - while(s[pos] == ' ') ++(pos); int c = s[(pos)++]; if (c == ';') { continue; - } - else if (c == ',') { + } else if (c == ',') { continue; - } - else if (c == '\0') { + } else if (c == '\0') { break; - } - else { + } else { fs_emu_warning("Unexpected byte (%d) while parsing " - "viewport option\n", c); + "viewport option\n", c); return; } } @@ -191,70 +188,97 @@ static void init_window_overrides() { static int ucx = 0, ucy = 0, ucw = 0, uch = 0; static int rd_width, rd_height; -static int modify_coordinates(int *cx, int *cy, int *cw, int *ch) { +static int modify_coordinates(int *cx, int *cy, int *cw, int *ch) +{ + int ocx = *cx, ocy = *cy, ocw = *cw, och = *ch; int changed = 0; - int ocx = *cx; - int ocy = *cy; - int ocw = *cw; - int och = *ch; - if (*cx == 114 && *cy == 96 && *cw == 560 && *ch == 384) { - fs_log("* amiga 600 kickstart screen?\n"); + if (false) { +#if 0 + } else if (*cx == 114 && *cy == 96 && *cw == 560 && *ch == 384) { + if (g_fs_log_autoscale) { + fs_log("* amiga 600 kickstart screen?\n"); + } *cx = 74; *cy = 92; *cw = 640; *ch = 400; changed = 1; - } - else if (*cx == 114 && *cy == 99 && *cw == 560 && *ch == 384) { - fs_log("* amiga 1200 kickstart screen?\n"); +#endif + } else if (*cx == 74 && *cy == 99 && *cw == 640 && *ch == 384) { + if (g_fs_log_autoscale) { + fs_log("* amiga 600 kickstart screen (pre)?\n"); + } *cx = 74; *cy = 92; *cw = 640; *ch = 400; changed = 1; - } + } else if (*cx == 6 && *cy == 99 && *cw == 724 && *ch == 384) { + if (g_fs_log_autoscale) { + fs_log("* amiga 1200 kickstart screen (pre)?\n"); + } + *cx = 74; *cy = 92; *cw = 640; *ch = 400; changed = 1; + } else if (*cx == 114 && *cy == 99 && *cw == 560 && *ch == 384) { + if (g_fs_log_autoscale) { + fs_log("* amiga 600/1200 kickstart screen?\n"); + } + *cx = 74; *cy = 92; *cw = 640; *ch = 400; changed = 1; +#if 0 // The following interfered with autoscaling for Jim Power - /* - else if (*cx == 74 && *cy == 30 && *cw == 640 && *ch == 518) { - fs_log("* workbench 1.3/2.0 screen?\n"); + } else if (*cx == 74 && *cy == 30 && *cw == 640 && *ch == 518) { + if (g_fs_log_autoscale) { + fs_log("* workbench 1.3/2.0 screen?\n"); + } *cx = 74; *cy = 36; *cw = 640; *ch = 512; changed = 1; - } - else if (*cx == 74 && *cy == 28 && *cw == 640 && *ch == 520) { - fs_log("* workbench 1.3/2.0 screen?\n"); + } else if (*cx == 74 && *cy == 28 && *cw == 640 && *ch == 520) { + if (g_fs_log_autoscale) { + fs_log("* workbench 1.3/2.0 screen?\n"); + } *cx = 74; *cy = 36; *cw = 640; *ch = 512; changed = 1; } - */ - /* - else if (*cx == 6 && *cy == 36 && *cw == 724 && *ch == 512) { - fs_log("* workbench screen with too much border?\n"); +#endif +#if 0 + } else if (*cx == 6 && *cy == 36 && *cw == 724 && *ch == 512) { + if (g_fs_log_autoscale) { + fs_log("* workbench screen with too much border?\n"); + } *cx = 74; *cy = 36; *cw = 640; *ch = 512; changed = 1; - } - */ - else if (*cx == 6 && *cy == 6 && *cw == 724 && *ch == 566) { - fs_log("* workbench screen with overscan incorrectly placed?\n"); +#endif + } else if (*cx == 6 && *cy == 6 && *cw == 724 && *ch == 566) { + if (g_fs_log_autoscale) { + fs_log("* workbench screen with overscan incorrectly placed?\n"); + } *cx = 2; *cy = 6; *cw = 724; *ch = 566; changed = 1; - } - else if (*cx == 10 && *cy == 7 && *cw == 716 && *ch == 566) { - fs_log("* amiga cd32 boot screen?\n"); + } else if (*cx == 10 && *cy == 7 && *cw == 716 && *ch == 566) { + if (g_fs_log_autoscale) { + fs_log("* amiga cd32 boot screen?\n"); + } *cx = 16; *cy = 6; *cw = 704; *ch = 566; changed = 1; - } - else if (*cx == 10 && *cy == 6 && *cw == 716 && *ch == 566) { - fs_log("* amiga cd32 boot screen?\n"); + } else if (*cx == 10 && *cy == 6 && *cw == 716 && *ch == 566) { + if (g_fs_log_autoscale) { + fs_log("* amiga cd32 boot screen?\n"); + } *cx = 16; *cy = 6; *cw = 704; *ch = 566; changed = 1; - } - else if (*cx == 6 && *cy == 96 && *cw == 724 && *ch == 476) { - fs_log("* amiga cd32 boot screen (booting CD)\n"); + } else if (*cx == 6 && *cy == 96 && *cw == 724 && *ch == 476) { + if (g_fs_log_autoscale) { + fs_log("* amiga cd32 boot screen (booting CD)\n"); + } *cx = 16; *cy = 6; *cw = 704; *ch = 566; changed = 1; - } - else if (*cx == 10 && *cy == 96 && *cw == 716 && *ch == 476) { - fs_log("* amiga cd32 boot screen (booting CD)\n"); + } else if (*cx == 10 && *cy == 96 && *cw == 716 && *ch == 476) { + if (g_fs_log_autoscale) { + fs_log("* amiga cd32 boot screen (booting CD)\n"); + } *cx = 16; *cy = 6; *cw = 704; *ch = 566; changed = 1; - } - else if (*cx == 6 && *cy == 82 && *cw == 724 && *ch == 490) { - fs_log("* amiga cd32 boot screen (booting Arcade Pool CD)\n"); + } else if (*cx == 6 && *cy == 82 && *cw == 724 && *ch == 490) { + if (g_fs_log_autoscale) { + fs_log("* amiga cd32 boot screen (booting Arcade Pool CD)\n"); + } *cx = 16; *cy = 6; *cw = 704; *ch = 566; changed = 1; - } - else if (*cx + *cw == 698 && *cy == 6 && *ch == 566) { - fs_log("* amiga cd32 menu\n"); + } else if (*cx + *cw == 698 && *cy == 6 && *ch == 566) { + if (g_fs_log_autoscale) { + fs_log("* amiga cd32 menu\n"); + } *cx = 16; *cy = 6; *cw = 704; *ch = 566; changed = 1; } if (changed) { - fs_log("* %3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", - *cx, *cy, *cw, *ch, ocx, ocy, ocw, och); - printf("* %3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", - *cx, *cy, *cw, *ch, ocx, ocy, ocw, och); + if (g_fs_log_autoscale) { + fs_log("* %3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", + *cx, *cy, *cw, *ch, ocx, ocy, ocw, och); + printf("* %3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", + *cx, *cy, *cw, *ch, ocx, ocy, ocw, och); + } } return changed; } @@ -262,7 +286,8 @@ static int modify_coordinates(int *cx, int *cy, int *cw, int *ch) { #define SUBSCAN #ifdef SUBSCAN -static void narrow_rect(RenderData* rd, int *nx, int *ny, int *nw, int *nh) { +static void narrow_rect(RenderData* rd, int *nx, int *ny, int *nw, int *nh) +{ if (rd->bpp != 4) { // not implemented for 16-bit video. return; @@ -359,8 +384,10 @@ static void narrow_rect(RenderData* rd, int *nx, int *ny, int *nw, int *nh) { static int px = 0, py = 0, pw = 0, ph = 0; if (x != px || y != py || w != pw || h != ph) { - fs_log(" sub: %3d %3d %3d %3d\n", x, y, w, h); - printf(" sub: %3d %3d %3d %3d\n", x, y, w, h); + if (g_fs_log_autoscale) { + fs_log(" sub: %3d %3d %3d %3d\n", x, y, w, h); + printf(" sub: %3d %3d %3d %3d\n", x, y, w, h); + } px = x; py = y; pw = w; @@ -379,7 +406,8 @@ static void narrow_rect(RenderData* rd, int *nx, int *ny, int *nw, int *nh) { } #endif -static void render_screen(RenderData* rd) { +static void render_screen(RenderData* rd) +{ #if 0 static int64_t last_time = 0; int64_t t = fs_emu_monotonic_time(); @@ -446,8 +474,10 @@ static void render_screen(RenderData* rd) { int have_narrowed = 0; #endif if (cchange) { - fs_log("auto: %3d %3d %3d %3d\n", cx, cy, cw, ch); - printf("auto: %3d %3d %3d %3d\n", cx, cy, cw, ch); + if (g_fs_log_autoscale) { + fs_log("auto: %3d %3d %3d %3d\n", cx, cy, cw, ch); + printf("auto: %3d %3d %3d %3d\n", cx, cy, cw, ch); + } } modify_coordinates(&cx, &cy, &cw, &ch); //if (!modify_coordinates(&cx, &cy, &cw, &ch)) { @@ -489,10 +519,12 @@ static void render_screen(RenderData* rd) { } #endif /* - fs_log("%3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", - ucx, ucy, ucw, uch, cx, cy, cw, ch); - printf("%3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", - ucx, ucy, ucw, uch, cx, cy, cw, ch); + * if (g_fs_log_autoscale) { + fs_log("%3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", + ucx, ucy, ucw, uch, cx, cy, cw, ch); + printf("%3d %3d %3d %3d [ %3d %3d %3d %3d ]\n", + ucx, ucy, ucw, uch, cx, cy, cw, ch); + } */ break; } @@ -505,14 +537,18 @@ static void render_screen(RenderData* rd) { ucw = cw; uch = ch; /* - fs_log("%3d %3d %3d %3d\n", ucx, ucy, ucw, uch); - printf("%3d %3d %3d %3d\n", ucx, ucy, ucw, uch); + if (g_fs_log_autoscale) { + fs_log("%3d %3d %3d %3d\n", ucx, ucy, ucw, uch); + printf("%3d %3d %3d %3d\n", ucx, ucy, ucw, uch); + } */ } static int lucx = 0, lucy = 0, lucw = 0, luch = 0; if (ucx != lucx || ucy != lucy || ucw != lucw || uch != luch) { - fs_log(" = %3d %3d %3d %3d\n", ucx, ucy, ucw, uch); - printf(" = %3d %3d %3d %3d\n", ucx, ucy, ucw, uch); + if (g_fs_log_autoscale) { + fs_log(" = %3d %3d %3d %3d\n", ucx, ucy, ucw, uch); + printf(" = %3d %3d %3d %3d\n", ucx, ucy, ucw, uch); + } lucx = ucx; lucy = ucy; lucw = ucw; @@ -642,7 +678,8 @@ static void display_screen() #endif } -static void toggle_zoom(int flags) { +static void toggle_zoom(int flags) +{ if (g_last_seen_mode_rtg) { fs_emu_notification(1511162016, _("Zoom is disabled in RTG mode")); return; @@ -730,7 +767,11 @@ void fs_uae_init_video(void) free(value); } - const char* cvalue = fs_config_get_const_string("theme_zoom"); + if (fs_config_get_boolean(OPTION_LOG_AUTOSCALE) == 1) { + g_fs_log_autoscale = true; + } + + const char* cvalue = fs_config_get_const_string(OPTION_THEME_ZOOM); if (cvalue) { zoom_mode *z = g_zoom_modes + CUSTOM_ZOOM_MODE; //char *name = malloc(strlen(cvalue) + 1); diff --git a/src/memory.cpp b/src/memory.cpp index 2e75d0e10..8764d7dd7 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1350,9 +1350,9 @@ static void log_kickstart(uae_u8 *mem, int size) if (rd) { char tmp[MAX_DPATH]; getromname(rd, tmp); - printf("KICKSTART: %s\n", tmp); + printf("UAE: %s\n", tmp); } else { - printf("KICKSTART: Unknown %08x (size %d)\n", crc32, size); + printf("UAE: KS ROM %08x (%d bytes)\n", crc32, size); } } @@ -1691,7 +1691,9 @@ static int load_kickstart (void) if (f != NULL) { #ifdef FSUAE +#if 0 printf("KICKSTART: %s\n", currprefs.romfile); +#endif #endif int filesize, size, maxsize; int kspos = ROM_SIZE_512; diff --git a/src/od-fs/libamiga.cpp b/src/od-fs/libamiga.cpp index 4a86ce364..247cc77fd 100644 --- a/src/od-fs/libamiga.cpp +++ b/src/od-fs/libamiga.cpp @@ -126,11 +126,10 @@ void amiga_floppy_set_writable_images(int writable) { g_fs_uae_writable_disk_images = writable; } -int amiga_init() { - printf("libamiga (based on emulation core from %s) initialized\n", - UAE_BASE_VERSION); - write_log("libamiga (based on emulation core from %s) initialized\n", - UAE_BASE_VERSION); +int amiga_init() +{ + printf("UAE: Initializing core derived from %s\n", UAE_BASE_VERSION); + write_log("UAE: Initializing core derived from %s\n", UAE_BASE_VERSION); // because frame_time_t is sometimes cast to int, we make sure to // start from 0 wo it will work for "a while". Should be fixed @@ -597,8 +596,9 @@ int amiga_set_int_option(const char *option, int value) { return result; } -int amiga_quit() { - printf("amiga_quit\n"); +int amiga_quit() +{ + printf("UAE: Calling uae_quit\n"); uae_quit(); return 1; } diff --git a/src/od-fs/stubs.cpp b/src/od-fs/stubs.cpp index cd4a94c1a..ffbc509d8 100644 --- a/src/od-fs/stubs.cpp +++ b/src/od-fs/stubs.cpp @@ -172,9 +172,10 @@ void target_restart (void) { STUB(""); } -void target_quit (void) { - write_log("UAE emulation core is quitting\n"); - printf("UAE emulation core is quitting\n"); +void target_quit (void) +{ + write_log("UAE: Stopping\n"); + printf("UAE: Stopping\n"); } void target_fixup_options (struct uae_prefs *p) { From 21071a06c31bc3d604ee045d7dacaaded2b558a5 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Mon, 10 Aug 2015 22:11:37 +0200 Subject: [PATCH 02/25] support direct loading of .adf file --- ChangeLog | 3 + src/fs-uae/main.c | 139 ++++++++++++++++++++++++++----------------- src/fs-uae/options.h | 2 + 3 files changed, 90 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index c4e3e0752..cfa51d3ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ Version 2.5.39dev: * Updated AROS kickstart replacement to ver. 2015-05-20 from WinUAE 3.1.0. +* Config files must end with .fs-uae or .conf to be loaded by FS-UAE. +* If you give fs-uae a command line argument with path to a .adf, it will + be used as value for floppy_drive_0. Version 2.5.38dev: diff --git a/src/fs-uae/main.c b/src/fs-uae/main.c index 4e40822b0..3b56ca021 100644 --- a/src/fs-uae/main.c +++ b/src/fs-uae/main.c @@ -3,19 +3,15 @@ #endif #define _GNU_SOURCE 1 - #include - #ifdef USE_SDL -// we must include SDL first before emu.h, so libfsemu's #definition of main -// is the current one (on Windows) when main is encountered further down +/* We must include SDL first before emu.h, so libfsemu's #definition of main + * is the current one (on Windows) when main is encountered further down. */ #include #endif - #ifdef MACOSX #include #endif - #include #include #include @@ -24,7 +20,6 @@ #include #include #include - #include #include #include @@ -33,10 +28,9 @@ #include "fs-uae.h" #include "recording.h" #include "plugins.h" +#include "options.h" #include "config-drives.h" -//static char *g_default_rom_dir = "."; - static int fs_uae_argc; static char **fs_uae_argv; static int g_warn_about_missing_config_file = 0; @@ -44,7 +38,8 @@ static int g_warn_about_missing_config_file = 0; #define LOG_LINE "---------------------------------------------------------" \ "-------------------\n" -static void change_port_device_mode(int data) { +static void change_port_device_mode(int data) +{ int modes = INPUTEVENT_AMIGA_JOYPORT_MODE_0_LAST - INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE + 1; int port = data / modes; @@ -62,7 +57,8 @@ static void change_port_device_mode(int data) { } } -static void select_port_0_device(int data) { +static void select_port_0_device(int data) +{ printf("--> device index %d\n", data); int port = 0; if (data == 9) { @@ -106,7 +102,8 @@ int g_fs_uae_last_input_event = 0; int g_fs_uae_last_input_event_state = 0; int g_fs_uae_state_number = 0; -void fs_uae_process_input_event(int line, int action, int state, int playback) { +void fs_uae_process_input_event(int line, int action, int state, int playback) +{ static int first_time = 1; if (first_time == 1) { first_time = 0; @@ -303,7 +300,8 @@ static int input_handler_loop(int line) { return 1; } -static void pause_throttle() { +static void pause_throttle() +{ /* if (fs_emu_get_vblank_sync()) { return; @@ -312,7 +310,8 @@ static void pause_throttle() { fs_emu_msleep(5); } -static void event_handler(int line) { +static void event_handler(int line) +{ // printf("%d\n", line); if (line >= 0) { input_handler_loop(line); @@ -379,11 +378,13 @@ static void event_handler(int line) { } +char *g_fs_uae_disk_file_path = NULL; char *g_fs_uae_config_file_path = NULL; char *g_fs_uae_config_dir_path = NULL; //GKeyFile *g_fs_uae_config = NULL; -static int audio_callback_function(int type, int16_t *buffer, int size) { +static int audio_callback_function(int type, int16_t *buffer, int size) +{ if (type == 0) { return fs_emu_audio_queue_buffer(0, buffer, size); } @@ -406,7 +407,8 @@ static int audio_callback_function(int type, int16_t *buffer, int size) { return -1; } -void fs_uae_load_rom_files(const char *path) { +void fs_uae_load_rom_files(const char *path) +{ fs_log("fs_uae_load_rom_files %s\n", path); GDir *dir = g_dir_open(path, 0, NULL); if (dir == NULL) { @@ -470,13 +472,15 @@ void fs_uae_load_rom_files(const char *path) { //exit(1); } -char *fs_uae_encode_path(const char* path) { +char *fs_uae_encode_path(const char* path) +{ // FIXME: libamiga now always accepts UTF-8, so this function is // deprecated. Simply returning a duplicate now. return g_strdup(path); } -char *fs_uae_decode_path(const char* path) { +char *fs_uae_decode_path(const char* path) +{ // FIXME: libamiga now always accepts UTF-8, so this function is // deprecated. Simply returning a duplicate now. return g_strdup(path); @@ -488,7 +492,8 @@ static void on_gui_message(const char* message) fs_emu_warning("%s", message); } -static void on_init() { +static void on_init() +{ fs_log("\n"); fs_log(LOG_LINE); fs_log("uae configuration\n"); @@ -588,13 +593,15 @@ static void on_init() { fs_log("\n"); } -static void pause_function(int pause) { +static void pause_function(int pause) +{ fs_log("pause_function %d\n", pause); //uae_pause(pause); amiga_pause(pause); } -static int load_config_file() { +static int load_config_file() +{ fs_log("load config file\n"); const char *msg = "checking config file %s\n"; @@ -686,11 +693,13 @@ static int load_config_file() { return 0; } -static void log_to_libfsemu(const char *message) { +static void log_to_libfsemu(const char *message) +{ fs_log_string(message); } -static void main_function() { +static void main_function() +{ amiga_main(); fs_log("amiga_main returned\n"); fs_uae_write_recorded_session(); @@ -701,7 +710,8 @@ static void main_function() { // int _putenv(const char *envstring); #endif -static void init_i18n() { +static void init_i18n() +{ if (fs_config_get_boolean("localization") == 0) { fs_log("localization was forced off\n"); return; @@ -747,15 +757,19 @@ static void init_i18n() { #endif } -static void led_function(int led, int state) { - // floppy led status is custom overlay 0..3 - //if (led >= 0) { - // printf("led %d state %d\n", led, state); - //} +static void led_function(int led, int state) +{ + /* floppy led status is custom overlay 0..3 */ +#if 0 + if (led >= 0) { + printf("led %d state %d\n", led, state); + } +#endif fs_emu_set_custom_overlay_state(led, state); } -static void on_update_leds(void *data) { +static void on_update_leds(void *data) +{ amiga_led_data *leds = (amiga_led_data *) data; for (int i = 0; i < 4; i++) { int led = 12; // df0_d1 @@ -766,7 +780,8 @@ static void on_update_leds(void *data) { } -static void media_function(int drive, const char *path) { +static void media_function(int drive, const char *path) +{ // media insertion status is custom overlay 4..7 fs_emu_set_custom_overlay_state(4 + drive, path && path[0]); } @@ -775,7 +790,8 @@ int ManyMouse_Init(void); void ManyMouse_Quit(void); const char *ManyMouse_DeviceName(unsigned int index); -static void list_joysticks() { +static void list_joysticks() +{ printf("# FS-UAE %s\n", PACKAGE_VERSION); printf("# listing keyboards\n"); printf("K: Keyboard\n"); @@ -822,7 +838,8 @@ extern int g_fsdb_debug; extern int g_random_debug_logging; extern int inputdevice_logging; -static void configure_logging(const char *logstr) { +static void configure_logging(const char *logstr) +{ if (!logstr) { fs_log("configure logging: none\n"); return; @@ -847,7 +864,8 @@ static void configure_logging(const char *logstr) { } } -static void cleanup_old_file(const char *path) { +static void cleanup_old_file(const char *path) +{ char *p = fs_uae_expand_path(path); if (fs_path_exists(p)) { if (fs_path_is_dir(p)) { @@ -862,7 +880,8 @@ static void cleanup_old_file(const char *path) { free(p); } -static void cleanup_old_files() { +static void cleanup_old_files() +{ // Logs are now stored in $BASE/Cache/Logs by default cleanup_old_file("$BASE/Logs/FS-UAE.log"); cleanup_old_file("$BASE/Logs/FS-UAE.log.txt"); @@ -873,6 +892,17 @@ static void cleanup_old_files() { cleanup_old_file("$BASE/Logs"); } +static bool check_extension(const char *path, const char *ext) +{ + if (path == NULL) { + return false; + } + gchar* path_lower = g_ascii_strdown(path, -1); + bool result = g_str_has_suffix(path_lower, ext); + g_free(path_lower); + return result; +} + static const char *overlay_names[] = { "df0_led", // 0 "df1_led", // 1 @@ -994,14 +1024,20 @@ int main(int argc, char* argv[]) while (arg && *arg) { const gchar *test_path = *arg; if (test_path && fs_path_exists(test_path)) { - g_fs_uae_config_file_path = g_strdup(test_path); + if (check_extension(test_path, ".fs-uae")) { + g_fs_uae_config_file_path = g_strdup(test_path); + } else if (check_extension(test_path, ".conf")) { + g_fs_uae_config_file_path = g_strdup(test_path); + } else if (check_extension(test_path, ".adf")) { + g_fs_uae_disk_file_path = g_strdup(test_path); + } } arg++; } } - // parse options first, in case base_dir, logging options etc is - // specified on the command line + /* Parse options first, in case base_dir, logging options etc is + * specified on the command line. */ fs_config_parse_options(argc - 1, argv + 1); fs_log("\n"); @@ -1017,12 +1053,14 @@ int main(int argc, char* argv[]) // then load the config file load_config_file(); - // parse options again, overwriting options loaded from configuration - // file - //fs_config_parse_options(argc - 1, argv + 1); init_i18n(); + if (g_fs_uae_disk_file_path) { + fs_config_set_string(OPTION_FLOPPY_DRIVE_0, g_fs_uae_disk_file_path); + g_warn_about_missing_config_file = 0; + } + if (g_warn_about_missing_config_file) { fs_emu_warning(_("No configuration file was found")); } @@ -1103,16 +1141,13 @@ int main(int argc, char* argv[]) record_file); deterministic_mode = 1; fs_uae_enable_recording(record_file); - } - else { + } else { fs_log("not running in record mode\n"); } - if (fs_emu_netplay_enabled() || - fs_config_get_boolean("deterministic") == 1) { + fs_config_get_boolean(OPTION_DETERMINISTIC) == 1) { deterministic_mode = 1; } - if (deterministic_mode) { amiga_set_deterministic_mode(); } @@ -1174,17 +1209,13 @@ int main(int argc, char* argv[]) if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_RGBA) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_RGBA); - } - else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) { + } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_BGRA); - } - else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G6B5) { + } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G6B5) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G6B5); - } - else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G5B5A1) { + } else if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_R5G5B5A1) { amiga_set_video_format(AMIGA_VIDEO_FORMAT_R5G5B5A1); - } - else { + } else { fs_emu_warning("Unsupported video format requested"); } amiga_add_rtg_resolution(672, 540); diff --git a/src/fs-uae/options.h b/src/fs-uae/options.h index 5620f4633..476c46915 100644 --- a/src/fs-uae/options.h +++ b/src/fs-uae/options.h @@ -13,8 +13,10 @@ //#define OPTION_CURSOR_INTEGRATION "cursor_integration" #define OPTION_CPU "cpu" #define OPTION_CPU_IDLE "cpu_idle" +#define OPTION_DETERMINISTIC "deterministic" #define OPTION_DONGLE_TYPE "dongle_type" #define OPTION_FAST_MEMORY "fast_memory" +#define OPTION_FLOPPY_DRIVE_0 "floppy_drive_0" #define OPTION_FLOPPY_DRIVE_VOLUME "floppy_drive_volume" #define OPTION_FLOPPY_DRIVE_VOLUME_EMPTY "floppy_drive_volume_empty" #define OPTION_FPU "fpu" From 4f6d198a51430639247a3c3f5b21e04da8d4c693 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Tue, 11 Aug 2015 18:32:24 +0200 Subject: [PATCH 03/25] use container-based travis infrastructure --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5df146e0a..dd4899ae0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,13 +7,12 @@ before_install: - sudo apt-get update -qq - sudo apt-get install libsdl2-dev libglib2.0-dev libopenal-dev gettext libfreetype6-dev libxi-dev libpng12-dev zlib1g-dev libmpeg2-4-dev zip libglew-dev script: ./bootstrap && ./configure && make distcheck - +sudo: false env: global: # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # via the "travis encrypt" command using the project repo's public key - secure: "g2yI8YRAL0kcKpFC4e3Bd4U5OePFRz+wXc2Ji0XkG69W66/WJ2KU03NsBRBlAxre6HccXltMl0Zq52ahg3j2c5INASTon68SRT9VIPFiKKXquM1L218hWnyGv6UPHdZldR72s9oiu3dBznIuZFKxsdIjlHW77dmJYJbxFKBkXBo=" - addons: coverity_scan: project: From e98f9f787dd58aa28a4979090f510a0bac3bff0c Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Tue, 11 Aug 2015 18:34:20 +0200 Subject: [PATCH 04/25] Revert "use container-based travis infrastructure" This reverts commit 4f6d198a51430639247a3c3f5b21e04da8d4c693. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dd4899ae0..5df146e0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,12 +7,13 @@ before_install: - sudo apt-get update -qq - sudo apt-get install libsdl2-dev libglib2.0-dev libopenal-dev gettext libfreetype6-dev libxi-dev libpng12-dev zlib1g-dev libmpeg2-4-dev zip libglew-dev script: ./bootstrap && ./configure && make distcheck -sudo: false + env: global: # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # via the "travis encrypt" command using the project repo's public key - secure: "g2yI8YRAL0kcKpFC4e3Bd4U5OePFRz+wXc2Ji0XkG69W66/WJ2KU03NsBRBlAxre6HccXltMl0Zq52ahg3j2c5INASTon68SRT9VIPFiKKXquM1L218hWnyGv6UPHdZldR72s9oiu3dBznIuZFKxsdIjlHW77dmJYJbxFKBkXBo=" + addons: coverity_scan: project: From 330e6d937abd38be1eda65b2f9db7ba743db87ed Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 14 Aug 2015 21:33:00 +0200 Subject: [PATCH 05/25] more gamepad configs, other minor changes --- ChangeLog | 1 + doc/options/uae_rtc | 2 +- libfsemu/src/emu/theme.c | 13 ++---- ...4f04000015b3000010010000.fs-uae-controller | 42 ++++++++++++++++++ ...6d0400001dc2000014400000.fs-uae-controller | 42 ++++++++++++++++++ ...0000000015b3000000000000.fs-uae-controller | 42 ++++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++++ ...000000008e02000000000000.fs-uae-controller | 5 ++- ...0000000016c2000000000000.fs-uae-controller | 42 ++++++++++++++++++ ...000000001dc2000000000000.fs-uae-controller | 43 +++++++++++++++++++ ...000000001ec2000000000000.fs-uae-controller | 43 +++++++++++++++++++ ...000000001fc2000000000000.fs-uae-controller | 43 +++++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++++ .../logitech_dual_action_12_4_1_0_macosx.conf | 38 ++++++++++------ ...logitech_dual_action_12_4_1_0_windows.conf | 42 ++++++++++++++++++ .../logitech_gamepad_f310_11_6_1_0_linux.conf | 42 ++++++++++++++++++ ...aster_dual_analog_3_2_12_4_1_0_macosx.conf | 42 ++++++++++++++++++ ...ster_dual_analog_3_2_12_4_1_0_windows.conf | 42 ++++++++++++++++++ ...master_dual_analog_3_2_12_4_1_0_linux.conf | 42 ++++++++++++++++++ ...reless_360_controller_15_6_0_0_macosx.conf | 43 +++++++++++++++++++ ..._360_wired_controller_15_6_0_0_macosx.conf | 43 +++++++++++++++++++ ..._one_wired_controller_15_6_0_0_macosx.conf | 43 +++++++++++++++++++ src/fs-uae/paths.c | 12 +----- 23 files changed, 757 insertions(+), 34 deletions(-) create mode 100644 share/fs-uae/input/030000004f04000015b3000010010000.fs-uae-controller create mode 100644 share/fs-uae/input/030000006d0400001dc2000014400000.fs-uae-controller create mode 100644 share/fs-uae/input/4f0400000000000015b3000000000000.fs-uae-controller create mode 100644 share/fs-uae/input/4f0415b3000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/6d0400000000000016c2000000000000.fs-uae-controller create mode 100644 share/fs-uae/input/6d040000000000001dc2000000000000.fs-uae-controller create mode 100644 share/fs-uae/input/6d040000000000001ec2000000000000.fs-uae-controller create mode 100644 share/fs-uae/input/6d040000000000001fc2000000000000.fs-uae-controller create mode 100644 share/fs-uae/input/6d0416c2000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/logitech_dual_action_12_4_1_0_windows.conf create mode 100644 share/fs-uae/input/logitech_gamepad_f310_11_6_1_0_linux.conf create mode 100644 share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_macosx.conf create mode 100644 share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_windows.conf create mode 100644 share/fs-uae/input/thrustmaster_thrustmaster_dual_analog_3_2_12_4_1_0_linux.conf create mode 100644 share/fs-uae/input/wireless_360_controller_15_6_0_0_macosx.conf create mode 100644 share/fs-uae/input/xbox_360_wired_controller_15_6_0_0_macosx.conf create mode 100644 share/fs-uae/input/xbox_one_wired_controller_15_6_0_0_macosx.conf diff --git a/ChangeLog b/ChangeLog index cfa51d3ff..e907e4f31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.39dev: +* Updated config for Logitech F310 and added Thrustmaster Dual Action 4. * Updated AROS kickstart replacement to ver. 2015-05-20 from WinUAE 3.1.0. * Config files must end with .fs-uae or .conf to be loaded by FS-UAE. * If you give fs-uae a command line argument with path to a .adf, it will diff --git a/doc/options/uae_rtc b/doc/options/uae_rtc index fe5161ea8..ff51283c1 100644 --- a/doc/options/uae_rtc +++ b/doc/options/uae_rtc @@ -11,7 +11,7 @@ want to override this option, you may also have to set Value: auto ("Auto") - Automatically enable RTC module for some Amiga models. Value: none ("None") - Real time clock is explicitly disabled. -Value: MSM6242B (Oki MSM6242B)- RTC module in A500/500+/600/1200/2000 models. +Value: MSM6242B (Oki MSM6242B) - RTC module in A500/500+/600/1200/2000 models. Value: RP5C01A (Ricoh RP5C01A) - RTC module in big-box Amigas (A3000, A4000). Value: MSM6242B_A2000 (A2000 MSM6242B) - Only used in very early A2000 revisions, not even WB 1.3 supports it. diff --git a/libfsemu/src/emu/theme.c b/libfsemu/src/emu/theme.c index ad65cce5b..92fa8f201 100644 --- a/libfsemu/src/emu/theme.c +++ b/libfsemu/src/emu/theme.c @@ -81,13 +81,8 @@ char *fs_emu_theme_get_resource_path(const char *name) { return NULL; } -int fs_emu_theme_get_resource_data(const char *name, char **data, int *size) { - // printf("fs_emu_theme_get_resource_data (%s)\n", name); - /* - if (fs_path_exists(name)) { - return g_strdup(name); - } - */ +int fs_emu_theme_get_resource_data(const char *name, char **data, int *size) +{ char *p; p = g_build_filename(g_fs_emu_theme.path, name, NULL); if (fs_path_exists(p)) { @@ -108,13 +103,13 @@ int fs_emu_theme_get_resource_data(const char *name, char **data, int *size) { } *data = malloc(*size); if (fread(*data, *size, 1, f) != 1) { + free(*data); fclose(f); return 3; } fclose(f); return 0; - } - else { + } else { free(p); } diff --git a/share/fs-uae/input/030000004f04000015b3000010010000.fs-uae-controller b/share/fs-uae/input/030000004f04000015b3000010010000.fs-uae-controller new file mode 100644 index 000000000..c2e911881 --- /dev/null +++ b/share/fs-uae/input/030000004f04000015b3000010010000.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Thrustmaster Thrustmaster dual analog 3.2 +platform = linux + +[device] +make = Thrustmaster +model = Dual Analog 4 +type = gamepad + +[sdl] +guid = 030000004f04000015b3000010010000 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = south_button +button_1 = west_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = left_trigger +button_6 = right_shoulder +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/030000006d0400001dc2000014400000.fs-uae-controller b/share/fs-uae/input/030000006d0400001dc2000014400000.fs-uae-controller new file mode 100644 index 000000000..610d5e2c1 --- /dev/null +++ b/share/fs-uae/input/030000006d0400001dc2000014400000.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Logitech Gamepad F310 +platform = linux + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 030000006d0400001dc2000014400000 +buttons = 11 +hats = 1 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = rstick_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_9 = lstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/4f0400000000000015b3000000000000.fs-uae-controller b/share/fs-uae/input/4f0400000000000015b3000000000000.fs-uae-controller new file mode 100644 index 000000000..4f2c50445 --- /dev/null +++ b/share/fs-uae/input/4f0400000000000015b3000000000000.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Thrustmaster dual analog 3.2 +platform = macosx + +[device] +make = Thrustmaster +model = Dual Analog 4 +type = gamepad + +[sdl] +guid = 4f0400000000000015b3000000000000 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = south_button +button_1 = west_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = left_trigger +button_6 = right_shoulder +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/4f0415b3000000000000504944564944.fs-uae-controller b/share/fs-uae/input/4f0415b3000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..46d7d5e8b --- /dev/null +++ b/share/fs-uae/input/4f0415b3000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Thrustmaster dual analog 3.2 +platform = windows + +[device] +make = Thrustmaster +model = Dual Analog 4 +type = gamepad + +[sdl] +guid = 4f0415b3000000000000504944564944 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = south_button +button_1 = west_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = left_trigger +button_6 = right_shoulder +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/5e040000000000008e02000000000000.fs-uae-controller b/share/fs-uae/input/5e040000000000008e02000000000000.fs-uae-controller index fce45db4a..16ff876e6 100644 --- a/share/fs-uae/input/5e040000000000008e02000000000000.fs-uae-controller +++ b/share/fs-uae/input/5e040000000000008e02000000000000.fs-uae-controller @@ -1,10 +1,10 @@ [fs-uae-controller] -name = X360Controller +name = Xbox 360 Wired Controller platform = macosx [device] make = Microsoft -model = Xbox One Pad +model = Xbox 360/One Pad type = gamepad [sdl] @@ -28,6 +28,7 @@ axis_4_pos = rstick_down axis_5_pos = right_trigger button_0 = south_button button_1 = east_button +button_10 = menu_button button_11 = dpad_up button_12 = dpad_down button_13 = dpad_left diff --git a/share/fs-uae/input/6d0400000000000016c2000000000000.fs-uae-controller b/share/fs-uae/input/6d0400000000000016c2000000000000.fs-uae-controller new file mode 100644 index 000000000..a4af793f8 --- /dev/null +++ b/share/fs-uae/input/6d0400000000000016c2000000000000.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Logitech Dual Action +platform = macosx + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d0400000000000016c2000000000000 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = west_button +button_1 = south_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = left_trigger +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/6d040000000000001dc2000000000000.fs-uae-controller b/share/fs-uae/input/6d040000000000001dc2000000000000.fs-uae-controller new file mode 100644 index 000000000..05126b9e0 --- /dev/null +++ b/share/fs-uae/input/6d040000000000001dc2000000000000.fs-uae-controller @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Xbox 360 Wired Controller +platform = macosx + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d040000000000001dc2000000000000 +buttons = 15 +hats = 0 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_11 = dpad_up +button_12 = dpad_down +button_13 = dpad_left +button_14 = dpad_right +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = lstick_button +button_7 = rstick_button +button_8 = start_button +button_9 = select_button diff --git a/share/fs-uae/input/6d040000000000001ec2000000000000.fs-uae-controller b/share/fs-uae/input/6d040000000000001ec2000000000000.fs-uae-controller new file mode 100644 index 000000000..20388ebb0 --- /dev/null +++ b/share/fs-uae/input/6d040000000000001ec2000000000000.fs-uae-controller @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Xbox 360 Wired Controller +platform = macosx + +[device] +make = Logitech +model = F510 +type = gamepad + +[sdl] +guid = 6d040000000000001ec2000000000000 +buttons = 15 +hats = 0 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_11 = dpad_up +button_12 = dpad_down +button_13 = dpad_left +button_14 = dpad_right +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = lstick_button +button_7 = rstick_button +button_8 = start_button +button_9 = select_button diff --git a/share/fs-uae/input/6d040000000000001fc2000000000000.fs-uae-controller b/share/fs-uae/input/6d040000000000001fc2000000000000.fs-uae-controller new file mode 100644 index 000000000..776c71b55 --- /dev/null +++ b/share/fs-uae/input/6d040000000000001fc2000000000000.fs-uae-controller @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Xbox 360 Wired Controller +platform = macosx + +[device] +make = Logitech +model = F710 +type = gamepad + +[sdl] +guid = 6d040000000000001fc2000000000000 +buttons = 15 +hats = 0 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_11 = dpad_up +button_12 = dpad_down +button_13 = dpad_left +button_14 = dpad_right +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = lstick_button +button_7 = rstick_button +button_8 = start_button +button_9 = select_button diff --git a/share/fs-uae/input/6d0416c2000000000000504944564944.fs-uae-controller b/share/fs-uae/input/6d0416c2000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..8ca4e4fca --- /dev/null +++ b/share/fs-uae/input/6d0416c2000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Logitech Dual Action +platform = windows + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d0416c2000000000000504944564944 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = west_button +button_1 = south_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = left_trigger +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/logitech_dual_action_12_4_1_0_macosx.conf b/share/fs-uae/input/logitech_dual_action_12_4_1_0_macosx.conf index a40af8e98..a4af793f8 100644 --- a/share/fs-uae/input/logitech_dual_action_12_4_1_0_macosx.conf +++ b/share/fs-uae/input/logitech_dual_action_12_4_1_0_macosx.conf @@ -1,28 +1,42 @@ -# Logitech Dual Action +[fs-uae-controller] +name = Logitech Dual Action +platform = macosx + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d0400000000000016c2000000000000 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 [default] include = universal_gamepad -hat_0_left = dpad_left -hat_0_right = dpad_right -hat_0_up = dpad_up -hat_0_down = dpad_down axis_0_neg = lstick_left axis_0_pos = lstick_right axis_1_neg = lstick_up axis_1_pos = lstick_down -button_10 = lstick_button axis_2_neg = rstick_left axis_2_pos = rstick_right axis_3_neg = rstick_up axis_3_pos = rstick_down -button_11 = rstick_button button_0 = west_button -button_3 = north_button -button_2 = east_button button_1 = south_button -button_8 = select_button -button_9 = start_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button button_4 = left_shoulder -button_6 = left_trigger button_5 = right_shoulder +button_6 = left_trigger button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/logitech_dual_action_12_4_1_0_windows.conf b/share/fs-uae/input/logitech_dual_action_12_4_1_0_windows.conf new file mode 100644 index 000000000..8ca4e4fca --- /dev/null +++ b/share/fs-uae/input/logitech_dual_action_12_4_1_0_windows.conf @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Logitech Dual Action +platform = windows + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d0416c2000000000000504944564944 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = west_button +button_1 = south_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = left_trigger +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/logitech_gamepad_f310_11_6_1_0_linux.conf b/share/fs-uae/input/logitech_gamepad_f310_11_6_1_0_linux.conf new file mode 100644 index 000000000..610d5e2c1 --- /dev/null +++ b/share/fs-uae/input/logitech_gamepad_f310_11_6_1_0_linux.conf @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Logitech Gamepad F310 +platform = linux + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 030000006d0400001dc2000014400000 +buttons = 11 +hats = 1 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = rstick_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_9 = lstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_macosx.conf b/share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_macosx.conf new file mode 100644 index 000000000..4f2c50445 --- /dev/null +++ b/share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_macosx.conf @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Thrustmaster dual analog 3.2 +platform = macosx + +[device] +make = Thrustmaster +model = Dual Analog 4 +type = gamepad + +[sdl] +guid = 4f0400000000000015b3000000000000 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = south_button +button_1 = west_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = left_trigger +button_6 = right_shoulder +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_windows.conf b/share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_windows.conf new file mode 100644 index 000000000..46d7d5e8b --- /dev/null +++ b/share/fs-uae/input/thrustmaster_dual_analog_3_2_12_4_1_0_windows.conf @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Thrustmaster dual analog 3.2 +platform = windows + +[device] +make = Thrustmaster +model = Dual Analog 4 +type = gamepad + +[sdl] +guid = 4f0415b3000000000000504944564944 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = south_button +button_1 = west_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = left_trigger +button_6 = right_shoulder +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/thrustmaster_thrustmaster_dual_analog_3_2_12_4_1_0_linux.conf b/share/fs-uae/input/thrustmaster_thrustmaster_dual_analog_3_2_12_4_1_0_linux.conf new file mode 100644 index 000000000..c2e911881 --- /dev/null +++ b/share/fs-uae/input/thrustmaster_thrustmaster_dual_analog_3_2_12_4_1_0_linux.conf @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Thrustmaster Thrustmaster dual analog 3.2 +platform = linux + +[device] +make = Thrustmaster +model = Dual Analog 4 +type = gamepad + +[sdl] +guid = 030000004f04000015b3000010010000 +buttons = 12 +hats = 1 +axes = 4 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = rstick_left +axis_2_pos = rstick_right +axis_3_neg = rstick_up +axis_3_pos = rstick_down +button_0 = south_button +button_1 = west_button +button_10 = lstick_button +button_11 = rstick_button +button_2 = east_button +button_3 = north_button +button_4 = left_shoulder +button_5 = left_trigger +button_6 = right_shoulder +button_7 = right_trigger +button_8 = select_button +button_9 = start_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/wireless_360_controller_15_6_0_0_macosx.conf b/share/fs-uae/input/wireless_360_controller_15_6_0_0_macosx.conf new file mode 100644 index 000000000..65c055a5b --- /dev/null +++ b/share/fs-uae/input/wireless_360_controller_15_6_0_0_macosx.conf @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Wireless 360 Controller +platform = macosx + +[device] +make = Microsoft +model = Xbox 360 Pad +type = gamepad + +[sdl] +guid = 5e040000000000008e02000000000000 +buttons = 15 +hats = 0 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_11 = dpad_up +button_12 = dpad_down +button_13 = dpad_left +button_14 = dpad_right +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = lstick_button +button_7 = rstick_button +button_8 = start_button +button_9 = select_button diff --git a/share/fs-uae/input/xbox_360_wired_controller_15_6_0_0_macosx.conf b/share/fs-uae/input/xbox_360_wired_controller_15_6_0_0_macosx.conf new file mode 100644 index 000000000..1e735e6d7 --- /dev/null +++ b/share/fs-uae/input/xbox_360_wired_controller_15_6_0_0_macosx.conf @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Xbox 360 Wired Controller +platform = macosx + +[device] +make = Microsoft +model = Xbox 360 Pad +type = gamepad + +[sdl] +guid = 5e040000000000008e02000000000000 +buttons = 15 +hats = 0 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_11 = dpad_up +button_12 = dpad_down +button_13 = dpad_left +button_14 = dpad_right +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = lstick_button +button_7 = rstick_button +button_8 = start_button +button_9 = select_button diff --git a/share/fs-uae/input/xbox_one_wired_controller_15_6_0_0_macosx.conf b/share/fs-uae/input/xbox_one_wired_controller_15_6_0_0_macosx.conf new file mode 100644 index 000000000..f84738cb7 --- /dev/null +++ b/share/fs-uae/input/xbox_one_wired_controller_15_6_0_0_macosx.conf @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Xbox One Wired Controller +platform = macosx + +[device] +make = Microsoft +model = Xbox One Pad +type = gamepad + +[sdl] +guid = 5e040000000000008e02000000000000 +buttons = 15 +hats = 0 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_11 = dpad_up +button_12 = dpad_down +button_13 = dpad_left +button_14 = dpad_right +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = lstick_button +button_7 = rstick_button +button_8 = start_button +button_9 = select_button diff --git a/src/fs-uae/paths.c b/src/fs-uae/paths.c index 2d6cf0e71..8fcb10ae8 100644 --- a/src/fs-uae/paths.c +++ b/src/fs-uae/paths.c @@ -162,22 +162,14 @@ static const char* fs_uae_base_dir(void) if (fs_path_exists(test)) { path = next; fs_log("using portable base dir %s\n", path); - next = NULL; + g_free(orig); break; } g_free(test); - if (orig != NULL) { - g_free(orig); - } + g_free(orig); orig = next; next = g_path_get_dirname(next); } - if (orig != NULL) { - g_free(orig); - } - if (next != NULL) { - g_free(next); - } } if (path == NULL) { path = read_custom_path("base-dir"); From 71af44e7a5a38d82086bfabcb55a982272b59025 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 15 Aug 2015 21:18:38 +0200 Subject: [PATCH 06/25] 2.5.39dev --- ChangeLog | 1 + configure.ac | 2 +- debian/changelog | 4 ++-- fs-uae.spec | 4 ++-- po/cs.po | 4 ++-- po/da.po | 20 ++++++++++---------- po/de.po | 12 ++++++------ po/el.po | 4 ++-- po/es.po | 4 ++-- po/fi.po | 4 ++-- po/fr.po | 8 ++++---- po/it.po | 4 ++-- po/nb.po | 4 ++-- po/pl.po | 4 ++-- po/pt.po | 4 ++-- po/pt_BR.po | 4 ++-- po/sr.po | 4 ++-- po/sv.po | 4 ++-- po/tr.po | 4 ++-- 19 files changed, 50 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index e907e4f31..41e7102bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Version 2.5.39dev: * Config files must end with .fs-uae or .conf to be loaded by FS-UAE. * If you give fs-uae a command line argument with path to a .adf, it will be used as value for floppy_drive_0. +* Imported updated translations from crowdin.com. Version 2.5.38dev: diff --git a/configure.ac b/configure.ac index 4b6fee464..a70f93602 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.67]) -AC_INIT([FS-UAE], [2.5.38dev], +AC_INIT([FS-UAE], [2.5.39dev], [frode@fs-uae.net], [fs-uae], [http://fs-uae.net]) AC_CONFIG_AUX_DIR([.]) AC_CANONICAL_HOST diff --git a/debian/changelog b/debian/changelog index 5fe26ee0a..a81a9425c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -fs-uae (2.5.38~dev-0) unstable; urgency=low +fs-uae (2.5.39~dev-0) unstable; urgency=low * Dummy changelog entry. - -- Frode Solheim Sun, 9 Aug 2015 19:05:44 +0200 + -- Frode Solheim Sat, 15 Aug 2015 21:18:14 +0200 diff --git a/fs-uae.spec b/fs-uae.spec index ca9977f83..300bd909d 100644 --- a/fs-uae.spec +++ b/fs-uae.spec @@ -1,6 +1,6 @@ %define name fs-uae -%define version 2.5.38dev -%define unmangled_version 2.5.38dev +%define version 2.5.39dev +%define unmangled_version 2.5.39dev %define release 1%{?dist} Summary: Amiga emulator with on-screen GUI and online play support diff --git a/po/cs.po b/po/cs.po index c12cd0cd7..58e3f039e 100644 --- a/po/cs.po +++ b/po/cs.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Czech\n" "Language: cs_CZ\n" diff --git a/po/da.po b/po/da.po index 329cc3715..d81489f9d 100644 --- a/po/da.po +++ b/po/da.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-15 15:15-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Danish\n" "Language: da_DK\n" @@ -169,28 +169,28 @@ msgid "Option \"%s\" is not enabled" msgstr "Indstilling \"%s\" er ikke aktiveret" msgid "Option chip_memory must be a multiple of 512" -msgstr "Indstilling chip_memory skal været et multiplicum af 512" +msgstr "Indstillingen chip_memory skal været et multiplicum af 512" msgid "Option fast_memory must be a multiple of 1024" -msgstr "Indstilling fast_memory skal været et multiplicum af 1024" +msgstr "Indstillingen fast_memory skal været et multiplicum af 1024" msgid "Option motherboard_ram must be a multiple of 1024" -msgstr "" +msgstr "Indstillingen motherboard_ram skal være et multiplum af 1024" msgid "Option motherboard_ram needs a CPU with 32-bit addressing" -msgstr "" +msgstr "Indstillingen motherboard_ram skal bruge en CPU med 32-bit adressering" msgid "Option slow_memory must be a multiple of 256" -msgstr "Indstilling slow_memory skal været et multiplicum af 256" +msgstr "Indstillingen slow_memory skal været et multiplicum af 256" msgid "Option uaegfx.card needs a CPU with 32-bit addressing" -msgstr "Indstilling uagfx.card kræver en CPU med 32-bits adressering" +msgstr "Indstillingen uagfx.card kræver en CPU med 32-bits adressering" msgid "Option zorro_iii_memory must be a multiple of 1024" -msgstr "Indstilling zorro_iii_memory skal været et multiplicum af 1024" +msgstr "Indstillingen zorro_iii_memory skal været et multiplicum af 1024" msgid "Option zorro_iii_memory needs a CPU with 32-bit addressing" -msgstr "Indstilling zorro_iii_memory kræver en CPU med 32-bits adressering" +msgstr "Indstillingen zorro_iii_memory kræver en CPU med 32-bits adressering" #. / TRANSLATORS: This is a menu entry and must not be too long msgid "Parallel Joystick Ports" diff --git a/po/de.po b/po/de.po index 46295b316..63c725733 100644 --- a/po/de.po +++ b/po/de.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-15 15:15-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: German\n" "Language: de_DE\n" @@ -74,7 +74,7 @@ msgstr "Emulator-Steuerung" #. / TRANSLATORS: In context "Zoom: Full Frame" msgid "Full Frame" -msgstr "Full Frame" +msgstr "Vollbild" #, c-format msgid "HD not found: %s" @@ -175,10 +175,10 @@ msgid "Option fast_memory must be a multiple of 1024" msgstr "Die Option fast_memory muss ein Vielfaches von 1024 sein" msgid "Option motherboard_ram must be a multiple of 1024" -msgstr "" +msgstr "Die Option motherboard_ram muss ein Vielfaches von 1024 betragen" msgid "Option motherboard_ram needs a CPU with 32-bit addressing" -msgstr "" +msgstr "Die Option Motherboard_ram benötigt eine CPU mit 32-Bit-Adressierung" msgid "Option slow_memory must be a multiple of 256" msgstr "Die Option slow_memory muss ein Vielfaches von 256 sein" @@ -241,7 +241,7 @@ msgstr "Zoom: %s" #, c-format msgid "Zoom: %s + Border" -msgstr "Zoom: %s + Begrenzung" +msgstr "Zoom: %s + Rand" msgid "[ Port 0 ] Switched to joystick mode" msgstr "[ Anschluss 0 ] Auf Joystick-Modus umgestellt" diff --git a/po/el.po b/po/el.po index 103c37669..502defd95 100644 --- a/po/el.po +++ b/po/el.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Greek\n" "Language: el_GR\n" diff --git a/po/es.po b/po/es.po index 406d35287..c0318f151 100644 --- a/po/es.po +++ b/po/es.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Spanish\n" "Language: es_ES\n" diff --git a/po/fi.po b/po/fi.po index ac9999bf5..5c8eab09e 100644 --- a/po/fi.po +++ b/po/fi.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 18:14+0200\n" -"PO-Revision-Date: 2015-08-09 12:15-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Finnish\n" "Language: fi_FI\n" diff --git a/po/fr.po b/po/fr.po index cb5b39040..ca67b9743 100644 --- a/po/fr.po +++ b/po/fr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: French\n" "Language: fr_FR\n" @@ -175,10 +175,10 @@ msgid "Option fast_memory must be a multiple of 1024" msgstr "L'option mémoire_fast doit être un multiple de 1024" msgid "Option motherboard_ram must be a multiple of 1024" -msgstr "" +msgstr "L'option motherboard_ram doit être un multiple de 1024" msgid "Option motherboard_ram needs a CPU with 32-bit addressing" -msgstr "" +msgstr "L'option motherboard_ram a besoin d'un processeur avec adressage 32 bits" msgid "Option slow_memory must be a multiple of 256" msgstr "L'option mémoire_slow doit être un multiple de 256" diff --git a/po/it.po b/po/it.po index 1d086aeca..cf886a103 100644 --- a/po/it.po +++ b/po/it.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Italian\n" "Language: it_IT\n" diff --git a/po/nb.po b/po/nb.po index e759d0bee..f0b033857 100644 --- a/po/nb.po +++ b/po/nb.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-15 15:16-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Norwegian Bokmal\n" "Language: nb_NO\n" diff --git a/po/pl.po b/po/pl.po index 0cf51a294..4813e3bb9 100644 --- a/po/pl.po +++ b/po/pl.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-15 15:15-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Polish\n" "Language: pl_PL\n" diff --git a/po/pt.po b/po/pt.po index 896cf2b3c..186435627 100644 --- a/po/pt.po +++ b/po/pt.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Portuguese\n" "Language: pt_PT\n" diff --git a/po/pt_BR.po b/po/pt_BR.po index e38dae78c..9fe23f681 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Portuguese, Brazilian\n" "Language: pt_BR\n" diff --git a/po/sr.po b/po/sr.po index 4141c2eab..da99487bb 100644 --- a/po/sr.po +++ b/po/sr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Serbian (Latin)\n" "Language: sr_CS\n" diff --git a/po/sv.po b/po/sv.po index 559ed3372..553289692 100644 --- a/po/sv.po +++ b/po/sv.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Swedish\n" "Language: sv_SE\n" diff --git a/po/tr.po b/po/tr.po index 7be36ff91..c38ce93bb 100644 --- a/po/tr.po +++ b/po/tr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-07 20:13+0200\n" -"PO-Revision-Date: 2015-08-08 12:23-0400\n" +"POT-Creation-Date: 2015-08-09 21:35+0200\n" +"PO-Revision-Date: 2015-08-10 14:41-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Turkish\n" "Language: tr_TR\n" From 4b850d33a489c87a70e8311c14ca0efb0f0bec64 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 21 Aug 2015 23:56:06 +0200 Subject: [PATCH 07/25] Added new option log_bsdsocket (boolean), some other updates --- ChangeLog | 4 ++ ISSUES | 2 + doc/options/log_bsdsocket | 4 ++ libfsemu/include/fs/lazyness.h | 3 ++ ...000000000000504944564944.fs-uae-controller | 23 +++++++++++ .../atari_controller_usb_1_2_0_0_windows.conf | 23 +++++++++++ src/bsdsocket.cpp | 2 +- src/fs-uae/main.c | 5 +++ src/fs-uae/options.h | 1 + src/include/bsdsocket.h | 2 +- src/od-fs/bsdsocket_posix.cpp | 38 +++++++++---------- 11 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 doc/options/log_bsdsocket create mode 100644 share/fs-uae/input/92125441000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/atari_controller_usb_1_2_0_0_windows.conf diff --git a/ChangeLog b/ChangeLog index 41e7102bd..84395b3f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Version 2.5.40dev: + +* Added new option log_bsdsocket (boolean). + Version 2.5.39dev: * Updated config for Logitech F310 and added Thrustmaster Dual Action 4. diff --git a/ISSUES b/ISSUES index f73ee3e35..eb39cd23a 100644 --- a/ISSUES +++ b/ISSUES @@ -1,3 +1,5 @@ * When entering the GUI using modifier+F12, the modifier key(s) sticks in the emulated Amiga when you return to the emulation. * Graphical flickering in Workbench with non-cycle-exact emulation. +* uae_rtc option does not have any effect on A1200 model, probably reset + by compatible chipset setting (adding memory expansion is a workaround). diff --git a/doc/options/log_bsdsocket b/doc/options/log_bsdsocket new file mode 100644 index 000000000..9988a9b00 --- /dev/null +++ b/doc/options/log_bsdsocket @@ -0,0 +1,4 @@ +Summary: +Type: boolean +Default: 0 +Example: 1 diff --git a/libfsemu/include/fs/lazyness.h b/libfsemu/include/fs/lazyness.h index 78d61be00..7b74a240b 100644 --- a/libfsemu/include/fs/lazyness.h +++ b/libfsemu/include/fs/lazyness.h @@ -3,4 +3,7 @@ extern int g_fs_log_input; +/* bsdsocket.h (uae) */ +extern int log_bsd; + #endif /* FS_LAZYNESS_H */ diff --git a/share/fs-uae/input/92125441000000000000504944564944.fs-uae-controller b/share/fs-uae/input/92125441000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..20c5a7ef4 --- /dev/null +++ b/share/fs-uae/input/92125441000000000000504944564944.fs-uae-controller @@ -0,0 +1,23 @@ +[fs-uae-controller] +name = ATARI Controller USB +platform = windows + +[device] +make = Retro-bit +model = Atari Adapter +type = joystick + +[sdl] +guid = 92125441000000000000504944564944 +buttons = 1 +hats = 0 +axes = 2 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = dpad_left +axis_0_pos = dpad_right +axis_1_neg = dpad_up +axis_1_pos = dpad_down +button_0 = south_button diff --git a/share/fs-uae/input/atari_controller_usb_1_2_0_0_windows.conf b/share/fs-uae/input/atari_controller_usb_1_2_0_0_windows.conf new file mode 100644 index 000000000..20c5a7ef4 --- /dev/null +++ b/share/fs-uae/input/atari_controller_usb_1_2_0_0_windows.conf @@ -0,0 +1,23 @@ +[fs-uae-controller] +name = ATARI Controller USB +platform = windows + +[device] +make = Retro-bit +model = Atari Adapter +type = joystick + +[sdl] +guid = 92125441000000000000504944564944 +buttons = 1 +hats = 0 +axes = 2 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = dpad_left +axis_0_pos = dpad_right +axis_1_neg = dpad_up +axis_1_pos = dpad_down +button_0 = south_button diff --git a/src/bsdsocket.cpp b/src/bsdsocket.cpp index bc9f5c306..f81124454 100644 --- a/src/bsdsocket.cpp +++ b/src/bsdsocket.cpp @@ -43,7 +43,7 @@ Bit iotextptrs are never initialized. Instead, there this this initalization usi #endif #ifdef BSDSOCKET -int log_bsd; +int log_bsd = 0; struct socketbase *socketbases; static uae_u32 SockLibBase; diff --git a/src/fs-uae/main.c b/src/fs-uae/main.c index 3b56ca021..4e3e7ba68 100644 --- a/src/fs-uae/main.c +++ b/src/fs-uae/main.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -840,6 +841,10 @@ extern int inputdevice_logging; static void configure_logging(const char *logstr) { + if (fs_config_get_int(OPTION_LOG_BSDSOCKET) == 1) { + log_bsd = 1; + } + if (!logstr) { fs_log("configure logging: none\n"); return; diff --git a/src/fs-uae/options.h b/src/fs-uae/options.h index 476c46915..18dc87147 100644 --- a/src/fs-uae/options.h +++ b/src/fs-uae/options.h @@ -26,6 +26,7 @@ #define OPTION_JOYSTICK_PORT_0_AUTOSWITCH "joystick_port_0_autoswitch" #define OPTION_LINE_DOUBLING "line_doubling" #define OPTION_LOG_AUTOSCALE "log_autoscale" +#define OPTION_LOG_BSDSOCKET "log_bsdsocket" #define OPTION_LOW_RESOLUTION "low_resolution" #define OPTION_MOTHERBOARD_RAM "motherboard_ram" #define OPTION_MMU "mmu" diff --git a/src/include/bsdsocket.h b/src/include/bsdsocket.h index ea7cfa5f2..cce73914d 100644 --- a/src/include/bsdsocket.h +++ b/src/include/bsdsocket.h @@ -219,4 +219,4 @@ void bsdsock_fake_int_handler(void); extern int volatile bsd_int_requested; -#endif // UAE_BSDSOCKET_H +#endif /* UAE_BSDSOCKET_H */ diff --git a/src/od-fs/bsdsocket_posix.cpp b/src/od-fs/bsdsocket_posix.cpp index 3b4255480..38134eaf2 100644 --- a/src/od-fs/bsdsocket_posix.cpp +++ b/src/od-fs/bsdsocket_posix.cpp @@ -40,7 +40,8 @@ volatile int bsd_int_requested; -void bsdsock_fake_int_handler(void) { +void bsdsock_fake_int_handler(void) +{ STUB(""); } @@ -61,12 +62,10 @@ void bsdsock_fake_int_handler(void) { #include #include -//#define DEBUG_BSDSOCKET -#ifdef DEBUG_BSDSOCKET -#define DEBUG_LOG write_log -#else -#define DEBUG_LOG(...) do ; while(0) -#endif +#define DEBUG_LOG(format, ...) \ + do { \ + if (log_bsd) write_log(format, ##__VA_ARGS__); \ + } while(0) #define WAITSIGNAL waitsig (context, sb) #ifdef ANDROID @@ -215,6 +214,10 @@ static int mapsockoptname (int level, int optname) return SO_DONTROUTE; case 0x0020: return SO_BROADCAST; +#if 0 + case 0x0023: + return SO_TIMESTAMPNS; +#endif #ifdef SO_USELOOPBACK case 0x0040: return SO_USELOOPBACK; @@ -245,8 +248,8 @@ static int mapsockoptname (int level, int optname) return SO_TYPE; default: - DEBUG_LOG ("Invalid setsockopt option %x for level %d\n", - optname, level); + DEBUG_LOG("Invalid setsockopt option 0x%x for level %d\n", + optname, level); return -1; } break; @@ -277,8 +280,8 @@ static int mapsockoptname (int level, int optname) return IP_ADD_MEMBERSHIP; default: - DEBUG_LOG ("Invalid setsockopt option %x for level %d\n", - optname, level); + DEBUG_LOG("Invalid setsockopt option 0x%x for level %d\n", + optname, level); return -1; } break; @@ -291,19 +294,18 @@ static int mapsockoptname (int level, int optname) return TCP_MAXSEG; default: - DEBUG_LOG ("Invalid setsockopt option %x for level %d\n", - optname, level); + DEBUG_LOG("Invalid setsockopt option 0x%x for level %d\n", + optname, level); return -1; } break; default: - DEBUG_LOG ("Unknown level %d\n", level); + DEBUG_LOG("Unknown level %d\n", level); return -1; } } - /* * Map amiga (s|g)etsockopt return value into the correct form */ @@ -489,16 +491,12 @@ STATIC_INLINE void bsd_amigaside_FD_SET (int n, uae_u32 set) put_long (set, get_long (set) | (1 << (n % 32))); } -#ifdef DEBUG_BSDSOCKET static void printSockAddr (struct sockaddr_in *in) { DEBUG_LOG ("Family %d, ", in->sin_family); DEBUG_LOG ("Port %d,", ntohs (in->sin_port)); DEBUG_LOG ("Address %s,", inet_ntoa (in->sin_addr)); } -#else -#define printSockAddr(sockAddr) -#endif /* * Copy a sockaddr object from amiga space to native space @@ -722,7 +720,7 @@ uae_u32 bsdthr_WaitSelect (SB) if (sb->sets [set] != 0) bsd_amigaside_FD_ZERO (sb->sets [set]); } - DEBUG_LOG ("WaitSelect: %d(%d)\n", r, errno); + DEBUG_LOG ("WaitSelect: r=%d errno=%d\n", r, errno); return r; } From 8fb5e174c7a75ee57dc1c67cc9af2d06fe6f628a Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 22 Aug 2015 01:33:37 +0200 Subject: [PATCH 08/25] small cleanups --- src/a2091.cpp | 4 ++-- src/blkdev_cdimage.cpp | 2 +- src/cd32_fmv.cpp | 2 +- src/include/cpuboard.h | 1 + src/ncr_scsi.cpp | 3 --- src/od-fs/stubs.cpp | 12 ++++++++---- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/a2091.cpp b/src/a2091.cpp index 551c2031a..213bd6e0c 100644 --- a/src/a2091.cpp +++ b/src/a2091.cpp @@ -3376,7 +3376,7 @@ void gvp_s2_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfi add_scsi_device(&wd->scsis[ch], ch, ci, rc); } -void a2091_free_device (struct wd_state *wd) +static void a2091_free_device (struct wd_state *wd) { freencrunit(wd); } @@ -3552,7 +3552,7 @@ addrbank *a2090_init (struct romconfig *rc) return wd->bank; } -void gvp_free_device (struct wd_state *wd) +static void gvp_free_device (struct wd_state *wd) { freencrunit(wd); } diff --git a/src/blkdev_cdimage.cpp b/src/blkdev_cdimage.cpp index e0c66b6eb..c5962b99b 100644 --- a/src/blkdev_cdimage.cpp +++ b/src/blkdev_cdimage.cpp @@ -435,7 +435,7 @@ static void audio_unpack (struct cdunit *cdu, struct cdtoc *t) static volatile int cda_bufon[2]; static cda_audio *cda; -void next_cd_audio_buffer_callback(int bufnum) +static void next_cd_audio_buffer_callback(int bufnum) { uae_sem_wait(&play_sem); if (bufnum >= 0) { diff --git a/src/cd32_fmv.cpp b/src/cd32_fmv.cpp index 949fbe80d..28f41abc8 100644 --- a/src/cd32_fmv.cpp +++ b/src/cd32_fmv.cpp @@ -1383,7 +1383,7 @@ void cd32_fmv_set_sync(double svpos, double adjust) fmv_syncadjust = adjust; } -void fmv_next_cd_audio_buffer_callback(int bufnum) +static void fmv_next_cd_audio_buffer_callback(int bufnum) { uae_sem_wait(&play_sem); if (bufnum >= 0) { diff --git a/src/include/cpuboard.h b/src/include/cpuboard.h index 76660cc44..5f0cc35fe 100644 --- a/src/include/cpuboard.h +++ b/src/include/cpuboard.h @@ -34,6 +34,7 @@ extern int REGPARAM3 cyberstorm_scsi_ram_check(uaecptr addr, uae_u32 size) REGPA extern uae_u8 *REGPARAM3 cyberstorm_scsi_ram_xlate(uaecptr addr) REGPARAM; void cyberstorm_irq(int level); +void cyberstorm_mk3_ppc_irq(int level); void blizzardppc_irq(int level); #define BOARD_MEMORY_Z2 1 diff --git a/src/ncr_scsi.cpp b/src/ncr_scsi.cpp index 3b51c2da0..39172633b 100644 --- a/src/ncr_scsi.cpp +++ b/src/ncr_scsi.cpp @@ -161,9 +161,6 @@ static struct ncr_state *ncr_we; static struct ncr_state *ncr_a4000t; static struct ncr_state *ncra4091[MAX_DUPLICATE_EXPANSION_BOARDS]; -extern void cyberstorm_mk3_ppc_irq(int); -extern void blizzardppc_irq(int); - static void set_irq2(int level) { if (level) diff --git a/src/od-fs/stubs.cpp b/src/od-fs/stubs.cpp index ffbc509d8..7f045bc32 100644 --- a/src/od-fs/stubs.cpp +++ b/src/od-fs/stubs.cpp @@ -132,16 +132,20 @@ bool vsync_switchmode (int hz) { } #ifndef AHI -void ahi_hsync (void) { + +#include "uae/ahi.h" + +void ahi_hsync (void) +{ VERBOSE_STUB(""); } -#endif -#ifndef AHI -int enforcer_disable(void) { +int enforcer_disable(void) +{ STUB(""); return 1; } + #endif void refreshtitle (void) { From d1f62b49e44cf6e82278f2c7637d275400c41a44 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Mon, 24 Aug 2015 21:26:22 +0200 Subject: [PATCH 09/25] Fix undefined behavior (shift count == bit length) when delay is 0 --- ChangeLog | 1 + configure.ac | 1 + src/custom.cpp | 30 ++++++++++++++++++++++++++++++ src/include/uae/types.h | 6 +++++- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 84395b3f6..40110e851 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.40dev: +* Fixed flickering caused by undefined behavior in shift operations. * Added new option log_bsdsocket (boolean). Version 2.5.39dev: diff --git a/configure.ac b/configure.ac index a70f93602..62ecece4e 100644 --- a/configure.ac +++ b/configure.ac @@ -349,6 +349,7 @@ AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T +AC_CHECK_TYPES([__uint128_t]) AC_TYPE_LONG_LONG_INT AC_CHECK_SIZEOF(int) diff --git a/src/custom.cpp b/src/custom.cpp index 704ae4300..8c04e6272 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -1954,6 +1954,8 @@ STATIC_INLINE void long_fetch_32 (int plane, int nwords, int weird_number_of_bit outword[plane] = outval; } +#ifndef HAVE_UAE_U128 + STATIC_INLINE void shift32plus (uae_u64 *p, int n) { uae_u64 t = p[1]; @@ -1964,6 +1966,7 @@ STATIC_INLINE void shift32plus (uae_u64 *p, int n) STATIC_INLINE void aga_shift (uae_u64 *p, int n) { + if (n == 0) return; shift32plus (p, n); p[0] <<= n; } @@ -1978,16 +1981,23 @@ STATIC_INLINE void shift32plusn (uae_u64 *p, int n) STATIC_INLINE void aga_shift_n (uae_u64 *p, int n) { + if (n == 0) return; shift32plusn (p, n); p[1] >>= n; } +#endif + STATIC_INLINE void long_fetch_64 (int plane, int nwords, int weird_number_of_bits, int dma) { uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane], nwords * 2); int delay = toscr_delay_adjusted[plane & 1]; int tmp_nbits = out_nbits; +#ifdef HAVE_UAE_U128 + uae_u128 shiftbuffer; +#else uae_u64 shiftbuffer[2]; +#endif uae_u32 outval = outword[plane]; uae_u64 fetchval = fetched_aga[plane]; uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs); @@ -2002,19 +2012,30 @@ STATIC_INLINE void long_fetch_64 (int plane, int nwords, int weird_number_of_bit /* @@@ Don't do this, fall back on chipmem_wget instead. */ return; +#ifdef HAVE_UAE_U128 + shiftbuffer = todisplay2_aga[plane] << delay; +#else shiftbuffer[1] = 0; shiftbuffer[0] = todisplay2_aga[plane]; aga_shift (shiftbuffer, delay); +#endif while (nwords > 0) { int i; +#ifdef HAVE_UAE_U128 + shiftbuffer |= fetchval; +#else shiftbuffer[0] |= fetchval; +#endif for (i = 0; i < 4; i++) { uae_u32 t; int bits_left = 32 - tmp_nbits; +#ifdef HAVE_UAE_U128 + t = (shiftbuffer >> shift) & 0xffff; +#else if (64 - shift > 0) { t = shiftbuffer[1] << (64 - shift); t |= shiftbuffer[0] >> shift; @@ -2022,6 +2043,7 @@ STATIC_INLINE void long_fetch_64 (int plane, int nwords, int weird_number_of_bit t = shiftbuffer[1] >> (shift - 64); } t &= 0xffff; +#endif if (weird_number_of_bits && bits_left < 16) { outval <<= bits_left; @@ -2041,7 +2063,11 @@ STATIC_INLINE void long_fetch_64 (int plane, int nwords, int weird_number_of_bit tmp_nbits = 0; } } +#ifdef HAVE_UAE_U128 + shiftbuffer <<= 16; +#else aga_shift (shiftbuffer, 16); +#endif } nwords -= 4; @@ -2057,8 +2083,12 @@ STATIC_INLINE void long_fetch_64 (int plane, int nwords, int weird_number_of_bit } } fetched_aga[plane] = fetchval; +#ifdef HAVE_UAE_U128 + todisplay2_aga[plane] = shiftbuffer >> delay; +#else aga_shift_n (shiftbuffer, delay); todisplay2_aga[plane] = shiftbuffer[0]; +#endif outword[plane] = outval; } #endif diff --git a/src/include/uae/types.h b/src/include/uae/types.h index e8193a005..b7162f249 100644 --- a/src/include/uae/types.h +++ b/src/include/uae/types.h @@ -34,11 +34,15 @@ typedef uint32_t uae_u32; #ifndef uae_s64 typedef long long int uae_s64; #endif - #ifndef uae_u64 typedef unsigned long long int uae_u64; #endif +#ifdef HAVE___UINT128_T +#define HAVE_UAE_U128 +typedef __uint128_t uae_u128; +#endif + /* Parts of the UAE/WinUAE code uses the bool type (from C++). * Including stdbool.h lets this be valid also when compiling with C. */ From 0dc69d3e0360950fbe0339e7d55cdc5c1cd4a43f Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 28 Aug 2015 21:13:15 +0200 Subject: [PATCH 10/25] Allow uae_rtc to be set without disabling uae_chipset_compatible --- ChangeLog | 1 + ISSUES | 3 --- README | 2 +- libfsemu/README | 2 +- src/cfgfile.cpp | 4 ++++ 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 40110e851..07184754c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.40dev: +* Allow uae_rtc to be set without disabling uae_chipset_compatible. * Fixed flickering caused by undefined behavior in shift operations. * Added new option log_bsdsocket (boolean). diff --git a/ISSUES b/ISSUES index eb39cd23a..c9ea8ec8d 100644 --- a/ISSUES +++ b/ISSUES @@ -1,5 +1,2 @@ * When entering the GUI using modifier+F12, the modifier key(s) sticks in the emulated Amiga when you return to the emulation. -* Graphical flickering in Workbench with non-cycle-exact emulation. -* uae_rtc option does not have any effect on A1200 model, probably reset - by compatible chipset setting (adding memory expansion is a workaround). diff --git a/README b/README index 50aa22278..834e5cf90 100644 --- a/README +++ b/README @@ -256,7 +256,7 @@ in the floppy list, some may be obscured. COPYRIGHT AND CREDITS ===================== -FS-UAE is Copyright (c) 2011-2014, Frode Solheim +FS-UAE is Copyright (c) 2011-2015, Frode Solheim Large portions are copyrighted by other individuals. FS-UAE is based on the fantastic work of the original UAE authors, the authors diff --git a/libfsemu/README b/libfsemu/README index 5bf0c0f6f..40108a019 100644 --- a/libfsemu/README +++ b/libfsemu/README @@ -1,4 +1,4 @@ -libfsemu is Copyright (c) 2011-2014, Frode Solheim, licensed under the +libfsemu is Copyright (c) 2011-2015, Frode Solheim, licensed under the terms of the GNU Lesser General Public License (See COPYING). diff --git a/src/cfgfile.cpp b/src/cfgfile.cpp index aecabe75e..37bac6ed9 100644 --- a/src/cfgfile.cpp +++ b/src/cfgfile.cpp @@ -6982,7 +6982,11 @@ int built_in_chipset_prefs (struct uae_prefs *p) p->cs_ksmirror_a8 = 0; p->cs_ciaoverlay = 1; p->cs_ciaatod = 0; +#ifdef FSUAE + /* Allow RTC to be set without disabling cs_compatible */ +#else p->cs_rtc = 0; +#endif p->cs_rtc_adjust_mode = p->cs_rtc_adjust = 0; p->cs_df0idhw = 1; p->cs_resetwarning = 1; From 8a7e751e8a1686522ea38268fb6e9f2d23385787 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 28 Aug 2015 21:14:24 +0200 Subject: [PATCH 11/25] Re-enable uae_comp_trust* = indirectKS options --- ChangeLog | 1 + src/jit/compemu_support.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 07184754c..1632f5826 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.40dev: +* Re-enable uae_comp_trust* = indirectKS options. * Allow uae_rtc to be set without disabling uae_chipset_compatible. * Fixed flickering caused by undefined behavior in shift operations. * Added new option log_bsdsocket (boolean). diff --git a/src/jit/compemu_support.cpp b/src/jit/compemu_support.cpp index 8d832abe7..275095fe1 100644 --- a/src/jit/compemu_support.cpp +++ b/src/jit/compemu_support.cpp @@ -5015,7 +5015,7 @@ STATIC_INLINE void writemem(int address, int source, int offset, int size, int t void writebyte(int address, int source, int tmp) { int distrust = currprefs.comptrustbyte; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustbyte) { case 0: distrust=0; break; case 1: distrust=1; break; @@ -5034,7 +5034,7 @@ STATIC_INLINE void writeword_general(int address, int source, int tmp, int clobber) { int distrust = currprefs.comptrustword; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustword) { case 0: distrust=0; break; case 1: distrust=1; break; @@ -5063,7 +5063,7 @@ STATIC_INLINE void writelong_general(int address, int source, int tmp, int clobber) { int distrust = currprefs.comptrustlong; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustlong) { case 0: distrust=0; break; case 1: distrust=1; break; @@ -5145,7 +5145,7 @@ STATIC_INLINE void readmem(int address, int dest, int offset, int size, int tmp) void readbyte(int address, int dest, int tmp) { int distrust = currprefs.comptrustbyte; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustbyte) { case 0: distrust=0; break; case 1: distrust=1; break; @@ -5163,7 +5163,7 @@ void readbyte(int address, int dest, int tmp) void readword(int address, int dest, int tmp) { int distrust = currprefs.comptrustword; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustword) { case 0: distrust=0; break; case 1: distrust=1; break; @@ -5181,7 +5181,7 @@ void readword(int address, int dest, int tmp) void readlong(int address, int dest, int tmp) { int distrust = currprefs.comptrustlong; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustlong) { case 0: distrust=0; break; case 1: distrust=1; break; @@ -5228,7 +5228,7 @@ STATIC_INLINE void get_n_addr_real(int address, int dest, int tmp) void get_n_addr(int address, int dest, int tmp) { int distrust = currprefs.comptrustnaddr; -#if 0 +#ifdef FSUAE switch (currprefs.comptrustnaddr) { case 0: distrust=0; break; case 1: distrust=1; break; From b3e64e2660c8100e1868b1d58e219383edbbd45c Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Mon, 31 Aug 2015 18:29:45 +0200 Subject: [PATCH 12/25] Fixed mman for compatibility with JIT direct memory access --- ChangeLog | 1 + Makefile.am | 3 +- src/od-fs/mman.cpp | 188 ++++++++++++++++++++++++++++++++++++++++++ src/od-win32/mman.cpp | 180 ++-------------------------------------- 4 files changed, 198 insertions(+), 174 deletions(-) create mode 100644 src/od-fs/mman.cpp diff --git a/ChangeLog b/ChangeLog index 1632f5826..5d5acc97c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.40dev: +* Fixed mman for compatibility with JIT direct memory access. * Re-enable uae_comp_trust* = indirectKS options. * Allow uae_rtc to be set without disabling uae_chipset_compatible. * Fixed flickering caused by undefined behavior in shift operations. diff --git a/Makefile.am b/Makefile.am index 02ac4e52a..657664cde 100644 --- a/Makefile.am +++ b/Makefile.am @@ -441,6 +441,7 @@ libuae_a_SOURCES = \ src/od-fs/machdep/ppc/maccess.h \ src/od-fs/machdep/rpt.h \ src/od-fs/machdep/x86/maccess.h \ + src/od-fs/mman.cpp \ src/od-fs/mouse.cpp \ src/od-fs/mp3decoder.h \ src/od-fs/parser.cpp \ @@ -467,7 +468,6 @@ libuae_a_SOURCES = \ src/od-win32/debug_win32.h \ src/od-win32/dxwrap.h \ src/od-win32/md-fpp.h \ - src/od-win32/mman.cpp \ src/od-win32/parser.h \ src/od-win32/picasso96_win.cpp \ src/od-win32/picasso96_win.h \ @@ -1163,6 +1163,7 @@ EXTRA_DIST = $(TESTS) $(EXTRA_TESTS) \ src/jit/compemu_raw_x86.cpp \ src/od-fs/bsdsocket_posix.cpp \ src/od-win32/bsdsock.cpp \ + src/od-win32/mman.cpp \ src/p96_blit.cpp \ src/sinctable.cpp \ src/table68k \ diff --git a/src/od-fs/mman.cpp b/src/od-fs/mman.cpp new file mode 100644 index 000000000..4eb58389e --- /dev/null +++ b/src/od-fs/mman.cpp @@ -0,0 +1,188 @@ +#include "sysconfig.h" +#include "sysdeps.h" +#include "uae/memory.h" +#include "uae/mman.h" +#include "options.h" +#include "autoconf.h" +#include "gfxboard.h" +#include "cpuboard.h" +#include "rommgr.h" +#include "newcpu.h" + +#ifdef __x86_64__ +static int os_64bit = 1; +#else +static int os_64bit = 0; +#endif + +#ifndef _WIN32 + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#if defined(__APPLE__) +#include +#endif +#include + +#define MEM_COMMIT 0x00001000 +#define MEM_RESERVE 0x00002000 +#define MEM_DECOMMIT 0x4000 +#define MEM_RELEASE 0x8000 +#define MEM_WRITE_WATCH 0x00200000 +#define MEM_TOP_DOWN 0x00100000 + +#define PAGE_EXECUTE_READWRITE 0x40 +#define PAGE_READONLY 0x02 +#define PAGE_READWRITE 0x04 + +typedef void * LPVOID; +typedef size_t SIZE_T; + +typedef struct { + int dwPageSize; +} SYSTEM_INFO; + +static void GetSystemInfo(SYSTEM_INFO *si) +{ + si->dwPageSize = sysconf(_SC_PAGESIZE); +} + +#define USE_MMAP + +#ifdef USE_MMAP +#ifdef MACOSX +#define MAP_ANONYMOUS MAP_ANON +#endif +#endif + +static void *VirtualAlloc(void *lpAddress, size_t dwSize, int flAllocationType, + int flProtect) +{ + write_log("- VirtualAlloc addr=%p size=%zu type=%d prot=%d\n", + lpAddress, dwSize, flAllocationType, flProtect); + if (flAllocationType & MEM_RESERVE) { + write_log(" MEM_RESERVE\n"); + } + if (flAllocationType & MEM_COMMIT) { + write_log(" MEM_COMMIT\n"); + } + if (flAllocationType & PAGE_READWRITE) { + write_log(" PAGE_READWRITE\n"); + } + int prot = 0; + if (flProtect == PAGE_READWRITE) { + write_log(" PAGE_READWRITE\n"); + prot = PROT_READ | PROT_WRITE; + } else if (flProtect == PAGE_READONLY) { + write_log(" PAGE_READONLY\n"); + prot = PROT_READ; + } else if (flProtect == PAGE_EXECUTE_READWRITE) { + write_log(" PAGE_EXECUTE_READWRITE\n"); + prot = PROT_READ | PROT_WRITE | PROT_EXEC; + } else { + write_log(" WARNING: unknown protection\n"); + } + + void *memory = NULL; + + if (flAllocationType == MEM_COMMIT && lpAddress == NULL) { + assert(false); + memory = malloc(dwSize); + if (memory == NULL) { + write_log("memory allocated failed errno %d\n", errno); + } + return memory; + } + + if (flAllocationType & MEM_RESERVE) { +#ifdef USE_MMAP + memory = mmap(lpAddress, dwSize, 0, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (memory == (void *) -1) { + write_log("mmap failed errno %d\n", errno); + } +#else + memory = malloc(dwSize); + if (memory == NULL) { + write_log("memory allocated failed errno %d\n", errno); + } +#endif + } + else { + memory = lpAddress; + } + + if (flAllocationType & MEM_COMMIT) { +#ifdef USE_MMAP + if (mprotect(memory, dwSize, prot) != 0) { + write_log("mprotect failed errno %d\n", errno); + } +#endif + } + + return memory; +} + +static int VirtualProtect(void *lpAddress, int dwSize, int flNewProtect, + unsigned int *lpflOldProtect) +{ + write_log("- VirtualProtect addr=%p size=%zu prot=%d\n", + lpAddress, dwSize, flNewProtect); + int prot = 0; + if (flNewProtect == PAGE_READWRITE) { + write_log(" PAGE_READWRITE\n"); + prot = PROT_READ | PROT_WRITE; + } else if (flNewProtect == PAGE_READONLY) { + write_log(" PAGE_READONLY\n"); + prot = PROT_READ; + } else { + write_log(" -- unknown protection --\n"); + } + if (mprotect(lpAddress, dwSize, prot) != 0) { + write_log("mprotect failed errno %d\n", errno); + return 0; + } + return 1; +} + +static bool VirtualFree(void *lpAddress, size_t dwSize, int dwFreeType) +{ +#ifdef MMAP + int result = 0; + if (dwFreeType == MEM_DECOMMIT) { + if (mprotect(lpAddress, dwSize, 0) != 0) { + write_log("mprotect failed errno %d\n", errno); + return 0; + } + } + else if (dwFreeType == MEM_RELEASE) { + result = munmap(lpAddress, dwSize); + if (result != 0) { + printf("munmap failed\n"); + } + return result == 0; + } + return 0; +#else + return 1; +#endif +} + +static int GetLastError() +{ + return errno; +} + +static int my_getpagesize (void) +{ + return sysconf(_SC_PAGESIZE); +} + +#define getpagesize my_getpagesize + +#endif + +/* Prevent od-win32/win32.h from being included */ +#define __WIN32_H__ + +#include "../od-win32/mman.cpp" diff --git a/src/od-win32/mman.cpp b/src/od-win32/mman.cpp index 68bbd91e7..3baba125e 100644 --- a/src/od-win32/mman.cpp +++ b/src/od-win32/mman.cpp @@ -2,13 +2,6 @@ // Copyright (C) 2000, Brian King // GNU Public License -#ifdef FSUAE // NL -#ifdef WINDOWS -#define _WIN32_WINNT 0x0501 -#include -#endif -#endif - #include #include "sysconfig.h" @@ -22,161 +15,6 @@ #include "rommgr.h" #include "newcpu.h" -#ifdef FSUAE // NL - -#ifdef __x86_64__ -static int os_64bit = 1; -#else -static int os_64bit = 0; -#endif - -#ifdef WINDOWS - -#else - -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#if defined(__APPLE__) -#include -#endif -#include - -#define MEM_COMMIT 0x00001000 -#define MEM_RESERVE 0x00002000 -#define MEM_DECOMMIT 0x4000 -#define MEM_RELEASE 0x8000 -#define MEM_WRITE_WATCH 0x00200000 -#define MEM_TOP_DOWN 0x00100000 - -#define PAGE_EXECUTE 0x10 -#define PAGE_EXECUTE_READ 0x20 -#define PAGE_EXECUTE_READWRITE 0x40 -#define PAGE_EXECUTE_WRITECOPY 0x80 -#define PAGE_NOACCESS 0x01 -#define PAGE_READONLY 0x02 -#define PAGE_READWRITE 0x04 -#define PAGE_WRITECOPY 0x08 - -typedef void * LPVOID; -typedef size_t SIZE_T; - -typedef struct { - int dwPageSize; -} SYSTEM_INFO; - -static void GetSystemInfo(SYSTEM_INFO *si) { - si->dwPageSize = sysconf(_SC_PAGESIZE); -} - -static void *VirtualAlloc(void *lpAddress, size_t dwSize, int flAllocationType, - int flProtect) { - write_log("- VirtualAlloc %p %zu %d %d\n", lpAddress, dwSize, - flAllocationType, flProtect); - if (flAllocationType & MEM_RESERVE) { - write_log(" MEM_RESERVE\n"); - } - if (flAllocationType & MEM_COMMIT) { - write_log(" MEM_COMMIT\n"); - } - if (flAllocationType & PAGE_READWRITE) { - write_log(" PAGE_READWRITE\n"); - } - int prot = 0; - void *memory = NULL; - - if (flAllocationType == MEM_COMMIT && lpAddress == NULL) { - memory = malloc(dwSize); - if (memory == NULL) { - write_log("memory allocated failed errno %d\n", errno); - } - return memory; - } - - if (flAllocationType & MEM_RESERVE) { - memory = malloc(dwSize); - if (memory == NULL) { - write_log("memory allocated failed errno %d\n", errno); - } -#if 0 - memory = mmap(lpAddress, dwSize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - printf("mmap result: %p\n", memory); - if (memory == (void *) -1) { - printf("mmap failed errno %d\n", errno); - } -#endif - } - else { - memory = lpAddress; - } - - if (flAllocationType & MEM_COMMIT) { -#if 0 - int lockresult = mlock(memory, dwSize); - if (lockresult != 0) { - printf("mlock failed errno %d\n", errno); - perror("mlock failed"); - } -#endif - } - - return memory; -} - -static bool VirtualFree(void *lpAddress, size_t dwSize, int dwFreeType) { -#if 0 - int result = 0; - if (dwFreeType == MEM_DECOMMIT) { - result = munlock(lpAddress, dwSize); - if (result != 0) { - printf("munlock failed %d\n", errno); - } - } - else if (dwFreeType == MEM_RELEASE) { - result = munmap(lpAddress, dwSize); - if (result != 0) { - printf("mlock failed\n"); - } - } - return result == 0; -#endif - return 1; -} - -static int GetLastError() { - return errno; -} - -#if 0 -#ifdef HAVE_POSIX_MEMALIGN -// FIXME: Set HAVE_POSIX_MEMALIGN when available in config.h, -// possibly via autoconf -#define valloc my_valloc - -static void *my_valloc(size_t size) { - size_t alignment = sysconf(_SC_PAGESIZE); - void *memptr = NULL; - if (posix_memalign(&memptr, alignment, size) == 0) { - return memptr; - } - return NULL; -} - -#endif -#endif - -static int my_getpagesize (void) { - return sysconf(_SC_PAGESIZE); -} - -#define getpagesize my_getpagesize - -#endif - -#else -#include "win32.h" -#endif - #if defined(NATMEM_OFFSET) uae_u32 max_z3fastmem; @@ -212,7 +50,7 @@ static void virtualfreewithlock (LPVOID addr, SIZE_T size, DWORD freetype) void cache_free (uae_u8 *cache) { -#ifdef WINDOWS +#ifdef _WIN32 virtualfreewithlock (cache, 0, MEM_RELEASE); #else // FIXME: Must add (address, size) to a list in cache_alloc, so the memory @@ -225,7 +63,7 @@ void cache_free (uae_u8 *cache) uae_u8 *cache_alloc (int size) { printf("cache_alloc size = %d\n", size); -#ifdef WINDOWS +#ifdef _WIN32 return virtualallocwithlock (NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else size = size < getpagesize() ? getpagesize() : size; @@ -286,7 +124,7 @@ void mman_ResetWatch (PVOID lpBaseAddress, SIZE_T dwRegionSize) #endif static uae_u64 size64; -#ifdef WINDOWS +#ifdef _WIN32 typedef BOOL (CALLBACK* GLOBALMEMORYSTATUSEX)(LPMEMORYSTATUSEX); #endif @@ -304,7 +142,7 @@ bool preinit_shm (void) write_log("preinit_shm\n"); uae_u64 total64; uae_u64 totalphys64; -#ifdef WINDOWS +#ifdef _WIN32 MEMORYSTATUS memstats; GLOBALMEMORYSTATUSEX pGlobalMemoryStatusEx; MEMORYSTATUSEX memstatsex; @@ -312,7 +150,7 @@ bool preinit_shm (void) uae_u32 max_allowed_mman; if (natmem_offset_allocated) -#ifdef WINDOWS +#ifdef _WIN32 VirtualFree (natmem_offset_allocated, 0, MEM_RELEASE); #else free (natmem_offset_allocated); @@ -320,7 +158,7 @@ bool preinit_shm (void) natmem_offset_allocated = NULL; natmem_offset = NULL; if (p96mem_offset) -#ifdef WINDOWS +#ifdef _WIN32 VirtualFree (p96mem_offset, 0, MEM_RELEASE); #else // Don't free p96mem_offset - it is freed as part of natmem_offset @@ -343,7 +181,7 @@ bool preinit_shm (void) if (maxmem > max_allowed_mman) max_allowed_mman = maxmem; -#ifdef WINDOWS +#ifdef _WIN32 memstats.dwLength = sizeof(memstats); GlobalMemoryStatus(&memstats); totalphys64 = memstats.dwTotalPhys; @@ -1040,14 +878,12 @@ void unprotect_maprom (void) if (shm->maprom <= 0) continue; shm->maprom = -1; -#ifdef WINDOWS DWORD old; if (!VirtualProtect (shm->attached, shm->rosize, protect ? PAGE_READONLY : PAGE_READWRITE, &old)) { write_log (_T("unprotect_maprom VP %08X - %08X %x (%dk) failed %d\n"), (uae_u8*)shm->attached - natmem_offset, (uae_u8*)shm->attached - natmem_offset + shm->size, shm->size, shm->size >> 10, GetLastError ()); } -#endif } } @@ -1066,14 +902,12 @@ void protect_roms (bool protect) continue; if (shm->maprom < 0 && protect) continue; -#ifdef WINDOWS DWORD old; if (!VirtualProtect (shm->attached, shm->rosize, protect ? PAGE_READONLY : PAGE_READWRITE, &old)) { write_log (_T("protect_roms VP %08X - %08X %x (%dk) failed %d\n"), (uae_u8*)shm->attached - natmem_offset, (uae_u8*)shm->attached - natmem_offset + shm->size, shm->size, shm->size >> 10, GetLastError ()); } -#endif } } From 26e19079c2f2a32bf6f7229430196cee9c1ff61a Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Mon, 31 Aug 2015 18:30:30 +0200 Subject: [PATCH 13/25] JIT: move exception handler into new exception_handler.cpp --- src/jit/compemu_raw_x86.cpp | 602 +-------------------------------- src/jit/exception_handler.cpp | 605 ++++++++++++++++++++++++++++++++++ 2 files changed, 608 insertions(+), 599 deletions(-) create mode 100644 src/jit/exception_handler.cpp diff --git a/src/jit/compemu_raw_x86.cpp b/src/jit/compemu_raw_x86.cpp index 4d5413edb..c02aadb0d 100644 --- a/src/jit/compemu_raw_x86.cpp +++ b/src/jit/compemu_raw_x86.cpp @@ -1685,611 +1685,15 @@ STATIC_INLINE void raw_inc_sp(int off) raw_add_l_ri(4,off); } + /************************************************************************* * Handling mistaken direct memory access * *************************************************************************/ - -#ifdef NATMEM_OFFSET -#ifdef _WIN32 // %%% BRIAN KING WAS HERE %%% -#include -#else -#ifndef __USE_GNU -#define __USE_GNU -#endif -#include -#endif -#include - -#define SIG_READ 1 -#define SIG_WRITE 2 - -static int in_handler=0; -static uae_u8 *veccode; - -#ifdef _WIN32 - -#if defined(CPU_64_BIT) -#define ctxPC (pContext->Rip) -#else -#define ctxPC (pContext->Eip) -#endif - -int EvalException (LPEXCEPTION_POINTERS blah, int n_except) -{ - PEXCEPTION_RECORD pExceptRecord = NULL; - PCONTEXT pContext = NULL; - - uae_u8* i = NULL; - uae_u32 addr = 0; - int r=-1; - int size=4; - int dir=-1; - int len=0; - - if (n_except != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) - return EXCEPTION_CONTINUE_SEARCH; - - pExceptRecord = blah->ExceptionRecord; - pContext = blah->ContextRecord; - - if (pContext) - i = (uae_u8 *)ctxPC; - if (pExceptRecord) - addr = (uae_u32)(pExceptRecord->ExceptionInformation[1]); -#ifdef JIT_DEBUG - write_log (_T("JIT: fault address is 0x%x at 0x%x\n"),addr,i); -#endif - if (!canbang || !currprefs.cachesize) - return EXCEPTION_CONTINUE_SEARCH; - - if (in_handler) - write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); - - if (canbang && i>=compiled_code && i<=current_compile_p) { - if (*i==0x66) { - i++; - size=2; - len++; - } - - switch(i[0]) { - case 0x8a: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - size=1; - len+=6; - break; - } - break; - case 0x88: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - size=1; - len+=6; - break; - } - break; - case 0x8b: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=2; - break; - default: - break; - } - break; - case 0x89: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=2; - break; - } - break; - } - } - - if (r!=-1) { - void* pr=NULL; -#ifdef JIT_DEBUG - write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); -#endif - - switch(r) { -#if defined(CPU_64_BIT) - case 0: pr=&(pContext->Rax); break; - case 1: pr=&(pContext->Rcx); break; - case 2: pr=&(pContext->Rdx); break; - case 3: pr=&(pContext->Rbx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Rax))+1); break; - case 5: pr=(size>1)? - (void*)(&(pContext->Rbp)): - (void*)(((uae_u8*)&(pContext->Rcx))+1); break; - case 6: pr=(size>1)? - (void*)(&(pContext->Rsi)): - (void*)(((uae_u8*)&(pContext->Rdx))+1); break; - case 7: pr=(size>1)? - (void*)(&(pContext->Rdi)): - (void*)(((uae_u8*)&(pContext->Rbx))+1); break; -#else - case 0: pr=&(pContext->Eax); break; - case 1: pr=&(pContext->Ecx); break; - case 2: pr=&(pContext->Edx); break; - case 3: pr=&(pContext->Ebx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Eax))+1); break; - case 5: pr=(size>1)? - (void*)(&(pContext->Ebp)): - (void*)(((uae_u8*)&(pContext->Ecx))+1); break; - case 6: pr=(size>1)? - (void*)(&(pContext->Esi)): - (void*)(((uae_u8*)&(pContext->Edx))+1); break; - case 7: pr=(size>1)? - (void*)(&(pContext->Edi)): - (void*)(((uae_u8*)&(pContext->Ebx))+1); break; -#endif - default: abort(); - } - if (pr) { - blockinfo* bi; - - if (currprefs.comp_oldsegv) { - addr-=(uae_u32)NATMEM_OFFSET; - -#ifdef JIT_DEBUG - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } -#endif - if (dir==SIG_READ) { - switch (size) { - case 1: *((uae_u8*)pr)=get_byte (addr); break; - case 2: *((uae_u16*)pr)=swap16(get_word (addr)); break; - case 4: *((uae_u32*)pr)=swap32(get_long (addr)); break; - default: abort(); - } - } - else { /* write */ - switch (size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; - case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; - default: abort(); - } - } -#ifdef JIT_DEBUG - write_log (_T("JIT: Handled one access!\n")); -#endif - fflush(stdout); - segvcount++; - ctxPC+=len; - } - else { - void* tmp=target; - int i; - uae_u8 vecbuf[5]; - - addr-=(uae_u32)NATMEM_OFFSET; - -#ifdef JIT_DEBUG - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } -#endif - - target=(uae_u8*)ctxPC; - for (i=0;i<5;i++) - vecbuf[i]=target[i]; - emit_byte(0xe9); - emit_long((uae_u32)veccode-(uae_u32)target-4); -#ifdef JIT_DEBUG - - write_log (_T("JIT: Create jump to %p\n"),veccode); - write_log (_T("JIT: Handled one access!\n")); -#endif - segvcount++; - - target=veccode; - - if (dir==SIG_READ) { - switch(size) { - case 1: raw_mov_b_ri(r,get_byte (addr)); break; - case 2: raw_mov_w_ri(r,swap16(get_word (addr))); break; - case 4: raw_mov_l_ri(r,swap32(get_long (addr))); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; - case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; - default: abort(); - } - } - for (i=0;i<5;i++) - raw_mov_b_mi(ctxPC+i,vecbuf[i]); - raw_mov_l_mi((uae_u32)&in_handler,0); - emit_byte(0xe9); - emit_long(ctxPC+len-(uae_u32)target-4); - in_handler=1; - target=(uae_u8*)tmp; - } - bi=active; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { -#ifdef JIT_DEBUG - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); -#endif - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return EXCEPTION_CONTINUE_EXECUTION; - } - bi=bi->next; - } - /* Not found in the active list. Might be a rom routine that - is in the dormant list */ - bi=dormant; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { -#ifdef JIT_DEBUG - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); -#endif - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return EXCEPTION_CONTINUE_EXECUTION; - } - bi=bi->next; - } -#ifdef JIT_DEBUG - write_log (_T("JIT: Huh? Could not find trigger!\n")); -#endif - return EXCEPTION_CONTINUE_EXECUTION; - } - } - write_log (_T("JIT: Can't handle access %08X!\n"), i); -#if 0 - if (i) - { - int j; - - for (j=0;j<10;j++) { - write_log (_T("JIT: instruction byte %2d is 0x%02x\n"),j,i[j]); - } - } - write_log (_T("Please send the above info (starting at \"fault address\") to\n")); - write_log (_T("bmeyer@csse.monash.edu.au\n")); - write_log (_T("This shouldn't happen ;-)\n")); -#endif - return EXCEPTION_CONTINUE_SEARCH; -} -#else - -#if defined(__APPLE__) && __DARWIN_UNIX03 -#define CONTEXT_MEMBER(x) __##x -#elif defined(__FreeBSD__) -#define CONTEXT_MEMBER(x) sc_##x -#else -#define CONTEXT_MEMBER(x) x -#endif - -#ifdef __APPLE__ -static void vec(int x, siginfo_t *info, ucontext_t *uap) -{ - _STRUCT_X86_THREAD_STATE32 sc = uap->uc_mcontext->CONTEXT_MEMBER(ss); - uae_u32 addr = 0; -#else -static void vec(int x, struct sigcontext sc) -{ -#endif - uae_u8* i=(uae_u8*)sc.CONTEXT_MEMBER(eip); -#ifdef __APPLE__ - if (i >= compiled_code) { - unsigned int j; - write_log ("JIT_APPLE: can't handle access!\n"); - for (j = 0 ; j < 10; j++) - write_log ("JIT: instruction byte %2d is %02x\n", i, j[i]); - } else { - write_log ("Caught illegal access to (unknown) at eip=%08x\n", i); - } - exit (EXIT_FAILURE); -#elif defined(__FreeBSD__) - //uae_u32 addr=sc.cr2; - uae_u32 addr=sc.CONTEXT_MEMBER(spare2); // UJ: @@@@: ????: -#else - uae_u32 addr=sc.cr2; -#endif - int r=-1; - int size=4; - int dir=-1; - int len=0; - int j; - - write_log (_T("JIT: fault address is %08x at %08x\n"),addr,i); - if (!canbang) - write_log (_T("JIT: Not happy! Canbang is 0 in SIGSEGV handler!\n")); - if (in_handler) - write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); - - /* - * Decode access opcode - */ - if (canbang && i>=compiled_code && i<=current_compile_p) { - if (*i==0x66) { - i++; - size=2; - len++; - } - - switch(i[0]) { - case 0x8a: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - size=1; - len+=6; - break; - } - break; - case 0x88: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - size=1; - len+=6; - break; - } - break; - - case 0x8b: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=2; - break; - default: - break; - } - break; - - case 0x89: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=2; - break; - } - break; - } - } - - if (r!=-1) { - void* pr=NULL; - write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); - - switch(r) { - case 0: pr = &(sc.CONTEXT_MEMBER(eax)); break; - case 1: pr = &(sc.CONTEXT_MEMBER(ecx)); break; - case 2: pr = &(sc.CONTEXT_MEMBER(edx)); break; - case 3: pr = &(sc.CONTEXT_MEMBER(ebx)); break; - case 4: pr = (size>1) ? NULL:(((uae_u8*)&(sc.CONTEXT_MEMBER(eax)))+1); break; - case 5: pr=(size>1)? - (void*)(&(sc.CONTEXT_MEMBER(ebp))): - (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(ecx)))+1); break; - case 6: pr=(size>1)? - (void*)(&(sc.CONTEXT_MEMBER(esi))): - (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(edx)))+1); break; - case 7: pr=(size>1)? - (void*)(&(sc.CONTEXT_MEMBER(edi))): - (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(ebx)))+1); break; - default: abort(); - } - if (pr) { - blockinfo* bi; - - if (currprefs.comp_oldsegv) { -#ifdef FSUAE -// FIXME: check why (uae_u8 was here originally...?) - addr -= (uae_u32)NATMEM_OFFSET; -#else - addr -= (uae_u8)NATMEM_OFFSET; -#endif - - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address in %x SEGV handler.\n"),addr); - } - if (dir==SIG_READ) { - switch(size) { - case 1: *((uae_u8*)pr)=get_byte (addr); break; - case 2: *((uae_u16*)pr)=get_word (addr); break; - case 4: *((uae_u32*)pr)=get_long (addr); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,*((uae_u16*)pr)); break; - case 4: put_long (addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - write_log ("JIT: Handled one access!\n"); - fflush(stdout); - segvcount++; - sc.CONTEXT_MEMBER(eip) += len; - } - else { - uint8_t* tmp=target; - int i; - uae_u8 vecbuf[5]; - -#ifdef FSUAE -// FIXME: check why (uae_u8 was here originally...?) - addr -= (uae_u32)NATMEM_OFFSET; -#else - addr-=(uae_u8)NATMEM_OFFSET; +#ifdef UAE +#include "exception_handler.cpp" #endif - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } - - target = (uae_u8*)sc.CONTEXT_MEMBER(eip); - for (i=0;i<5;i++) - vecbuf[i]=target[i]; - emit_byte(0xe9); - emit_long((uae_u32)veccode-(uae_u32)target-4); - write_log (_T("JIT: Create jump to %p\n"),veccode); - - write_log (_T("JIT: Handled one access!\n")); - segvcount++; - - target=veccode; - - if (dir==SIG_READ) { - switch(size) { - case 1: raw_mov_b_ri(r,get_byte (addr)); break; - case 2: raw_mov_w_ri(r,get_word (addr)); break; - case 4: raw_mov_l_ri(r,get_long (addr)); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,*((uae_u16*)pr)); break; - case 4: put_long (addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - for (i=0;i<5;i++) - raw_mov_b_mi(sc.CONTEXT_MEMBER(eip)+i,vecbuf[i]); - raw_mov_l_mi((uae_u32)&in_handler,0); - emit_byte(0xe9); - emit_long(sc.CONTEXT_MEMBER(eip)+len-(uae_u32)target-4); - in_handler=1; - target=tmp; - } - bi=active; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - /* Not found in the active list. Might be a rom routine that - is in the dormant list */ - bi=dormant; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - write_log (_T("JIT: Huh? Could not find trigger!\n")); - return; - } - } - write_log (_T("JIT: Can't handle access!\n")); - for (j=0;j<10;j++) { - write_log (_T("JIT: instruction byte %2d is %02x\n"),j,i[j]); - } -#if 0 - write_log (_T("Please send the above info (starting at \"fault address\") to\n") - "bmeyer@csse.monash.edu.au\n" - "This shouldn't happen ;-)\n"); - fflush(stdout); -#endif - signal(SIGSEGV,SIG_DFL); /* returning here will cause a "real" SEGV */ -} -#endif -#endif /************************************************************************* * Checking for CPU features * diff --git a/src/jit/exception_handler.cpp b/src/jit/exception_handler.cpp new file mode 100644 index 000000000..8cc0d8c37 --- /dev/null +++ b/src/jit/exception_handler.cpp @@ -0,0 +1,605 @@ +/************************************************************************* +* Handling mistaken direct memory access * +*************************************************************************/ + + +#ifdef NATMEM_OFFSET +#ifdef _WIN32 // %%% BRIAN KING WAS HERE %%% +#include +#else +#ifndef __USE_GNU +#define __USE_GNU +#endif +#include +#endif +#include + +#define SIG_READ 1 +#define SIG_WRITE 2 + +static int in_handler=0; +static uae_u8 *veccode; + +#ifdef _WIN32 + +#if defined(CPU_64_BIT) +#define ctxPC (pContext->Rip) +#else +#define ctxPC (pContext->Eip) +#endif + +int EvalException (LPEXCEPTION_POINTERS blah, int n_except) +{ + PEXCEPTION_RECORD pExceptRecord = NULL; + PCONTEXT pContext = NULL; + + uae_u8* i = NULL; + uae_u32 addr = 0; + int r=-1; + int size=4; + int dir=-1; + int len=0; + + if (n_except != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) + return EXCEPTION_CONTINUE_SEARCH; + + pExceptRecord = blah->ExceptionRecord; + pContext = blah->ContextRecord; + + if (pContext) + i = (uae_u8 *)ctxPC; + if (pExceptRecord) + addr = (uae_u32)(pExceptRecord->ExceptionInformation[1]); +#ifdef JIT_DEBUG + write_log (_T("JIT: fault address is 0x%x at 0x%x\n"),addr,i); +#endif + if (!canbang || !currprefs.cachesize) + return EXCEPTION_CONTINUE_SEARCH; + + if (in_handler) + write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); + + if (canbang && i>=compiled_code && i<=current_compile_p) { + if (*i==0x66) { + i++; + size=2; + len++; + } + + switch(i[0]) { + case 0x8a: + if ((i[1]&0xc0)==0x80) { + r=(i[1]>>3)&7; + dir=SIG_READ; + size=1; + len+=6; + break; + } + break; + case 0x88: + if ((i[1]&0xc0)==0x80) { + r=(i[1]>>3)&7; + dir=SIG_WRITE; + size=1; + len+=6; + break; + } + break; + case 0x8b: + switch(i[1]&0xc0) { + case 0x80: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=6; + break; + case 0x40: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=3; + break; + case 0x00: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=2; + break; + default: + break; + } + break; + case 0x89: + switch(i[1]&0xc0) { + case 0x80: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=6; + break; + case 0x40: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=3; + break; + case 0x00: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=2; + break; + } + break; + } + } + + if (r!=-1) { + void* pr=NULL; +#ifdef JIT_DEBUG + write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); +#endif + + switch(r) { +#if defined(CPU_64_BIT) + case 0: pr=&(pContext->Rax); break; + case 1: pr=&(pContext->Rcx); break; + case 2: pr=&(pContext->Rdx); break; + case 3: pr=&(pContext->Rbx); break; + case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Rax))+1); break; + case 5: pr=(size>1)? + (void*)(&(pContext->Rbp)): + (void*)(((uae_u8*)&(pContext->Rcx))+1); break; + case 6: pr=(size>1)? + (void*)(&(pContext->Rsi)): + (void*)(((uae_u8*)&(pContext->Rdx))+1); break; + case 7: pr=(size>1)? + (void*)(&(pContext->Rdi)): + (void*)(((uae_u8*)&(pContext->Rbx))+1); break; +#else + case 0: pr=&(pContext->Eax); break; + case 1: pr=&(pContext->Ecx); break; + case 2: pr=&(pContext->Edx); break; + case 3: pr=&(pContext->Ebx); break; + case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Eax))+1); break; + case 5: pr=(size>1)? + (void*)(&(pContext->Ebp)): + (void*)(((uae_u8*)&(pContext->Ecx))+1); break; + case 6: pr=(size>1)? + (void*)(&(pContext->Esi)): + (void*)(((uae_u8*)&(pContext->Edx))+1); break; + case 7: pr=(size>1)? + (void*)(&(pContext->Edi)): + (void*)(((uae_u8*)&(pContext->Ebx))+1); break; +#endif + default: abort(); + } + if (pr) { + blockinfo* bi; + + if (currprefs.comp_oldsegv) { + addr-=(uae_u32)NATMEM_OFFSET; + +#ifdef JIT_DEBUG + if ((addr>=0x10000000 && addr<0x40000000) || + (addr>=0x50000000)) { + write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); + } +#endif + if (dir==SIG_READ) { + switch (size) { + case 1: *((uae_u8*)pr)=get_byte (addr); break; + case 2: *((uae_u16*)pr)=swap16(get_word (addr)); break; + case 4: *((uae_u32*)pr)=swap32(get_long (addr)); break; + default: abort(); + } + } + else { /* write */ + switch (size) { + case 1: put_byte (addr,*((uae_u8*)pr)); break; + case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; + case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; + default: abort(); + } + } +#ifdef JIT_DEBUG + write_log (_T("JIT: Handled one access!\n")); +#endif + fflush(stdout); + segvcount++; + ctxPC+=len; + } + else { + void* tmp=target; + int i; + uae_u8 vecbuf[5]; + + addr-=(uae_u32)NATMEM_OFFSET; + +#ifdef JIT_DEBUG + if ((addr>=0x10000000 && addr<0x40000000) || + (addr>=0x50000000)) { + write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); + } +#endif + + target=(uae_u8*)ctxPC; + for (i=0;i<5;i++) + vecbuf[i]=target[i]; + emit_byte(0xe9); + emit_long((uae_u32)veccode-(uae_u32)target-4); +#ifdef JIT_DEBUG + + write_log (_T("JIT: Create jump to %p\n"),veccode); + write_log (_T("JIT: Handled one access!\n")); +#endif + segvcount++; + + target=veccode; + + if (dir==SIG_READ) { + switch(size) { + case 1: raw_mov_b_ri(r,get_byte (addr)); break; + case 2: raw_mov_w_ri(r,swap16(get_word (addr))); break; + case 4: raw_mov_l_ri(r,swap32(get_long (addr))); break; + default: abort(); + } + } + else { /* write */ + switch(size) { + case 1: put_byte (addr,*((uae_u8*)pr)); break; + case 2: put_word (addr,swap16(*((uae_u16*)pr))); break; + case 4: put_long (addr,swap32(*((uae_u32*)pr))); break; + default: abort(); + } + } + for (i=0;i<5;i++) + raw_mov_b_mi(ctxPC+i,vecbuf[i]); + raw_mov_l_mi((uae_u32)&in_handler,0); + emit_byte(0xe9); + emit_long(ctxPC+len-(uae_u32)target-4); + in_handler=1; + target=(uae_u8*)tmp; + } + bi=active; + while (bi) { + if (bi->handler && + (uae_u8*)bi->direct_handler<=i && + (uae_u8*)bi->nexthandler>i) { +#ifdef JIT_DEBUG + write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), + bi->handler, + i, + bi->nexthandler, + bi->pc_p); +#endif + invalidate_block(bi); + raise_in_cl_list(bi); + set_special(0); + return EXCEPTION_CONTINUE_EXECUTION; + } + bi=bi->next; + } + /* Not found in the active list. Might be a rom routine that + is in the dormant list */ + bi=dormant; + while (bi) { + if (bi->handler && + (uae_u8*)bi->direct_handler<=i && + (uae_u8*)bi->nexthandler>i) { +#ifdef JIT_DEBUG + write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), + bi->handler, + i, + bi->nexthandler, + bi->pc_p); +#endif + invalidate_block(bi); + raise_in_cl_list(bi); + set_special(0); + return EXCEPTION_CONTINUE_EXECUTION; + } + bi=bi->next; + } +#ifdef JIT_DEBUG + write_log (_T("JIT: Huh? Could not find trigger!\n")); +#endif + return EXCEPTION_CONTINUE_EXECUTION; + } + } + write_log (_T("JIT: Can't handle access %08X!\n"), i); +#if 0 + if (i) + { + int j; + + for (j=0;j<10;j++) { + write_log (_T("JIT: instruction byte %2d is 0x%02x\n"),j,i[j]); + } + } + write_log (_T("Please send the above info (starting at \"fault address\") to\n")); + write_log (_T("bmeyer@csse.monash.edu.au\n")); + write_log (_T("This shouldn't happen ;-)\n")); +#endif + return EXCEPTION_CONTINUE_SEARCH; +} +#else + +#if defined(__APPLE__) && __DARWIN_UNIX03 +#define CONTEXT_MEMBER(x) __##x +#elif defined(__FreeBSD__) +#define CONTEXT_MEMBER(x) sc_##x +#else +#define CONTEXT_MEMBER(x) x +#endif + +#ifdef __APPLE__ +static void vec(int x, siginfo_t *info, ucontext_t *uap) +{ + _STRUCT_X86_THREAD_STATE32 sc = uap->uc_mcontext->CONTEXT_MEMBER(ss); + uae_u32 addr = 0; +#else +static void vec(int x, struct sigcontext sc) +{ +#endif + uae_u8* i=(uae_u8*)sc.CONTEXT_MEMBER(eip); +#ifdef __APPLE__ + if (i >= compiled_code) { + unsigned int j; + write_log ("JIT_APPLE: can't handle access!\n"); + for (j = 0 ; j < 10; j++) + write_log ("JIT: instruction byte %2d is %02x\n", i, j[i]); + } else { + write_log ("Caught illegal access to (unknown) at eip=%08x\n", i); + } + exit (EXIT_FAILURE); +#elif defined(__FreeBSD__) + //uae_u32 addr=sc.cr2; + uae_u32 addr=sc.CONTEXT_MEMBER(spare2); // UJ: @@@@: ????: +#else + uae_u32 addr=sc.cr2; +#endif + int r=-1; + int size=4; + int dir=-1; + int len=0; + int j; + + write_log (_T("JIT: fault address is %08x at %08x\n"),addr,i); + if (!canbang) + write_log (_T("JIT: Not happy! Canbang is 0 in SIGSEGV handler!\n")); + if (in_handler) + write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); + + /* + * Decode access opcode + */ + if (canbang && i>=compiled_code && i<=current_compile_p) { + if (*i==0x66) { + i++; + size=2; + len++; + } + + switch(i[0]) { + case 0x8a: + if ((i[1]&0xc0)==0x80) { + r=(i[1]>>3)&7; + dir=SIG_READ; + size=1; + len+=6; + break; + } + break; + case 0x88: + if ((i[1]&0xc0)==0x80) { + r=(i[1]>>3)&7; + dir=SIG_WRITE; + size=1; + len+=6; + break; + } + break; + + case 0x8b: + switch(i[1]&0xc0) { + case 0x80: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=6; + break; + case 0x40: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=3; + break; + case 0x00: + r=(i[1]>>3)&7; + dir=SIG_READ; + len+=2; + break; + default: + break; + } + break; + + case 0x89: + switch(i[1]&0xc0) { + case 0x80: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=6; + break; + case 0x40: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=3; + break; + case 0x00: + r=(i[1]>>3)&7; + dir=SIG_WRITE; + len+=2; + break; + } + break; + } + } + + if (r!=-1) { + void* pr=NULL; + write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); + + switch(r) { + case 0: pr = &(sc.CONTEXT_MEMBER(eax)); break; + case 1: pr = &(sc.CONTEXT_MEMBER(ecx)); break; + case 2: pr = &(sc.CONTEXT_MEMBER(edx)); break; + case 3: pr = &(sc.CONTEXT_MEMBER(ebx)); break; + case 4: pr = (size>1) ? NULL:(((uae_u8*)&(sc.CONTEXT_MEMBER(eax)))+1); break; + case 5: pr=(size>1)? + (void*)(&(sc.CONTEXT_MEMBER(ebp))): + (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(ecx)))+1); break; + case 6: pr=(size>1)? + (void*)(&(sc.CONTEXT_MEMBER(esi))): + (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(edx)))+1); break; + case 7: pr=(size>1)? + (void*)(&(sc.CONTEXT_MEMBER(edi))): + (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(ebx)))+1); break; + default: abort(); + } + if (pr) { + blockinfo* bi; + + if (currprefs.comp_oldsegv) { +#ifdef FSUAE +// FIXME: check why (uae_u8 was here originally...?) + addr -= (uae_u32)NATMEM_OFFSET; +#else + addr -= (uae_u8)NATMEM_OFFSET; +#endif + + if ((addr>=0x10000000 && addr<0x40000000) || + (addr>=0x50000000)) { + write_log (_T("JIT: Suspicious address in %x SEGV handler.\n"),addr); + } + if (dir==SIG_READ) { + switch(size) { + case 1: *((uae_u8*)pr)=get_byte (addr); break; + case 2: *((uae_u16*)pr)=get_word (addr); break; + case 4: *((uae_u32*)pr)=get_long (addr); break; + default: abort(); + } + } + else { /* write */ + switch(size) { + case 1: put_byte (addr,*((uae_u8*)pr)); break; + case 2: put_word (addr,*((uae_u16*)pr)); break; + case 4: put_long (addr,*((uae_u32*)pr)); break; + default: abort(); + } + } + write_log ("JIT: Handled one access!\n"); + fflush(stdout); + segvcount++; + sc.CONTEXT_MEMBER(eip) += len; + } + else { + uint8_t* tmp=target; + int i; + uae_u8 vecbuf[5]; + +#ifdef FSUAE +// FIXME: check why (uae_u8 was here originally...?) + addr -= (uae_u32)NATMEM_OFFSET; +#else + addr-=(uae_u8)NATMEM_OFFSET; +#endif + + if ((addr>=0x10000000 && addr<0x40000000) || + (addr>=0x50000000)) { + write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); + } + + target = (uae_u8*)sc.CONTEXT_MEMBER(eip); + for (i=0;i<5;i++) + vecbuf[i]=target[i]; + emit_byte(0xe9); + emit_long((uae_u32)veccode-(uae_u32)target-4); + write_log (_T("JIT: Create jump to %p\n"),veccode); + + write_log (_T("JIT: Handled one access!\n")); + segvcount++; + + target=veccode; + + if (dir==SIG_READ) { + switch(size) { + case 1: raw_mov_b_ri(r,get_byte (addr)); break; + case 2: raw_mov_w_ri(r,get_word (addr)); break; + case 4: raw_mov_l_ri(r,get_long (addr)); break; + default: abort(); + } + } + else { /* write */ + switch(size) { + case 1: put_byte (addr,*((uae_u8*)pr)); break; + case 2: put_word (addr,*((uae_u16*)pr)); break; + case 4: put_long (addr,*((uae_u32*)pr)); break; + default: abort(); + } + } + for (i=0;i<5;i++) + raw_mov_b_mi(sc.CONTEXT_MEMBER(eip)+i,vecbuf[i]); + raw_mov_l_mi((uae_u32)&in_handler,0); + emit_byte(0xe9); + emit_long(sc.CONTEXT_MEMBER(eip)+len-(uae_u32)target-4); + in_handler=1; + target=tmp; + } + bi=active; + while (bi) { + if (bi->handler && + (uae_u8*)bi->direct_handler<=i && + (uae_u8*)bi->nexthandler>i) { + write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), + bi->handler, + i, + bi->nexthandler, + bi->pc_p); + invalidate_block(bi); + raise_in_cl_list(bi); + set_special(0); + return; + } + bi=bi->next; + } + /* Not found in the active list. Might be a rom routine that + is in the dormant list */ + bi=dormant; + while (bi) { + if (bi->handler && + (uae_u8*)bi->direct_handler<=i && + (uae_u8*)bi->nexthandler>i) { + write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), + bi->handler, + i, + bi->nexthandler, + bi->pc_p); + invalidate_block(bi); + raise_in_cl_list(bi); + set_special(0); + return; + } + bi=bi->next; + } + write_log (_T("JIT: Huh? Could not find trigger!\n")); + return; + } + } + write_log (_T("JIT: Can't handle access!\n")); + for (j=0;j<10;j++) { + write_log (_T("JIT: instruction byte %2d is %02x\n"),j,i[j]); + } +#if 0 + write_log (_T("Please send the above info (starting at \"fault address\") to\n") + "bmeyer@csse.monash.edu.au\n" + "This shouldn't happen ;-)\n"); + fflush(stdout); +#endif + signal(SIGSEGV,SIG_DFL); /* returning here will cause a "real" SEGV */ +} +#endif +#endif From c05c28d54d852e7da026141dc62782c64c05eb6a Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Mon, 31 Aug 2015 18:32:30 +0200 Subject: [PATCH 14/25] Unified (segfault) exception handler for Windows and Linux --- ChangeLog | 2 + Makefile.am | 1 + configure.ac | 2 + src/jit/compemu.h | 8 + src/jit/compemu_raw_x86.cpp | 9 - src/jit/compemu_support.cpp | 14 +- src/jit/exception_handler.cpp | 473 +++++++++++----------------------- src/main.cpp | 16 +- 8 files changed, 165 insertions(+), 360 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d5acc97c..6b524763c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ Version 2.5.40dev: +* Use SetUnhandledExceptionFilter on Windows for JIT direct memory. +* Unified (segfault) exception handler for Windows and Linux. * Fixed mman for compatibility with JIT direct memory access. * Re-enable uae_comp_trust* = indirectKS options. * Allow uae_rtc to be set without disabling uae_chipset_compatible. diff --git a/Makefile.am b/Makefile.am index 657664cde..6ab4050f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1161,6 +1161,7 @@ EXTRA_DIST = $(TESTS) $(EXTRA_TESTS) \ src/inputevents.def \ src/jit/compemu_optimizer_x86.cpp \ src/jit/compemu_raw_x86.cpp \ + src/jit/exception_handler.cpp \ src/od-fs/bsdsocket_posix.cpp \ src/od-win32/bsdsock.cpp \ src/od-win32/mman.cpp \ diff --git a/configure.ac b/configure.ac index 62ecece4e..602e3d52f 100644 --- a/configure.ac +++ b/configure.ac @@ -333,6 +333,8 @@ AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec]) AC_CHECK_MEMBERS([struct stat.st_mtime_nsec]) AC_CHECK_MEMBERS([struct in_addr.S_un]) +AC_CHECK_MEMBERS([struct ucontext.uc_mcontext.gregs], + [], [], [[#include ]]) AC_CHECK_TYPES([ptrdiff_t]) AC_STRUCT_ST_BLOCKS diff --git a/src/jit/compemu.h b/src/jit/compemu.h index a07d883f7..b70e99d0f 100644 --- a/src/jit/compemu.h +++ b/src/jit/compemu.h @@ -323,6 +323,7 @@ DECLARE(setcc_m(IMM d, IMM cc)); DECLARE(cmov_b_rr(RW1 d, R1 s, IMM cc)); DECLARE(cmov_w_rr(RW2 d, R2 s, IMM cc)); DECLARE(cmov_l_rr(RW4 d, R4 s, IMM cc)); +DECLARE(setzflg_l(RW4 r)); DECLARE(cmov_l_rm(RW4 d, IMM s, IMM cc)); DECLARE(bsf_l_rr(W4 d, R4 s)); DECLARE(pop_m(IMM d)); @@ -578,3 +579,10 @@ void comp_fbcc_opp (uae_u32 opcode); void comp_fsave_opp (uae_u32 opcode); void comp_frestore_opp (uae_u32 opcode); void comp_fpp_opp (uae_u32 opcode, uae_u16 extra); + +#ifdef _WIN32 +LONG WINAPI EvalException(LPEXCEPTION_POINTERS info); +#if defined(_MSC_VER) && !defined(NO_WIN32_EXCEPTION_HANDLER) +#define USE_STRUCTURED_EXCEPTION_HANDLING +#endif +#endif diff --git a/src/jit/compemu_raw_x86.cpp b/src/jit/compemu_raw_x86.cpp index c02aadb0d..72bffd7aa 100644 --- a/src/jit/compemu_raw_x86.cpp +++ b/src/jit/compemu_raw_x86.cpp @@ -1,15 +1,6 @@ /* This should eventually end up in machdep/, but for now, x86 is the only target, and it's easier this way... */ -#ifdef FSUAE // NL -extern uae_u8 *natmem_offset, *natmem_offset_end; - -#ifdef WINDOWS -#define _WIN32 -#endif - -#endif - /************************************************************************* * Some basic information about the the target CPU * *************************************************************************/ diff --git a/src/jit/compemu_support.cpp b/src/jit/compemu_support.cpp index 275095fe1..0c08abb8f 100644 --- a/src/jit/compemu_support.cpp +++ b/src/jit/compemu_support.cpp @@ -5677,19 +5677,7 @@ void build_comp(void) #endif raw_init_cpu(); #ifdef NATMEM_OFFSET - write_log (_T("JIT: Setting signal handler\n")); -#ifndef _WIN32 -#ifdef FSUAE - struct sigaction sa; - sa.sa_handler = (void (*)(int)) vec; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - - sigaction(SIGSEGV, &sa, NULL); -#else - signal(SIGSEGV,vec); -#endif -#endif + install_exception_handler(); #endif write_log (_T("JIT: Building Compiler function table\n")); for (opcode = 0; opcode < 65536; opcode++) { diff --git a/src/jit/exception_handler.cpp b/src/jit/exception_handler.cpp index 8cc0d8c37..e93ade413 100644 --- a/src/jit/exception_handler.cpp +++ b/src/jit/exception_handler.cpp @@ -2,7 +2,6 @@ * Handling mistaken direct memory access * *************************************************************************/ - #ifdef NATMEM_OFFSET #ifdef _WIN32 // %%% BRIAN KING WAS HERE %%% #include @@ -22,39 +21,81 @@ static uae_u8 *veccode; #ifdef _WIN32 +typedef LPEXCEPTION_POINTERS CONTEXT_T; +#define HAVE_CONTEXT_T 1 + +#define CONTEXT_EIP(context) (context->ContextRecord->Eip) +#define CONTEXT_EAX(context) (context->ContextRecord->Eax) +#define CONTEXT_ECX(context) (context->ContextRecord->Ecx) +#define CONTEXT_EDX(context) (context->ContextRecord->Edx) +#define CONTEXT_EBX(context) (context->ContextRecord->Ebx) +#define CONTEXT_ESP(context) (context->ContextRecord->Esp) +#define CONTEXT_EBP(context) (context->ContextRecord->Ebp) +#define CONTEXT_ESI(context) (context->ContextRecord->Esi) +#define CONTEXT_EDI(context) (context->ContextRecord->Edi) + +#define CONTEXT_RIP(context) (context->ContextRecord->Rip) +#define CONTEXT_RAX(context) (context->ContextRecord->Rax) +#define CONTEXT_RCX(context) (context->ContextRecord->Rcx) +#define CONTEXT_RDX(context) (context->ContextRecord->Rdx) +#define CONTEXT_RBX(context) (context->ContextRecord->Rbx) +#define CONTEXT_RSP(context) (context->ContextRecord->Rsp) +#define CONTEXT_RBP(context) (context->ContextRecord->Rbp) +#define CONTEXT_RSI(context) (context->ContextRecord->Rsi) +#define CONTEXT_RDI(context) (context->ContextRecord->Rdi) + +#define CONTEXT_CR2(context) ((uae_u32)(context->ExceptionRecord->ExceptionInformation[1])) + +#elif HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS + +typedef void *CONTEXT_T; +#define HAVE_CONTEXT_T 1 + +#define CONTEXT_EIP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EIP]) +#define CONTEXT_EAX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EAX]) +#define CONTEXT_ECX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ECX]) +#define CONTEXT_EDX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDX]) +#define CONTEXT_EBX(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBX]) +#define CONTEXT_ESP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESP]) +#define CONTEXT_EBP(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EBP]) +#define CONTEXT_ESI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESI]) +#define CONTEXT_EDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDI]) + +#define CONTEXT_CR2(context) (((struct ucontext *) context)->uc_mcontext.cr2) + +#endif + #if defined(CPU_64_BIT) -#define ctxPC (pContext->Rip) +#ifdef CONTEXT_RIP +#define CONTEXT_PC(context) CONTEXT_RIP(context) +#endif #else -#define ctxPC (pContext->Eip) +#ifdef CONTEXT_EIP +#define CONTEXT_PC(context) CONTEXT_EIP(context) +#endif #endif -int EvalException (LPEXCEPTION_POINTERS blah, int n_except) +#ifdef HAVE_CONTEXT_T +/* + * Try to handle faulted memory access in compiled code + * + * Returns 1 if handled, 0 otherwise + */ +static int handle_access(CONTEXT_T context) { - PEXCEPTION_RECORD pExceptRecord = NULL; - PCONTEXT pContext = NULL; + uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context); + uae_u32 addr = CONTEXT_CR2(context); - uae_u8* i = NULL; - uae_u32 addr = 0; int r=-1; int size=4; int dir=-1; int len=0; - if (n_except != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) - return EXCEPTION_CONTINUE_SEARCH; - - pExceptRecord = blah->ExceptionRecord; - pContext = blah->ContextRecord; - - if (pContext) - i = (uae_u8 *)ctxPC; - if (pExceptRecord) - addr = (uae_u32)(pExceptRecord->ExceptionInformation[1]); #ifdef JIT_DEBUG write_log (_T("JIT: fault address is 0x%x at 0x%x\n"),addr,i); #endif if (!canbang || !currprefs.cachesize) - return EXCEPTION_CONTINUE_SEARCH; + return 0; if (in_handler) write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); @@ -136,37 +177,42 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) switch(r) { #if defined(CPU_64_BIT) - case 0: pr=&(pContext->Rax); break; - case 1: pr=&(pContext->Rcx); break; - case 2: pr=&(pContext->Rdx); break; - case 3: pr=&(pContext->Rbx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Rax))+1); break; - case 5: pr=(size>1)? - (void*)(&(pContext->Rbp)): - (void*)(((uae_u8*)&(pContext->Rcx))+1); break; - case 6: pr=(size>1)? - (void*)(&(pContext->Rsi)): - (void*)(((uae_u8*)&(pContext->Rdx))+1); break; - case 7: pr=(size>1)? - (void*)(&(pContext->Rdi)): - (void*)(((uae_u8*)&(pContext->Rbx))+1); break; + case 0: pr = &(CONTEXT_RAX(context)); break; + case 1: pr = &(CONTEXT_RCX(context)); break; + case 2: pr = &(CONTEXT_RDX(context)); break; + case 3: pr = &(CONTEXT_RBX(context)); break; + case 4: pr = (size > 1) ? NULL + : (((uae_u8*)&(CONTEXT_RAX(context)))+1); + break; + case 5: pr = (size > 1) ? (void*) (&(CONTEXT_RBP(context))) + : (void*)(((uae_u8*)&(CONTEXT_RCX(context))) + 1); + break; + case 6: pr = (size > 1) ? (void*) (&(CONTEXT_RSI(context))) + : (void*)(((uae_u8*)&(CONTEXT_RDX(context))) + 1); + break; + case 7: pr = (size > 1) ? (void*) (&(CONTEXT_RDI(context))) + : (void*)(((uae_u8*)&(CONTEXT_RBX(context))) + 1); + break; #else - case 0: pr=&(pContext->Eax); break; - case 1: pr=&(pContext->Ecx); break; - case 2: pr=&(pContext->Edx); break; - case 3: pr=&(pContext->Ebx); break; - case 4: pr=(size>1)?NULL:(((uae_u8*)&(pContext->Eax))+1); break; - case 5: pr=(size>1)? - (void*)(&(pContext->Ebp)): - (void*)(((uae_u8*)&(pContext->Ecx))+1); break; - case 6: pr=(size>1)? - (void*)(&(pContext->Esi)): - (void*)(((uae_u8*)&(pContext->Edx))+1); break; - case 7: pr=(size>1)? - (void*)(&(pContext->Edi)): - (void*)(((uae_u8*)&(pContext->Ebx))+1); break; + case 0: pr = &(CONTEXT_EAX(context)); break; + case 1: pr = &(CONTEXT_ECX(context)); break; + case 2: pr = &(CONTEXT_EDX(context)); break; + case 3: pr = &(CONTEXT_EBX(context)); break; + case 4: pr = (size > 1) ? NULL + : (((uae_u8*)&(CONTEXT_EAX(context)))+1); + break; + case 5: pr = (size > 1) ? (void*) (&(CONTEXT_EBP(context))) + : (void*)(((uae_u8*)&(CONTEXT_ECX(context))) + 1); + break; + case 6: pr = (size > 1) ? (void*) (&(CONTEXT_ESI(context))) + : (void*)(((uae_u8*)&(CONTEXT_EDX(context))) + 1); + break; + case 7: pr = (size > 1) ? (void*) (&(CONTEXT_EDI(context))) + : (void*)(((uae_u8*)&(CONTEXT_EBX(context))) + 1); + break; #endif - default: abort(); + default: + abort (); } if (pr) { blockinfo* bi; @@ -201,7 +247,7 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) #endif fflush(stdout); segvcount++; - ctxPC+=len; + CONTEXT_PC(context) += len; } else { void* tmp=target; @@ -217,7 +263,7 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) } #endif - target=(uae_u8*)ctxPC; + target = (uae_u8*) CONTEXT_PC(context); for (i=0;i<5;i++) vecbuf[i]=target[i]; emit_byte(0xe9); @@ -248,10 +294,10 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) } } for (i=0;i<5;i++) - raw_mov_b_mi(ctxPC+i,vecbuf[i]); + raw_mov_b_mi(CONTEXT_PC(context) + i, vecbuf[i]); raw_mov_l_mi((uae_u32)&in_handler,0); emit_byte(0xe9); - emit_long(ctxPC+len-(uae_u32)target-4); + emit_long(CONTEXT_PC(context) + len - (uae_u32)target - 4); in_handler=1; target=(uae_u8*)tmp; } @@ -270,7 +316,7 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) invalidate_block(bi); raise_in_cl_list(bi); set_special(0); - return EXCEPTION_CONTINUE_EXECUTION; + return 1; } bi=bi->next; } @@ -291,14 +337,14 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) invalidate_block(bi); raise_in_cl_list(bi); set_special(0); - return EXCEPTION_CONTINUE_EXECUTION; + return 1; } bi=bi->next; } #ifdef JIT_DEBUG write_log (_T("JIT: Huh? Could not find trigger!\n")); #endif - return EXCEPTION_CONTINUE_EXECUTION; + return 1; } } write_log (_T("JIT: Can't handle access %08X!\n"), i); @@ -315,291 +361,66 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) write_log (_T("bmeyer@csse.monash.edu.au\n")); write_log (_T("This shouldn't happen ;-)\n")); #endif - return EXCEPTION_CONTINUE_SEARCH; + return 0; } -#else +#endif /* CONTEXT_T */ -#if defined(__APPLE__) && __DARWIN_UNIX03 -#define CONTEXT_MEMBER(x) __##x -#elif defined(__FreeBSD__) -#define CONTEXT_MEMBER(x) sc_##x -#else -#define CONTEXT_MEMBER(x) x -#endif +#ifdef _WIN32 -#ifdef __APPLE__ -static void vec(int x, siginfo_t *info, ucontext_t *uap) -{ - _STRUCT_X86_THREAD_STATE32 sc = uap->uc_mcontext->CONTEXT_MEMBER(ss); - uae_u32 addr = 0; -#else -static void vec(int x, struct sigcontext sc) +LONG WINAPI EvalException(LPEXCEPTION_POINTERS info) { -#endif - uae_u8* i=(uae_u8*)sc.CONTEXT_MEMBER(eip); -#ifdef __APPLE__ - if (i >= compiled_code) { - unsigned int j; - write_log ("JIT_APPLE: can't handle access!\n"); - for (j = 0 ; j < 10; j++) - write_log ("JIT: instruction byte %2d is %02x\n", i, j[i]); - } else { - write_log ("Caught illegal access to (unknown) at eip=%08x\n", i); - } - exit (EXIT_FAILURE); -#elif defined(__FreeBSD__) - //uae_u32 addr=sc.cr2; - uae_u32 addr=sc.CONTEXT_MEMBER(spare2); // UJ: @@@@: ????: -#else - uae_u32 addr=sc.cr2; -#endif - int r=-1; - int size=4; - int dir=-1; - int len=0; - int j; + DWORD code = info->ExceptionRecord->ExceptionCode; + if (code != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) + return EXCEPTION_CONTINUE_SEARCH; - write_log (_T("JIT: fault address is %08x at %08x\n"),addr,i); - if (!canbang) - write_log (_T("JIT: Not happy! Canbang is 0 in SIGSEGV handler!\n")); - if (in_handler) - write_log (_T("JIT: Argh --- Am already in a handler. Shouldn't happen!\n")); + if (handle_access(info)) { + return EXCEPTION_CONTINUE_EXECUTION; + } + return EXCEPTION_CONTINUE_SEARCH; +} - /* - * Decode access opcode - */ - if (canbang && i>=compiled_code && i<=current_compile_p) { - if (*i==0x66) { - i++; - size=2; - len++; - } +#elif defined(HAVE_CONTEXT_T) - switch(i[0]) { - case 0x8a: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_READ; - size=1; - len+=6; - break; - } - break; - case 0x88: - if ((i[1]&0xc0)==0x80) { - r=(i[1]>>3)&7; - dir=SIG_WRITE; - size=1; - len+=6; - break; - } - break; - - case 0x8b: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_READ; - len+=2; - break; - default: - break; - } - break; +static void sigsegv_handler(int signum, struct siginfo *info, void *context) +{ + uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context); + uae_u32 addr = CONTEXT_CR2(context); - case 0x89: - switch(i[1]&0xc0) { - case 0x80: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=6; - break; - case 0x40: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=3; - break; - case 0x00: - r=(i[1]>>3)&7; - dir=SIG_WRITE; - len+=2; - break; - } - break; + if (i >= compiled_code) { + if (handle_access (context)) + return; + else { + int j; + write_log ("JIT: can't handle access!\n"); + for (j = 0 ; j < 10; j++) + write_log ("JIT: instruction byte %2d is %02x\n", i, j[i]); } + } else { + write_log ("Caught illegal access to %08x at eip=%08x\n", addr, i); } - if (r!=-1) { - void* pr=NULL; - write_log (_T("JIT: register was %d, direction was %d, size was %d\n"),r,dir,size); - - switch(r) { - case 0: pr = &(sc.CONTEXT_MEMBER(eax)); break; - case 1: pr = &(sc.CONTEXT_MEMBER(ecx)); break; - case 2: pr = &(sc.CONTEXT_MEMBER(edx)); break; - case 3: pr = &(sc.CONTEXT_MEMBER(ebx)); break; - case 4: pr = (size>1) ? NULL:(((uae_u8*)&(sc.CONTEXT_MEMBER(eax)))+1); break; - case 5: pr=(size>1)? - (void*)(&(sc.CONTEXT_MEMBER(ebp))): - (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(ecx)))+1); break; - case 6: pr=(size>1)? - (void*)(&(sc.CONTEXT_MEMBER(esi))): - (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(edx)))+1); break; - case 7: pr=(size>1)? - (void*)(&(sc.CONTEXT_MEMBER(edi))): - (void*)(((uae_u8*)&(sc.CONTEXT_MEMBER(ebx)))+1); break; - default: abort(); - } - if (pr) { - blockinfo* bi; + exit (EXIT_FAILURE); +} - if (currprefs.comp_oldsegv) { -#ifdef FSUAE -// FIXME: check why (uae_u8 was here originally...?) - addr -= (uae_u32)NATMEM_OFFSET; -#else - addr -= (uae_u8)NATMEM_OFFSET; #endif - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address in %x SEGV handler.\n"),addr); - } - if (dir==SIG_READ) { - switch(size) { - case 1: *((uae_u8*)pr)=get_byte (addr); break; - case 2: *((uae_u16*)pr)=get_word (addr); break; - case 4: *((uae_u32*)pr)=get_long (addr); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,*((uae_u16*)pr)); break; - case 4: put_long (addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - write_log ("JIT: Handled one access!\n"); - fflush(stdout); - segvcount++; - sc.CONTEXT_MEMBER(eip) += len; - } - else { - uint8_t* tmp=target; - int i; - uae_u8 vecbuf[5]; - -#ifdef FSUAE -// FIXME: check why (uae_u8 was here originally...?) - addr -= (uae_u32)NATMEM_OFFSET; +static void install_exception_handler(void) +{ +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING + /* Structured exception handler is installed in main.cpp */ +#elif defined(_WIN32) + write_log (_T("JIT: Installing unhandled exception filter\n")); + SetUnhandledExceptionFilter(EvalException); +#elif defined(HAVE_CONTEXT_T) + write_log (_T("JIT: Installing segfault handler\n")); + struct sigaction act; + act.sa_sigaction = (void (*)(int, siginfo_t*, void*)) sigsegv_handler; + sigemptyset (&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &act, NULL); #else - addr-=(uae_u8)NATMEM_OFFSET; -#endif - - if ((addr>=0x10000000 && addr<0x40000000) || - (addr>=0x50000000)) { - write_log (_T("JIT: Suspicious address 0x%x in SEGV handler.\n"),addr); - } - - target = (uae_u8*)sc.CONTEXT_MEMBER(eip); - for (i=0;i<5;i++) - vecbuf[i]=target[i]; - emit_byte(0xe9); - emit_long((uae_u32)veccode-(uae_u32)target-4); - write_log (_T("JIT: Create jump to %p\n"),veccode); - - write_log (_T("JIT: Handled one access!\n")); - segvcount++; - - target=veccode; - - if (dir==SIG_READ) { - switch(size) { - case 1: raw_mov_b_ri(r,get_byte (addr)); break; - case 2: raw_mov_w_ri(r,get_word (addr)); break; - case 4: raw_mov_l_ri(r,get_long (addr)); break; - default: abort(); - } - } - else { /* write */ - switch(size) { - case 1: put_byte (addr,*((uae_u8*)pr)); break; - case 2: put_word (addr,*((uae_u16*)pr)); break; - case 4: put_long (addr,*((uae_u32*)pr)); break; - default: abort(); - } - } - for (i=0;i<5;i++) - raw_mov_b_mi(sc.CONTEXT_MEMBER(eip)+i,vecbuf[i]); - raw_mov_l_mi((uae_u32)&in_handler,0); - emit_byte(0xe9); - emit_long(sc.CONTEXT_MEMBER(eip)+len-(uae_u32)target-4); - in_handler=1; - target=tmp; - } - bi=active; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - /* Not found in the active list. Might be a rom routine that - is in the dormant list */ - bi=dormant; - while (bi) { - if (bi->handler && - (uae_u8*)bi->direct_handler<=i && - (uae_u8*)bi->nexthandler>i) { - write_log (_T("JIT: deleted trigger (%p<%p<%p) %p\n"), - bi->handler, - i, - bi->nexthandler, - bi->pc_p); - invalidate_block(bi); - raise_in_cl_list(bi); - set_special(0); - return; - } - bi=bi->next; - } - write_log (_T("JIT: Huh? Could not find trigger!\n")); - return; - } - } - write_log (_T("JIT: Can't handle access!\n")); - for (j=0;j<10;j++) { - write_log (_T("JIT: instruction byte %2d is %02x\n"),j,i[j]); - } -#if 0 - write_log (_T("Please send the above info (starting at \"fault address\") to\n") - "bmeyer@csse.monash.edu.au\n" - "This shouldn't happen ;-)\n"); - fflush(stdout); + write_log (_T("JIT: No segfault handler installed\n")); #endif - signal(SIGSEGV,SIG_DFL); /* returning here will cause a "real" SEGV */ } -#endif -#endif + +#endif /* NATMEM_OFFSET */ diff --git a/src/main.cpp b/src/main.cpp index 56af0498c..95891c558 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,7 @@ #include "cpuboard.h" #include "uae/ppc.h" #include "devices.h" +#include "jit/compemu.h" #ifdef RETROPLATFORM #include "rp.h" #endif @@ -959,23 +960,15 @@ void do_start_program (void) #ifdef WITH_LUA uae_lua_loadall (); #endif -#ifdef FSUAE - -#else -#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER) - extern int EvalException (LPEXCEPTION_POINTERS blah, int n_except); +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING __try -#endif #endif { m68k_go (1); } -#ifdef FSUAE - -#else -#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER) +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING #ifdef JIT - __except (EvalException (GetExceptionInformation (), GetExceptionCode ())) + __except (EvalException(GetExceptionInformation())) #else __except (DummyException (GetExceptionInformation (), GetExceptionCode ())) #endif @@ -983,7 +976,6 @@ void do_start_program (void) // EvalException does the good stuff... } #endif -#endif } void start_program (void) From 1ba8901fc0c374bc0e105fec3adf209c4c89b462 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 4 Sep 2015 19:06:26 +0200 Subject: [PATCH 15/25] 2.5.40dev --- ISSUES | 11 +++++++++-- configure.ac | 2 +- debian/changelog | 4 ++-- fs-uae.spec | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ISSUES b/ISSUES index c9ea8ec8d..2efeb0976 100644 --- a/ISSUES +++ b/ISSUES @@ -1,2 +1,9 @@ -* When entering the GUI using modifier+F12, the modifier key(s) sticks in - the emulated Amiga when you return to the emulation. +* Amiga key sticks when opening/closing FS-UAE menu with modifier+F12 + https://github.com/FrodeSolheim/fs-uae/issues/77 + +* FS-UAE freezes with black screen on Windows / nVIDIA? + https://github.com/FrodeSolheim/fs-uae/issues/75 + +* Black screen when FS-UAE is started from FS-UAE Arcade? + https://github.com/FrodeSolheim/fs-uae/issues/76 + https://github.com/FrodeSolheim/fs-uae-arcade/issues/6 diff --git a/configure.ac b/configure.ac index 602e3d52f..6fdcea3bd 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.67]) -AC_INIT([FS-UAE], [2.5.39dev], +AC_INIT([FS-UAE], [2.5.40dev], [frode@fs-uae.net], [fs-uae], [http://fs-uae.net]) AC_CONFIG_AUX_DIR([.]) AC_CANONICAL_HOST diff --git a/debian/changelog b/debian/changelog index a81a9425c..3494bc3b1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -fs-uae (2.5.39~dev-0) unstable; urgency=low +fs-uae (2.5.40~dev-0) unstable; urgency=low * Dummy changelog entry. - -- Frode Solheim Sat, 15 Aug 2015 21:18:14 +0200 + -- Frode Solheim Mon, 31 Aug 2015 19:46:02 +0200 diff --git a/fs-uae.spec b/fs-uae.spec index 300bd909d..151cc93f5 100644 --- a/fs-uae.spec +++ b/fs-uae.spec @@ -1,6 +1,6 @@ %define name fs-uae -%define version 2.5.39dev -%define unmangled_version 2.5.39dev +%define version 2.5.40dev +%define unmangled_version 2.5.40dev %define release 1%{?dist} Summary: Amiga emulator with on-screen GUI and online play support From 568cec3a4cfd9c3df42144a4e9f48ec3d8a8c8aa Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 4 Sep 2015 19:06:38 +0200 Subject: [PATCH 16/25] handle failed mmap --- src/od-fs/mman.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/od-fs/mman.cpp b/src/od-fs/mman.cpp index 4eb58389e..1458221c7 100644 --- a/src/od-fs/mman.cpp +++ b/src/od-fs/mman.cpp @@ -100,11 +100,13 @@ static void *VirtualAlloc(void *lpAddress, size_t dwSize, int flAllocationType, memory = mmap(lpAddress, dwSize, 0, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (memory == (void *) -1) { write_log("mmap failed errno %d\n", errno); + return NULL; } #else memory = malloc(dwSize); if (memory == NULL) { write_log("memory allocated failed errno %d\n", errno); + return NULL; } #endif } From b992f7abf0a327627333900400f312b26b9d5cbb Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Wed, 16 Sep 2015 23:41:02 +0200 Subject: [PATCH 17/25] JIT direct memory exception handler for OS X (32-bit) --- ChangeLog | 4 ++++ src/jit/exception_handler.cpp | 34 ++++++++++++++++++++++++---------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b524763c..194428c46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Version 2.5.41dev: + +* JIT direct memory exception handler for OS X (32-bit). + Version 2.5.40dev: * Use SetUnhandledExceptionFilter on Windows for JIT direct memory. diff --git a/src/jit/exception_handler.cpp b/src/jit/exception_handler.cpp index e93ade413..ed4c32ad2 100644 --- a/src/jit/exception_handler.cpp +++ b/src/jit/exception_handler.cpp @@ -44,8 +44,6 @@ typedef LPEXCEPTION_POINTERS CONTEXT_T; #define CONTEXT_RSI(context) (context->ContextRecord->Rsi) #define CONTEXT_RDI(context) (context->ContextRecord->Rdi) -#define CONTEXT_CR2(context) ((uae_u32)(context->ExceptionRecord->ExceptionInformation[1])) - #elif HAVE_STRUCT_UCONTEXT_UC_MCONTEXT_GREGS typedef void *CONTEXT_T; @@ -61,7 +59,19 @@ typedef void *CONTEXT_T; #define CONTEXT_ESI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_ESI]) #define CONTEXT_EDI(context) (((struct ucontext *) context)->uc_mcontext.gregs[REG_EDI]) -#define CONTEXT_CR2(context) (((struct ucontext *) context)->uc_mcontext.cr2) +#elif defined(__DARWIN_UNIX03) && defined(_STRUCT_X86_EXCEPTION_STATE32) + +typedef void *CONTEXT_T; +#define HAVE_CONTEXT_T 1 +#define CONTEXT_EIP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__eip)) +#define CONTEXT_EAX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__eax) +#define CONTEXT_ECX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ecx) +#define CONTEXT_EDX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edx) +#define CONTEXT_EBX(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebx) +#define CONTEXT_ESP(context) (*((unsigned long *) &((ucontext_t *) context)->uc_mcontext->__ss.__esp)) +#define CONTEXT_EBP(context) (((ucontext_t *) context)->uc_mcontext->__ss.__ebp) +#define CONTEXT_ESI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__esi) +#define CONTEXT_EDI(context) (((ucontext_t *) context)->uc_mcontext->__ss.__edi) #endif @@ -81,10 +91,10 @@ typedef void *CONTEXT_T; * * Returns 1 if handled, 0 otherwise */ -static int handle_access(CONTEXT_T context) +static int handle_access(uintptr_t fault_addr, CONTEXT_T context) { uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context); - uae_u32 addr = CONTEXT_CR2(context); + uae_u32 addr = fault_addr; int r=-1; int size=4; @@ -373,7 +383,8 @@ LONG WINAPI EvalException(LPEXCEPTION_POINTERS info) if (code != STATUS_ACCESS_VIOLATION || !canbang || currprefs.cachesize == 0) return EXCEPTION_CONTINUE_SEARCH; - if (handle_access(info)) { + uintptr_t address = info->ExceptionRecord->ExceptionInformation[1]; + if (handle_access(address, info)) { return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH; @@ -381,13 +392,13 @@ LONG WINAPI EvalException(LPEXCEPTION_POINTERS info) #elif defined(HAVE_CONTEXT_T) -static void sigsegv_handler(int signum, struct siginfo *info, void *context) +static void sigsegv_handler(int signum, siginfo_t *info, void *context) { uae_u8 *i = (uae_u8 *) CONTEXT_EIP(context); - uae_u32 addr = CONTEXT_CR2(context); + uintptr_t address = (uintptr_t) info->si_addr; if (i >= compiled_code) { - if (handle_access (context)) + if (handle_access(address, context)) return; else { int j; @@ -396,7 +407,7 @@ static void sigsegv_handler(int signum, struct siginfo *info, void *context) write_log ("JIT: instruction byte %2d is %02x\n", i, j[i]); } } else { - write_log ("Caught illegal access to %08x at eip=%08x\n", addr, i); + write_log ("Caught illegal access to %08lx at eip=%p\n", address, i); } exit (EXIT_FAILURE); @@ -418,6 +429,9 @@ static void install_exception_handler(void) sigemptyset (&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &act, NULL); +#ifdef MACOSX + sigaction(SIGBUS, &act, NULL); +#endif #else write_log (_T("JIT: No segfault handler installed\n")); #endif From 43a479fe78d383d318d95c432b3b8d86c4dd8589 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Wed, 16 Sep 2015 23:50:57 +0200 Subject: [PATCH 18/25] Added official JIT compiler options, default to direct memory access --- ChangeLog | 3 +++ doc/options/jit_compiler | 1 + doc/options/jit_memory | 4 ++++ src/fs-uae/config.c | 18 +++++++++++++----- src/fs-uae/options.h | 2 ++ 5 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 doc/options/jit_compiler create mode 100644 doc/options/jit_memory diff --git a/ChangeLog b/ChangeLog index 194428c46..5b75d4b62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ Version 2.5.41dev: +* New boolean option jit_compiler (to enable/disable JIT compilation). +* New option jit_memory (=direct/indirect). +* JIT compiler defaults to direct memory access on all platforms now. * JIT direct memory exception handler for OS X (32-bit). Version 2.5.40dev: diff --git a/doc/options/jit_compiler b/doc/options/jit_compiler new file mode 100644 index 000000000..57d4f0b6d --- /dev/null +++ b/doc/options/jit_compiler @@ -0,0 +1 @@ +Type: Boolean diff --git a/doc/options/jit_memory b/doc/options/jit_memory new file mode 100644 index 000000000..1c1815b33 --- /dev/null +++ b/doc/options/jit_memory @@ -0,0 +1,4 @@ +Type: Choice + +Value: direct +Value: indirect diff --git a/src/fs-uae/config.c b/src/fs-uae/config.c index da057f492..3201ea01d 100644 --- a/src/fs-uae/config.c +++ b/src/fs-uae/config.c @@ -194,11 +194,19 @@ void fs_uae_configure_amiga_hardware() fs_emu_log("configuring \"%s\", accuracy=%d\n", c->name, 1); amiga_quickstart(c->quickstart_model, c->quickstart_config, 1); - amiga_set_option("cachesize", "0"); - amiga_set_option("comp_trustbyte", "indirect"); - amiga_set_option("comp_trustword", "indirect"); - amiga_set_option("comp_trustlong", "indirect"); - amiga_set_option("comp_trustnaddr", "indirect"); + + if (fs_config_get_boolean(OPTION_JIT_COMPILER) == 1) { + amiga_set_option("cachesize", "8192"); + } else { + amiga_set_option("cachesize", "0"); + } + const char *jit_memory = fs_config_get_const_string(OPTION_JIT_MEMORY); + if (jit_memory && strcmp(jit_memory, "indirect") == 0) { + amiga_set_option("comp_trustbyte", "indirect"); + amiga_set_option("comp_trustword", "indirect"); + amiga_set_option("comp_trustlong", "indirect"); + amiga_set_option("comp_trustnaddr", "indirect"); + } #if 1 if (cfg->z3realmapping == 0) { diff --git a/src/fs-uae/options.h b/src/fs-uae/options.h index 18dc87147..92bdf2848 100644 --- a/src/fs-uae/options.h +++ b/src/fs-uae/options.h @@ -23,6 +23,8 @@ #define OPTION_GRAPHICS_CARD "graphics_card" #define OPTION_GRAPHICS_CARD_ROM "graphics_card_rom" #define OPTION_GRAPHICS_CARD_MEMORY "graphics_card_memory" +#define OPTION_JIT_COMPILER "jit_compiler" +#define OPTION_JIT_MEMORY "jit_memory" #define OPTION_JOYSTICK_PORT_0_AUTOSWITCH "joystick_port_0_autoswitch" #define OPTION_LINE_DOUBLING "line_doubling" #define OPTION_LOG_AUTOSCALE "log_autoscale" From 44f0ca45409c9e98380bd43be300bdc8fad06bde Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Fri, 18 Sep 2015 18:05:11 +0200 Subject: [PATCH 19/25] Separate auto-fire button (based on patch from S. Jordan) --- ChangeLog | 2 ++ share/fs-uae/input/universal_gamepad.ini | 1 + src/fs-uae/input.c | 6 ++++++ src/fs-uae/joystick.c | 4 ++++ src/inputevents.def | 7 +++++++ src/od-fs/input.cpp | 5 ++++- 6 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5b75d4b62..91143890a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ Version 2.5.41dev: +* Separate auto-fire button (based on patch from S. Jordan). +* Dedicated auto-fire button mapped to "right trigger" by default. * New boolean option jit_compiler (to enable/disable JIT compilation). * New option jit_memory (=direct/indirect). * JIT compiler defaults to direct memory access on all platforms now. diff --git a/share/fs-uae/input/universal_gamepad.ini b/share/fs-uae/input/universal_gamepad.ini index 0edd59d29..6cd5c4d80 100644 --- a/share/fs-uae/input/universal_gamepad.ini +++ b/share/fs-uae/input/universal_gamepad.ini @@ -33,6 +33,7 @@ dpad_down = down south_button = 1 west_button = 2 left_trigger = toggle_autofire +right_trigger = autofire lstick_left = left lstick_right = right diff --git a/src/fs-uae/input.c b/src/fs-uae/input.c index f3c7bd3c7..7c9588bba 100644 --- a/src/fs-uae/input.c +++ b/src/fs-uae/input.c @@ -276,6 +276,12 @@ static fs_emu_action g_actions[] = { { INPUTEVENT_SPC_CDTV_FRONT_PANEL_NEXT, "action_cdtv_front_panel_next", 0 }, { INPUTEVENT_SPC_CDTV_FRONT_PANEL_REW, "action_cdtv_front_panel_rew", 0 }, { INPUTEVENT_SPC_CDTV_FRONT_PANEL_FF, "action_cdtv_front_panel_ff", 0 }, + + { INPUTEVENT_JOY1_AUTOFIRE_BUTTON, "action_joy_0_autofire_button", 0 }, + { INPUTEVENT_JOY2_AUTOFIRE_BUTTON, "action_joy_1_autofire_button", 0 }, + { INPUTEVENT_PAR_JOY1_AUTOFIRE_BUTTON, "action_par_joy_0_autofire_button", 0 }, + { INPUTEVENT_PAR_JOY2_AUTOFIRE_BUTTON, "action_par_joy_1_autofire_button", 0 }, + { INPUTEVENT_SPC_STATESAVE1, "action_save_state_1", 0 }, { INPUTEVENT_SPC_STATESAVE2, "action_save_state_2", 0 }, { INPUTEVENT_SPC_STATESAVE3, "action_save_state_3", 0 }, diff --git a/src/fs-uae/joystick.c b/src/fs-uae/joystick.c index 3b218f0e9..87a7b426c 100644 --- a/src/fs-uae/joystick.c +++ b/src/fs-uae/joystick.c @@ -29,6 +29,7 @@ static fs_emu_input_mapping g_joystick_mappings[][FS_UAE_MAX_PORT_ACTIONS] = { { "rewind", INPUTEVENT_JOY1_CD32_RWD }, { "forward", INPUTEVENT_JOY1_CD32_FFW }, { "play", INPUTEVENT_JOY1_CD32_PLAY }, + { "autofire", INPUTEVENT_JOY1_AUTOFIRE_BUTTON }, { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE }, { NULL, 0 }, }, @@ -48,6 +49,7 @@ static fs_emu_input_mapping g_joystick_mappings[][FS_UAE_MAX_PORT_ACTIONS] = { { "rewind", INPUTEVENT_JOY2_CD32_RWD }, { "forward", INPUTEVENT_JOY2_CD32_FFW }, { "play", INPUTEVENT_JOY2_CD32_PLAY }, + { "autofire", INPUTEVENT_JOY2_AUTOFIRE_BUTTON }, { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_1_AUTOFIRE }, { NULL, 0 }, }, @@ -59,6 +61,7 @@ static fs_emu_input_mapping g_joystick_mappings[][FS_UAE_MAX_PORT_ACTIONS] = { { "down", INPUTEVENT_PAR_JOY1_DOWN }, { "1", INPUTEVENT_PAR_JOY1_FIRE_BUTTON }, { "2", INPUTEVENT_PAR_JOY1_2ND_BUTTON }, + { "autofire", INPUTEVENT_PAR_JOY1_AUTOFIRE_BUTTON }, { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_2_AUTOFIRE }, { NULL, 0 }, { NULL, 0 }, @@ -78,6 +81,7 @@ static fs_emu_input_mapping g_joystick_mappings[][FS_UAE_MAX_PORT_ACTIONS] = { { "down", INPUTEVENT_PAR_JOY2_DOWN }, { "1", INPUTEVENT_PAR_JOY2_FIRE_BUTTON }, { "2", INPUTEVENT_PAR_JOY2_2ND_BUTTON }, + { "autofire", INPUTEVENT_PAR_JOY2_AUTOFIRE_BUTTON }, { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_3_AUTOFIRE }, { NULL, 0 }, { NULL, 0 }, diff --git a/src/inputevents.def b/src/inputevents.def index 6db929ec0..44c241256 100644 --- a/src/inputevents.def +++ b/src/inputevents.def @@ -405,6 +405,13 @@ DEFEVENT(SPC_CDTV_FRONT_PANEL_FF,_T("CDTV Front Panel Fast Forward"),AM_K,0,0,AK #ifdef FSUAE +DEFEVENT(AUTOFIRE_BEGIN, _T(""), AM_K, 0, 0, 0) +DEFEVENT(JOY1_AUTOFIRE_BUTTON,_T("Joy1 Fire/Mouse1 Left Button (Autofire)"),AM_K,4,1,JOYBUTTON_1) +DEFEVENT(JOY2_AUTOFIRE_BUTTON,_T("Joy2 Fire/Mouse2 Left Button (Autofire)"),AM_K,4,2,JOYBUTTON_1) +DEFEVENT(PAR_JOY1_AUTOFIRE_BUTTON,_T("Parallel Joy1 Fire Button (Autofire)"),AM_K,4,3,JOYBUTTON_1) +DEFEVENT(PAR_JOY2_AUTOFIRE_BUTTON,_T("Parallel Joy2 Fire Button (Autofire)"),AM_K,4,4,JOYBUTTON_1) +DEFEVENT(AUTOFIRE_END, _T(""), AM_K, 0, 0, 0) + DEFEVENT(SPC_STATESAVE1,_T("Quick save state slot 1"),AM_K,0,0,AKS_STATESAVEQUICK1) DEFEVENT(SPC_STATESAVE2,_T("Quick save state slot 2"),AM_K,0,0,AKS_STATESAVEQUICK2) DEFEVENT(SPC_STATESAVE3,_T("Quick save state slot 3"),AM_K,0,0,AKS_STATESAVEQUICK3) diff --git a/src/od-fs/input.cpp b/src/od-fs/input.cpp index de318bb68..e399a6798 100644 --- a/src/od-fs/input.cpp +++ b/src/od-fs/input.cpp @@ -121,7 +121,10 @@ int amiga_send_input_event(int input_event, int state) { g_joystick_port_autofire[3]) { autofire = 1; } - + else if ((input_event > INPUTEVENT_AUTOFIRE_BEGIN) && + (input_event < INPUTEVENT_AUTOFIRE_END)) { + autofire = 1; + } bool canstopplayback = 1; bool playbackevent = 0; From 91f22f7079f3050fbb6cc0c23f02d48e2918372a Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 19 Sep 2015 11:58:25 +0200 Subject: [PATCH 20/25] Implement action_pause to make action key configurable --- ChangeLog | 1 + libfsemu/src/emu/actions.c | 6 +++++- libfsemu/src/emu/actions.h | 9 +++++---- libfsemu/src/emu/input.c | 5 ++++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91143890a..5291f6167 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.41dev: +* Implement action_pause to make action key configurable. * Separate auto-fire button (based on patch from S. Jordan). * Dedicated auto-fire button mapped to "right trigger" by default. * New boolean option jit_compiler (to enable/disable JIT compilation). diff --git a/libfsemu/src/emu/actions.c b/libfsemu/src/emu/actions.c index 54225bd93..88b6ded17 100644 --- a/libfsemu/src/emu/actions.c +++ b/libfsemu/src/emu/actions.c @@ -49,7 +49,8 @@ static void taunt() { g_free(text); } -void fs_emu_handle_libfsemu_action(int action, int state) { +void fs_emu_handle_libfsemu_action(int action, int state) +{ printf("internal action %d %d\n", action, state); if (state) { if (action == FS_EMU_ACTION_TAUNT) { @@ -58,5 +59,8 @@ void fs_emu_handle_libfsemu_action(int action, int state) { else if (action == FS_EMU_ACTION_SCREENSHOT) { g_fs_emu_screenshot = 1; } + else if (action == FS_EMU_ACTION_PAUSE) { + fs_emu_pause(!fs_emu_is_paused()); + } } } diff --git a/libfsemu/src/emu/actions.h b/libfsemu/src/emu/actions.h index 6ea32c609..9839f035a 100644 --- a/libfsemu/src/emu/actions.h +++ b/libfsemu/src/emu/actions.h @@ -1,9 +1,10 @@ -#ifndef LIBFSEMU_ACTIONS_H_ -#define LIBFSEMU_ACTIONS_H_ +#ifndef LIBFSEMU_ACTIONS_H +#define LIBFSEMU_ACTIONS_H -#define FS_EMU_ACTION_TAUNT 0xc001 +#define FS_EMU_ACTION_TAUNT 0xc001 #define FS_EMU_ACTION_SCREENSHOT 0xc002 +#define FS_EMU_ACTION_PAUSE 0xc003 void fs_emu_handle_libfsemu_action(int action, int state); -#endif // LIBFSEMU_ACTIONS_H_ +#endif /* LIBFSEMU_ACTIONS_H */ diff --git a/libfsemu/src/emu/input.c b/libfsemu/src/emu/input.c index aa6efc273..1f17229dd 100644 --- a/libfsemu/src/emu/input.c +++ b/libfsemu/src/emu/input.c @@ -627,13 +627,16 @@ void fs_emu_map_custom_actions() { map_custom_joystick_actions(); } -void fs_emu_set_actions(fs_emu_action *actions) { +void fs_emu_set_actions(fs_emu_action *actions) +{ int k = 0; g_actions[k].name = "action_taunt"; g_actions[k++].input_event = FS_EMU_ACTION_TAUNT; g_actions[k].name = "action_screenshot"; g_actions[k++].input_event = FS_EMU_ACTION_SCREENSHOT; + g_actions[k].name = "action_pause"; + g_actions[k++].input_event = FS_EMU_ACTION_PAUSE; while (actions->name) { if (k == MAX_ACTIONS) { From 9835fae26e1a6d766a1e0a19516261299e60ac5d Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 19 Sep 2015 12:17:37 +0200 Subject: [PATCH 21/25] 2.5.41dev --- ChangeLog | 1 + README | 6 ++---- configure.ac | 2 +- debian/changelog | 4 ++-- fs-uae.spec | 4 ++-- po/cs.po | 4 ++-- po/da.po | 4 ++-- po/de.po | 4 ++-- po/el.po | 4 ++-- po/es.po | 14 +++++++------- po/fi.po | 4 ++-- po/fr.po | 4 ++-- po/it.po | 30 +++++++++++++++--------------- po/nb.po | 4 ++-- po/pl.po | 4 ++-- po/pt.po | 4 ++-- po/pt_BR.po | 4 ++-- po/sr.po | 4 ++-- po/sv.po | 4 ++-- po/tr.po | 4 ++-- 20 files changed, 56 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5291f6167..2c0d8fa46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ Version 2.5.41dev: * New option jit_memory (=direct/indirect). * JIT compiler defaults to direct memory access on all platforms now. * JIT direct memory exception handler for OS X (32-bit). +* Imported updated translations from crowdin.com. Version 2.5.40dev: diff --git a/README b/README index 834e5cf90..1b568d9ae 100644 --- a/README +++ b/README @@ -220,7 +220,7 @@ SUPPORTED HOST OPERATING SYSTEM =============================== - Linux - Windows XP or newer -- Mac OS X 10.5 or newer +- Mac OS X 10.6 or newer - FreeBSD (Other Unices will probably also work just fine) @@ -270,12 +270,10 @@ contributors (see the UAE distribution for full credits). WinUAE has been developed and maintained by Mathias Ortmann and Toni Wilen. Toni Wilen has developed WinUAE for the last years and is the current maintainer. E-UAE was developed by Richard Drummond (no longer maintained), -and P-UAE is developed by Mustafa "GnoStiC" TUFAN. +and P-UAE is developed by Mustafa "GnoStiC" TUFAN (no longer maintained). -http://www.amigaemulator.org/ http://www.winuae.net/ http://www.rcdrummond.net/uae/ -https://github.com/GnoStiC/PUAE http://www.softpres.org/ libfsemu is Copyright (c) 2011-2013, Frode Solheim diff --git a/configure.ac b/configure.ac index 6fdcea3bd..ab6657acd 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.67]) -AC_INIT([FS-UAE], [2.5.40dev], +AC_INIT([FS-UAE], [2.5.41dev], [frode@fs-uae.net], [fs-uae], [http://fs-uae.net]) AC_CONFIG_AUX_DIR([.]) AC_CANONICAL_HOST diff --git a/debian/changelog b/debian/changelog index 3494bc3b1..57c1fd8e9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -fs-uae (2.5.40~dev-0) unstable; urgency=low +fs-uae (2.5.41~dev-0) unstable; urgency=low * Dummy changelog entry. - -- Frode Solheim Mon, 31 Aug 2015 19:46:02 +0200 + -- Frode Solheim Sat, 19 Sep 2015 12:00:45 +0200 diff --git a/fs-uae.spec b/fs-uae.spec index 151cc93f5..06843478c 100644 --- a/fs-uae.spec +++ b/fs-uae.spec @@ -1,6 +1,6 @@ %define name fs-uae -%define version 2.5.40dev -%define unmangled_version 2.5.40dev +%define version 2.5.41dev +%define unmangled_version 2.5.41dev %define release 1%{?dist} Summary: Amiga emulator with on-screen GUI and online play support diff --git a/po/cs.po b/po/cs.po index 58e3f039e..f71db578c 100644 --- a/po/cs.po +++ b/po/cs.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Czech\n" "Language: cs_CZ\n" diff --git a/po/da.po b/po/da.po index d81489f9d..ad2de2929 100644 --- a/po/da.po +++ b/po/da.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-15 15:15-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Danish\n" "Language: da_DK\n" diff --git a/po/de.po b/po/de.po index 63c725733..a0c222ebf 100644 --- a/po/de.po +++ b/po/de.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-15 15:15-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: German\n" "Language: de_DE\n" diff --git a/po/el.po b/po/el.po index 502defd95..a2e15486c 100644 --- a/po/el.po +++ b/po/el.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Greek\n" "Language: el_GR\n" diff --git a/po/es.po b/po/es.po index c0318f151..bff1d7a15 100644 --- a/po/es.po +++ b/po/es.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Spanish\n" "Language: es_ES\n" @@ -137,7 +137,7 @@ msgid "Load State" msgstr "Cargar Estado" msgid "Max 1 CD-ROM drive supported currently" -msgstr "" +msgstr "Max 1 CD-ROM disco soportador actualmente" msgid "More..." msgstr "Mas..." @@ -169,16 +169,16 @@ msgid "Option \"%s\" is not enabled" msgstr "Opció \"%s\" no esta activada" msgid "Option chip_memory must be a multiple of 512" -msgstr "Opción chip_memori debe ser mútiplo de 512" +msgstr "Opción chip_memory debe ser mútiplo de 512" msgid "Option fast_memory must be a multiple of 1024" msgstr "Opción fast_memory debe ser mútiplo de 1024" msgid "Option motherboard_ram must be a multiple of 1024" -msgstr "" +msgstr "Opción motherboard_ram debe ser mútiplo de 1024" msgid "Option motherboard_ram needs a CPU with 32-bit addressing" -msgstr "" +msgstr "Opciónmotherboard_ram necesita una CPU con direcciones de 32-bit" msgid "Option slow_memory must be a multiple of 256" msgstr "Opción fast_memory debe ser mútiplo de 256" @@ -190,7 +190,7 @@ msgid "Option zorro_iii_memory must be a multiple of 1024" msgstr "Opción zorro_iii_memory debe ser mútiplo de 1024" msgid "Option zorro_iii_memory needs a CPU with 32-bit addressing" -msgstr "" +msgstr "Opción zorro_iii_memory necesita una CPU con direcciones de 32-bit" #. / TRANSLATORS: This is a menu entry and must not be too long msgid "Parallel Joystick Ports" diff --git a/po/fi.po b/po/fi.po index 5c8eab09e..ff8be5ef8 100644 --- a/po/fi.po +++ b/po/fi.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Finnish\n" "Language: fi_FI\n" diff --git a/po/fr.po b/po/fr.po index ca67b9743..38c745719 100644 --- a/po/fr.po +++ b/po/fr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: French\n" "Language: fr_FR\n" diff --git a/po/it.po b/po/it.po index cf886a103..017e9d9bb 100644 --- a/po/it.po +++ b/po/it.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Italian\n" "Language: it_IT\n" @@ -27,18 +27,18 @@ msgid "Auto" msgstr "Automatico" msgid "Auto-Fire is Off" -msgstr "Fuoco-Automatico Spento" +msgstr "Fuoco automatico disattivato" msgid "Auto-Fire is On" -msgstr "Fuco-Automatico Attivato" +msgstr "Fuoco automatico attivato" #, c-format msgid "Auto-fire disabled for port %d" -msgstr "Fuoco-Automatico disabilitato sulla porta %d" +msgstr "Fuoco automatico disabilitato sulla porta %d" #, c-format msgid "Auto-fire enabled for port %d" -msgstr "Fuoco-Automatico abilitato sulla porta %d" +msgstr "Fuoco automatico abilitato sulla porta %d" #. / TRANSLATORS: Empty or nothing #, c-format @@ -74,7 +74,7 @@ msgstr "Controllo Emulatore" #. / TRANSLATORS: In context "Zoom: Full Frame" msgid "Full Frame" -msgstr "Fotogramma Completo" +msgstr "Fotogramma completo" #, c-format msgid "HD not found: %s" @@ -91,12 +91,12 @@ msgstr "Opzioni di Input" #. / TRANSLATORS: This is a menu entry and must not be too long #, c-format msgid "Insert Into CD%d" -msgstr "Inserisci in CD%d" +msgstr "Inserisci nel CD%d" #. / TRANSLATORS: This is a menu entry and must not be too long #, c-format msgid "Insert Into DF%d" -msgstr "Inserire nel DF%d" +msgstr "Inserisci nel DF%d" msgid "Joystick Mode" msgstr "Modalità joystick" @@ -159,7 +159,7 @@ msgstr "Nessun Dispositivo Amiga" #. / TRANSLATORS: This is a menu entry and must not be too long: If you struggle #. / to get in short enough, just translate "No Device" instead. msgid "No Host Device" -msgstr "Nessun Dispositivo Ospite" +msgstr "Nessun dispositivo ospite" msgid "No configuration file was found" msgstr "Non è stato trovato alcun file di configurazione" @@ -175,10 +175,10 @@ msgid "Option fast_memory must be a multiple of 1024" msgstr "L'opzione fast_memory deve essere un multiplo di 1024" msgid "Option motherboard_ram must be a multiple of 1024" -msgstr "" +msgstr "L'opzione motherboard_ram deve essere un multiplo di 1024" msgid "Option motherboard_ram needs a CPU with 32-bit addressing" -msgstr "" +msgstr "L'opzione motherboard_ram ha bisogno di una CPU con indirizzamento a 32-bit" msgid "Option slow_memory must be a multiple of 256" msgstr "L'opzione slow_memory deve essere un multiplo di 256" @@ -204,10 +204,10 @@ msgid "Port 0: %s" msgstr "Porta 0: %s" msgid "Port Settings" -msgstr "Impostazioni Porta" +msgstr "Impostazioni porta" msgid "Removable Media" -msgstr "Supporti Rimovibili" +msgstr "Supporti rimovibili" #. / TRANSLATORS: Reset Amiga as in reboot the computer msgid "Reset Amiga" @@ -220,7 +220,7 @@ msgid "Save" msgstr "Salva" msgid "Save State" -msgstr "Salva Stato" +msgstr "Salva stato" #. / TRANSLATORS: Soft reset reboots the computer without a power cycle msgid "Soft Reset" diff --git a/po/nb.po b/po/nb.po index f0b033857..7d2a5a50b 100644 --- a/po/nb.po +++ b/po/nb.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-15 15:16-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Norwegian Bokmal\n" "Language: nb_NO\n" diff --git a/po/pl.po b/po/pl.po index 4813e3bb9..7635b2240 100644 --- a/po/pl.po +++ b/po/pl.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-15 15:15-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Polish\n" "Language: pl_PL\n" diff --git a/po/pt.po b/po/pt.po index 186435627..55dd37aa0 100644 --- a/po/pt.po +++ b/po/pt.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Portuguese\n" "Language: pt_PT\n" diff --git a/po/pt_BR.po b/po/pt_BR.po index 9fe23f681..6831fbb46 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Portuguese, Brazilian\n" "Language: pt_BR\n" diff --git a/po/sr.po b/po/sr.po index da99487bb..d6bdf0b77 100644 --- a/po/sr.po +++ b/po/sr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Serbian (Latin)\n" "Language: sr_CS\n" diff --git a/po/sv.po b/po/sv.po index 553289692..1440068df 100644 --- a/po/sv.po +++ b/po/sv.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Swedish\n" "Language: sv_SE\n" diff --git a/po/tr.po b/po/tr.po index c38ce93bb..d3e408ee1 100644 --- a/po/tr.po +++ b/po/tr.po @@ -2,8 +2,8 @@ msgid "" msgstr "" "Project-Id-Version: fs-uae\n" "Report-Msgid-Bugs-To: frode@fs-uae.net\n" -"POT-Creation-Date: 2015-08-09 21:35+0200\n" -"PO-Revision-Date: 2015-08-10 14:41-0400\n" +"POT-Creation-Date: 2015-09-19 12:02+0200\n" +"PO-Revision-Date: 2015-09-19 06:02-0400\n" "Last-Translator: FrodeSolheim \n" "Language-Team: Turkish\n" "Language: tr_TR\n" From 7c8b7cd8eaada98231bbbe8b92327af97b02cfcd Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 19 Sep 2015 13:21:46 +0200 Subject: [PATCH 22/25] Map gamepad select button to pause action --- ChangeLog | 4 + configure.ac | 4 +- libfsemu/{src => include/fs}/emu/actions.h | 0 libfsemu/src/emu/actions.c | 13 +- libfsemu/src/emu/input.c | 4 +- share/fs-uae/input/universal_gamepad.ini | 8 +- src/fs-uae/fs-uae.h | 2 - src/fs-uae/joystick.c | 210 ++++++++++----------- 8 files changed, 121 insertions(+), 124 deletions(-) rename libfsemu/{src => include/fs}/emu/actions.h (100%) diff --git a/ChangeLog b/ChangeLog index 2c0d8fa46..bd1bb6860 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Version 2.5.42dev: + +* Map gamepad select button to pause action. + Version 2.5.41dev: * Implement action_pause to make action key configurable. diff --git a/configure.ac b/configure.ac index ab6657acd..f50a847e3 100644 --- a/configure.ac +++ b/configure.ac @@ -150,8 +150,8 @@ PKG_CHECK_MODULES([OPENAL], [openal], [ AS_CASE([$host_os], [darwin*], [ AC_MSG_NOTICE([Using OpenAL.framework]) - #OPENAL_CFLAGS="-I/System/Library/Frameworks/OpenAL.framework/Headers" - OPENAL_CFLAGS="-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/OpenAL.framework/Headers" + OPENAL_CFLAGS="-I/System/Library/Frameworks/OpenAL.framework/Headers" + # OPENAL_CFLAGS="-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks/OpenAL.framework/Headers" OPENAL_LIBS="-framework OpenAL" ], diff --git a/libfsemu/src/emu/actions.h b/libfsemu/include/fs/emu/actions.h similarity index 100% rename from libfsemu/src/emu/actions.h rename to libfsemu/include/fs/emu/actions.h diff --git a/libfsemu/src/emu/actions.c b/libfsemu/src/emu/actions.c index 88b6ded17..9260862ff 100644 --- a/libfsemu/src/emu/actions.c +++ b/libfsemu/src/emu/actions.c @@ -21,14 +21,12 @@ #endif #include +#include +#include #include - -#include "actions.h" #include "video.h" - #include - static const char* g_taunts[] = { "You play like a dairy farmer!", "No one will ever catch ME playing as badly as you do!", @@ -42,7 +40,8 @@ static const char* g_taunts[] = { }; static int g_num_taunts = 8; -static void taunt() { +static void taunt() +{ char *text = g_strdup_printf("%c%s\n", 1, g_taunts[g_random_int_range(0, g_num_taunts)]); fs_emu_netplay_say(text); @@ -51,7 +50,9 @@ static void taunt() { void fs_emu_handle_libfsemu_action(int action, int state) { - printf("internal action %d %d\n", action, state); + if (g_fs_log_input) { + fs_log("fs_emu_handle_libfsemu_action %d %d\n", action, state); + } if (state) { if (action == FS_EMU_ACTION_TAUNT) { taunt(); diff --git a/libfsemu/src/emu/input.c b/libfsemu/src/emu/input.c index 1f17229dd..122cbe6a4 100644 --- a/libfsemu/src/emu/input.c +++ b/libfsemu/src/emu/input.c @@ -8,7 +8,6 @@ #include #include #include "input.h" - #include #include #include @@ -17,8 +16,7 @@ #include #include #include - -#include "actions.h" +#include #include "hud.h" #include "menu.h" #include "netplay.h" diff --git a/share/fs-uae/input/universal_gamepad.ini b/share/fs-uae/input/universal_gamepad.ini index 6cd5c4d80..cabed3c14 100644 --- a/share/fs-uae/input/universal_gamepad.ini +++ b/share/fs-uae/input/universal_gamepad.ini @@ -32,8 +32,6 @@ dpad_up = up dpad_down = down south_button = 1 west_button = 2 -left_trigger = toggle_autofire -right_trigger = autofire lstick_left = left lstick_right = right @@ -43,6 +41,9 @@ east_button = up north_button = 1 right_shoulder = up left_shoulder = down +left_trigger = toggle_autofire +right_trigger = autofire +select_button = pause [amigacd32] dpad_left = left @@ -61,6 +62,9 @@ lstick_left = left lstick_right = right lstick_up = up lstick_down = down +left_trigger = toggle_autofire +right_trigger = autofire +select_button = pause [amstradcpc] dpad_left = left diff --git a/src/fs-uae/fs-uae.h b/src/fs-uae/fs-uae.h index cb327995c..2c26a6867 100644 --- a/src/fs-uae/fs-uae.h +++ b/src/fs-uae/fs-uae.h @@ -64,8 +64,6 @@ const char *fs_uae_kickstarts_cache_dir(); #define FS_UAE_CONFIG_TYPE_JOYSTICK "amiga" #define FS_UAE_CONFIG_TYPE_MOUSE "amiga_mouse" -#define FS_UAE_MAX_PORT_ACTIONS 16 - #define FS_UAE_NUM_INPUT_PORTS 5 #define MAX_DEVICE_NAME_LEN 128 typedef struct fs_uae_input_port { diff --git a/src/fs-uae/joystick.c b/src/fs-uae/joystick.c index 87a7b426c..b1f8c3f76 100644 --- a/src/fs-uae/joystick.c +++ b/src/fs-uae/joystick.c @@ -7,120 +7,108 @@ #include #include +#include #include "fs-uae.h" #include "config-common.h" fs_uae_input_port g_fs_uae_input_ports[FS_UAE_NUM_INPUT_PORTS] = {}; -static fs_emu_input_mapping g_joystick_mappings[][FS_UAE_MAX_PORT_ACTIONS] = { - // joystick in joystick port 0 - { - { "left", INPUTEVENT_JOY1_LEFT }, - { "right", INPUTEVENT_JOY1_RIGHT }, - { "up", INPUTEVENT_JOY1_UP }, - { "down", INPUTEVENT_JOY1_DOWN }, - { "1", INPUTEVENT_JOY1_FIRE_BUTTON }, - { "2", INPUTEVENT_JOY1_2ND_BUTTON }, - { "3", INPUTEVENT_JOY1_3RD_BUTTON }, - { "red", INPUTEVENT_JOY1_CD32_RED }, - { "yellow", INPUTEVENT_JOY1_CD32_YELLOW }, - { "green", INPUTEVENT_JOY1_CD32_GREEN }, - { "blue", INPUTEVENT_JOY1_CD32_BLUE }, - { "rewind", INPUTEVENT_JOY1_CD32_RWD }, - { "forward", INPUTEVENT_JOY1_CD32_FFW }, - { "play", INPUTEVENT_JOY1_CD32_PLAY }, - { "autofire", INPUTEVENT_JOY1_AUTOFIRE_BUTTON }, - { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE }, - { NULL, 0 }, - }, - // joystick in joystick port 1 - { - { "left", INPUTEVENT_JOY2_LEFT }, - { "right", INPUTEVENT_JOY2_RIGHT }, - { "up", INPUTEVENT_JOY2_UP }, - { "down", INPUTEVENT_JOY2_DOWN }, - { "1", INPUTEVENT_JOY2_FIRE_BUTTON }, - { "2", INPUTEVENT_JOY2_2ND_BUTTON }, - { "3", INPUTEVENT_JOY2_3RD_BUTTON }, - { "red", INPUTEVENT_JOY2_CD32_RED }, - { "yellow", INPUTEVENT_JOY2_CD32_YELLOW }, - { "green", INPUTEVENT_JOY2_CD32_GREEN }, - { "blue", INPUTEVENT_JOY2_CD32_BLUE }, - { "rewind", INPUTEVENT_JOY2_CD32_RWD }, - { "forward", INPUTEVENT_JOY2_CD32_FFW }, - { "play", INPUTEVENT_JOY2_CD32_PLAY }, - { "autofire", INPUTEVENT_JOY2_AUTOFIRE_BUTTON }, - { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_1_AUTOFIRE }, - { NULL, 0 }, - }, - // first parallel port joystick - { - { "left", INPUTEVENT_PAR_JOY1_LEFT }, - { "right", INPUTEVENT_PAR_JOY1_RIGHT }, - { "up", INPUTEVENT_PAR_JOY1_UP }, - { "down", INPUTEVENT_PAR_JOY1_DOWN }, - { "1", INPUTEVENT_PAR_JOY1_FIRE_BUTTON }, - { "2", INPUTEVENT_PAR_JOY1_2ND_BUTTON }, - { "autofire", INPUTEVENT_PAR_JOY1_AUTOFIRE_BUTTON }, - { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_2_AUTOFIRE }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - }, - // second parallel port joystick - { - { "left", INPUTEVENT_PAR_JOY2_LEFT }, - { "right", INPUTEVENT_PAR_JOY2_RIGHT }, - { "up", INPUTEVENT_PAR_JOY2_UP }, - { "down", INPUTEVENT_PAR_JOY2_DOWN }, - { "1", INPUTEVENT_PAR_JOY2_FIRE_BUTTON }, - { "2", INPUTEVENT_PAR_JOY2_2ND_BUTTON }, - { "autofire", INPUTEVENT_PAR_JOY2_AUTOFIRE_BUTTON }, - { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_3_AUTOFIRE }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - }, - // custom joystick, 65536 = no action - { - { "left", 65536 }, - { "right", 65536 }, - { "up", 65536 }, - { "down", 65536 }, - { "1", 65536 }, - { "2", 65536 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - { NULL, 0 }, - }, +#define NO_ACTION 65536 + +#define COMMON_ACTIONS \ + { "pause", FS_EMU_ACTION_PAUSE }, + +static fs_emu_input_mapping g_joystick_port_0_mapping[] = { + { "left", INPUTEVENT_JOY1_LEFT }, + { "right", INPUTEVENT_JOY1_RIGHT }, + { "up", INPUTEVENT_JOY1_UP }, + { "down", INPUTEVENT_JOY1_DOWN }, + { "1", INPUTEVENT_JOY1_FIRE_BUTTON }, + { "2", INPUTEVENT_JOY1_2ND_BUTTON }, + { "3", INPUTEVENT_JOY1_3RD_BUTTON }, + { "red", INPUTEVENT_JOY1_CD32_RED }, + { "yellow", INPUTEVENT_JOY1_CD32_YELLOW }, + { "green", INPUTEVENT_JOY1_CD32_GREEN }, + { "blue", INPUTEVENT_JOY1_CD32_BLUE }, + { "rewind", INPUTEVENT_JOY1_CD32_RWD }, + { "forward", INPUTEVENT_JOY1_CD32_FFW }, + { "play", INPUTEVENT_JOY1_CD32_PLAY }, + { "autofire", INPUTEVENT_JOY1_AUTOFIRE_BUTTON }, + { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_0_AUTOFIRE }, + COMMON_ACTIONS + { NULL, 0 }, }; -void fs_uae_read_override_actions_for_port(int port) { +static fs_emu_input_mapping g_joystick_port_1_mapping[] = { + { "left", INPUTEVENT_JOY2_LEFT }, + { "right", INPUTEVENT_JOY2_RIGHT }, + { "up", INPUTEVENT_JOY2_UP }, + { "down", INPUTEVENT_JOY2_DOWN }, + { "1", INPUTEVENT_JOY2_FIRE_BUTTON }, + { "2", INPUTEVENT_JOY2_2ND_BUTTON }, + { "3", INPUTEVENT_JOY2_3RD_BUTTON }, + { "red", INPUTEVENT_JOY2_CD32_RED }, + { "yellow", INPUTEVENT_JOY2_CD32_YELLOW }, + { "green", INPUTEVENT_JOY2_CD32_GREEN }, + { "blue", INPUTEVENT_JOY2_CD32_BLUE }, + { "rewind", INPUTEVENT_JOY2_CD32_RWD }, + { "forward", INPUTEVENT_JOY2_CD32_FFW }, + { "play", INPUTEVENT_JOY2_CD32_PLAY }, + { "autofire", INPUTEVENT_JOY2_AUTOFIRE_BUTTON }, + { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_1_AUTOFIRE }, + COMMON_ACTIONS + { NULL, 0 }, +}; + +static fs_emu_input_mapping g_parallel_port_1st_mapping[] = { + { "left", INPUTEVENT_PAR_JOY1_LEFT }, + { "right", INPUTEVENT_PAR_JOY1_RIGHT }, + { "up", INPUTEVENT_PAR_JOY1_UP }, + { "down", INPUTEVENT_PAR_JOY1_DOWN }, + { "1", INPUTEVENT_PAR_JOY1_FIRE_BUTTON }, + { "2", INPUTEVENT_PAR_JOY1_2ND_BUTTON }, + { "autofire", INPUTEVENT_PAR_JOY1_AUTOFIRE_BUTTON }, + { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_2_AUTOFIRE }, + COMMON_ACTIONS + { NULL, 0 }, +}; + +static fs_emu_input_mapping g_parallel_port_2nd_mapping[] = { + { "left", INPUTEVENT_PAR_JOY2_LEFT }, + { "right", INPUTEVENT_PAR_JOY2_RIGHT }, + { "up", INPUTEVENT_PAR_JOY2_UP }, + { "down", INPUTEVENT_PAR_JOY2_DOWN }, + { "1", INPUTEVENT_PAR_JOY2_FIRE_BUTTON }, + { "2", INPUTEVENT_PAR_JOY2_2ND_BUTTON }, + { "autofire", INPUTEVENT_PAR_JOY2_AUTOFIRE_BUTTON }, + { "toggle_autofire", INPUTEVENT_AMIGA_JOYPORT_3_AUTOFIRE }, + COMMON_ACTIONS + { NULL, 0 }, +}; + +static fs_emu_input_mapping g_custom_port_mapping[] = { + { "left", NO_ACTION }, + { "right", NO_ACTION }, + { "up", NO_ACTION }, + { "down", NO_ACTION }, + { "1", NO_ACTION }, + { "2", NO_ACTION }, + { NULL, 0 }, +}; + +static fs_emu_input_mapping *g_joystick_mappings[] = { + g_joystick_port_0_mapping, + g_joystick_port_1_mapping, + g_parallel_port_1st_mapping, + g_parallel_port_2nd_mapping, + g_custom_port_mapping, +}; + +void fs_uae_read_override_actions_for_port(int port) +{ fs_log("fs_uae_read_override_actions_for_port %d\n", port); fs_emu_input_mapping *mapping = g_joystick_mappings[port]; - for (int i = 0; i < FS_UAE_MAX_PORT_ACTIONS; i++) { - if (mapping[i].name == NULL) { - continue; - } + for (int i = 0; mapping[i].name != NULL; i++) { const char* name = mapping[i].name; if (strcmp(name, "1") == 0) { name = "primary"; @@ -143,7 +131,8 @@ void fs_uae_read_override_actions_for_port(int port) { } } -static void map_mouse(const char *device_name, int port) { +static void map_mouse(const char *device_name, int port) +{ fs_log("mapping mouse to port %d\n", port); if (port == 0) { fs_emu_configure_mouse(device_name, INPUTEVENT_MOUSE1_HORIZ, @@ -163,7 +152,8 @@ static void map_mouse(const char *device_name, int port) { } static void configure_joystick_port(int port, const char *value, - const char *port_name, const char *joy_dev) { + const char *port_name, const char *joy_dev) +{ fs_emu_log("configuring joystick port %d (%s)\n", port, value); fs_uae_input_port *p = g_fs_uae_input_ports + port; @@ -320,7 +310,8 @@ void fs_uae_configure_input() g_free(value); } -void fs_uae_reconfigure_input_ports_amiga() { +void fs_uae_reconfigure_input_ports_amiga() +{ fs_emu_log("fs_uae_reconfigure_input_ports_amiga\n"); int modes = INPUTEVENT_AMIGA_JOYPORT_MODE_0_LAST - INPUTEVENT_AMIGA_JOYPORT_MODE_0_NONE + 1; @@ -345,7 +336,8 @@ void fs_uae_reconfigure_input_ports_amiga() { } } -void fs_uae_reconfigure_input_ports_host() { +void fs_uae_reconfigure_input_ports_host() +{ fs_emu_log("fs_uae_reconfigure_input_ports_host\n"); fs_emu_reset_input_mapping(); fs_uae_map_keyboard(); From 75d8791999a7e807124cbbc8e796274052596bd9 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 19 Sep 2015 13:38:52 +0200 Subject: [PATCH 23/25] Map gamepad start button to menu when in Amiga joystick mode (not CD32) --- ChangeLog | 1 + libfsemu/include/fs/emu/actions.h | 2 ++ libfsemu/src/emu/actions.c | 10 +++++----- libfsemu/src/emu/menu.c | 8 ++++++-- share/fs-uae/input/universal_gamepad.ini | 1 + src/fs-uae/joystick.c | 1 + 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd1bb6860..5975ef772 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ Version 2.5.42dev: +* Map gamepad start button to menu when in Amiga joystick mode (not CD32). * Map gamepad select button to pause action. Version 2.5.41dev: diff --git a/libfsemu/include/fs/emu/actions.h b/libfsemu/include/fs/emu/actions.h index 9839f035a..33a68fc13 100644 --- a/libfsemu/include/fs/emu/actions.h +++ b/libfsemu/include/fs/emu/actions.h @@ -4,7 +4,9 @@ #define FS_EMU_ACTION_TAUNT 0xc001 #define FS_EMU_ACTION_SCREENSHOT 0xc002 #define FS_EMU_ACTION_PAUSE 0xc003 +#define FS_EMU_ACTION_MENU_ALT 0xc004 void fs_emu_handle_libfsemu_action(int action, int state); #endif /* LIBFSEMU_ACTIONS_H */ + diff --git a/libfsemu/src/emu/actions.c b/libfsemu/src/emu/actions.c index 9260862ff..945b79ac6 100644 --- a/libfsemu/src/emu/actions.c +++ b/libfsemu/src/emu/actions.c @@ -54,13 +54,13 @@ void fs_emu_handle_libfsemu_action(int action, int state) fs_log("fs_emu_handle_libfsemu_action %d %d\n", action, state); } if (state) { - if (action == FS_EMU_ACTION_TAUNT) { + if (action == FS_EMU_ACTION_MENU_ALT) { + fs_emu_menu_toggle(); + } else if (action == FS_EMU_ACTION_TAUNT) { taunt(); - } - else if (action == FS_EMU_ACTION_SCREENSHOT) { + } else if (action == FS_EMU_ACTION_SCREENSHOT) { g_fs_emu_screenshot = 1; - } - else if (action == FS_EMU_ACTION_PAUSE) { + } else if (action == FS_EMU_ACTION_PAUSE) { fs_emu_pause(!fs_emu_is_paused()); } } diff --git a/libfsemu/src/emu/menu.c b/libfsemu/src/emu/menu.c index ffa8446e9..15a886547 100644 --- a/libfsemu/src/emu/menu.c +++ b/libfsemu/src/emu/menu.c @@ -181,6 +181,9 @@ void fs_emu_menu_function(int action, int state) { else if (action == ACTION_MENU_BACK) { go_back_in_menu_stack(); } + else if (action == ACTION_MENU_START) { + fs_emu_menu_toggle(); + } else if (action == ACTION_MENU_ESCAPE) { if (!go_back_in_menu_stack()) { // no more menus to back out of, go out of menu mode instead @@ -680,8 +683,9 @@ void fs_emu_menu_render(double transition) { glPopMatrix(); } -void fs_emu_menu_toggle() { - fs_emu_log("fs_emu_toggle_menu\n"); +void fs_emu_menu_toggle() +{ + fs_emu_log("fs_emu_menu_toggle\n"); if (g_fs_emu_menu_mode) { // leave menu g_fs_emu_menu_mode = 0; diff --git a/share/fs-uae/input/universal_gamepad.ini b/share/fs-uae/input/universal_gamepad.ini index cabed3c14..b5e8b3d2a 100644 --- a/share/fs-uae/input/universal_gamepad.ini +++ b/share/fs-uae/input/universal_gamepad.ini @@ -44,6 +44,7 @@ left_shoulder = down left_trigger = toggle_autofire right_trigger = autofire select_button = pause +start_button = menu_alt [amigacd32] dpad_left = left diff --git a/src/fs-uae/joystick.c b/src/fs-uae/joystick.c index b1f8c3f76..1d0307015 100644 --- a/src/fs-uae/joystick.c +++ b/src/fs-uae/joystick.c @@ -16,6 +16,7 @@ fs_uae_input_port g_fs_uae_input_ports[FS_UAE_NUM_INPUT_PORTS] = {}; #define NO_ACTION 65536 #define COMMON_ACTIONS \ + { "menu_alt", FS_EMU_ACTION_MENU_ALT }, \ { "pause", FS_EMU_ACTION_PAUSE }, static fs_emu_input_mapping g_joystick_port_0_mapping[] = { From 491ed89be512654af1d32dab247af8c7bef777a5 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 19 Sep 2015 15:54:38 +0200 Subject: [PATCH 24/25] Added/updated some XInput controller configs for DirectInput mode --- ChangeLog | 1 + ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 43 +++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++ ...000000000000504944564944.fs-uae-controller | 42 ++++++++++++++++ ...troller_gamepad_f310_10_5_1_0_windows.conf | 48 ++++++++++++------- ..._rumble_gamepad_f510_10_5_1_0_windows.conf | 48 ++++++++++++------- ...ireless_gamepad_f710_10_5_1_0_windows.conf | 48 ++++++++++++------- ...xbox_360_for_windows_10_5_1_0_windows.conf | 48 ++++++++++++------- ...receiver_for_windows_10_5_1_0_windows.conf | 48 ++++++++++++------- ...xbox_one_for_windows_11_6_1_0_windows.conf | 43 +++++++++++++++++ 13 files changed, 452 insertions(+), 85 deletions(-) create mode 100644 share/fs-uae/input/5e048e02000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/5e04a102000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/5e04d102000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/6d041dc2000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/6d041ec2000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/6d041fc2000000000000504944564944.fs-uae-controller create mode 100644 share/fs-uae/input/controller_xbox_one_for_windows_11_6_1_0_windows.conf diff --git a/ChangeLog b/ChangeLog index 5975ef772..3dea0bebb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ Version 2.5.42dev: * Map gamepad start button to menu when in Amiga joystick mode (not CD32). * Map gamepad select button to pause action. +* Added/updated some XInput controller configs for DirectInput mode. Version 2.5.41dev: diff --git a/share/fs-uae/input/5e048e02000000000000504944564944.fs-uae-controller b/share/fs-uae/input/5e048e02000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..24f95c18a --- /dev/null +++ b/share/fs-uae/input/5e048e02000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Controller (XBOX 360 For Windows) +platform = windows + +[device] +make = Microsoft +model = Xbox 360 Pad +type = gamepad + +[sdl] +guid = 5e048e02000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/5e04a102000000000000504944564944.fs-uae-controller b/share/fs-uae/input/5e04a102000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..4fa2a4b70 --- /dev/null +++ b/share/fs-uae/input/5e04a102000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Controller (Xbox 360 Wireless Receiver for Windows) +platform = windows + +[device] +make = Microsoft +model = Xbox 360 Pad +type = gamepad + +[sdl] +guid = 5e04a102000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/5e04d102000000000000504944564944.fs-uae-controller b/share/fs-uae/input/5e04d102000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..bcaf6de96 --- /dev/null +++ b/share/fs-uae/input/5e04d102000000000000504944564944.fs-uae-controller @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Controller (XBOX One For Windows) +platform = windows + +[device] +make = Microsoft +model = Xbox One Pad +type = gamepad + +[sdl] +guid = 5e04d102000000000000504944564944 +buttons = 11 +hats = 1 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = left_shoulder +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_2 = west_button +button_3 = north_button +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/6d041dc2000000000000504944564944.fs-uae-controller b/share/fs-uae/input/6d041dc2000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..ff43b7e22 --- /dev/null +++ b/share/fs-uae/input/6d041dc2000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Controller (Gamepad F310) +platform = windows + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d041dc2000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/6d041ec2000000000000504944564944.fs-uae-controller b/share/fs-uae/input/6d041ec2000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..fafe385ec --- /dev/null +++ b/share/fs-uae/input/6d041ec2000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Controller (Rumble Gamepad F510) +platform = windows + +[device] +make = Logitech +model = F510 +type = gamepad + +[sdl] +guid = 6d041ec2000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/6d041fc2000000000000504944564944.fs-uae-controller b/share/fs-uae/input/6d041fc2000000000000504944564944.fs-uae-controller new file mode 100644 index 000000000..5eeefc569 --- /dev/null +++ b/share/fs-uae/input/6d041fc2000000000000504944564944.fs-uae-controller @@ -0,0 +1,42 @@ +[fs-uae-controller] +name = Controller (Wireless Gamepad F710) +platform = windows + +[device] +make = Logitech +model = F710 +type = gamepad + +[sdl] +guid = 6d041fc2000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button +button_2 = west_button +button_3 = north_button +button_4 = left_shoulder +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/controller_gamepad_f310_10_5_1_0_windows.conf b/share/fs-uae/input/controller_gamepad_f310_10_5_1_0_windows.conf index f82d7a3f6..ff43b7e22 100644 --- a/share/fs-uae/input/controller_gamepad_f310_10_5_1_0_windows.conf +++ b/share/fs-uae/input/controller_gamepad_f310_10_5_1_0_windows.conf @@ -1,28 +1,42 @@ -# Controller (Gamepad F310) +[fs-uae-controller] +name = Controller (Gamepad F310) +platform = windows + +[device] +make = Logitech +model = F310 +type = gamepad + +[sdl] +guid = 6d041dc2000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 [default] include = universal_gamepad -hat_0_left = dpad_left -hat_0_right = dpad_right -hat_0_up = dpad_up -hat_0_down = dpad_down axis_0_neg = lstick_left axis_0_pos = lstick_right axis_1_neg = lstick_up axis_1_pos = lstick_down -button_8 = lstick_button -axis_4_neg = rstick_left -axis_4_pos = rstick_right -axis_3_neg = rstick_up -axis_3_pos = rstick_down -button_9 = rstick_button +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button button_2 = west_button button_3 = north_button -button_1 = east_button -button_0 = south_button -button_6 = select_button -button_7 = start_button button_4 = left_shoulder -axis_2_pos = left_trigger button_5 = right_shoulder -axis_2_neg = right_trigger +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/controller_rumble_gamepad_f510_10_5_1_0_windows.conf b/share/fs-uae/input/controller_rumble_gamepad_f510_10_5_1_0_windows.conf index ef8eee971..fafe385ec 100644 --- a/share/fs-uae/input/controller_rumble_gamepad_f510_10_5_1_0_windows.conf +++ b/share/fs-uae/input/controller_rumble_gamepad_f510_10_5_1_0_windows.conf @@ -1,28 +1,42 @@ -# Controller (Rumble Gamepad F510) +[fs-uae-controller] +name = Controller (Rumble Gamepad F510) +platform = windows + +[device] +make = Logitech +model = F510 +type = gamepad + +[sdl] +guid = 6d041ec2000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 [default] include = universal_gamepad -hat_0_left = dpad_left -hat_0_right = dpad_right -hat_0_up = dpad_up -hat_0_down = dpad_down axis_0_neg = lstick_left axis_0_pos = lstick_right axis_1_neg = lstick_up axis_1_pos = lstick_down -button_8 = lstick_button -axis_4_neg = rstick_left -axis_4_pos = rstick_right -axis_3_neg = rstick_up -axis_3_pos = rstick_down -button_9 = rstick_button +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button button_2 = west_button button_3 = north_button -button_1 = east_button -button_0 = south_button -button_6 = select_button -button_7 = start_button button_4 = left_shoulder -axis_2_pos = left_trigger button_5 = right_shoulder -axis_2_neg = right_trigger +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/controller_wireless_gamepad_f710_10_5_1_0_windows.conf b/share/fs-uae/input/controller_wireless_gamepad_f710_10_5_1_0_windows.conf index 2cd16ecf1..5eeefc569 100644 --- a/share/fs-uae/input/controller_wireless_gamepad_f710_10_5_1_0_windows.conf +++ b/share/fs-uae/input/controller_wireless_gamepad_f710_10_5_1_0_windows.conf @@ -1,28 +1,42 @@ -# Controller (Wireless Gamepad F710) +[fs-uae-controller] +name = Controller (Wireless Gamepad F710) +platform = windows + +[device] +make = Logitech +model = F710 +type = gamepad + +[sdl] +guid = 6d041fc2000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 [default] include = universal_gamepad -hat_0_left = dpad_left -hat_0_right = dpad_right -hat_0_up = dpad_up -hat_0_down = dpad_down axis_0_neg = lstick_left axis_0_pos = lstick_right axis_1_neg = lstick_up axis_1_pos = lstick_down -button_8 = lstick_button -axis_4_neg = rstick_left -axis_4_pos = rstick_right -axis_3_neg = rstick_up -axis_3_pos = rstick_down -button_9 = rstick_button +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button button_2 = west_button button_3 = north_button -button_1 = east_button -button_0 = south_button -button_6 = select_button -button_7 = start_button button_4 = left_shoulder -axis_2_pos = left_trigger button_5 = right_shoulder -axis_2_neg = right_trigger +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/controller_xbox_360_for_windows_10_5_1_0_windows.conf b/share/fs-uae/input/controller_xbox_360_for_windows_10_5_1_0_windows.conf index e163ee780..24f95c18a 100644 --- a/share/fs-uae/input/controller_xbox_360_for_windows_10_5_1_0_windows.conf +++ b/share/fs-uae/input/controller_xbox_360_for_windows_10_5_1_0_windows.conf @@ -1,28 +1,42 @@ -# Controller (XBOX 360 For Windows) +[fs-uae-controller] +name = Controller (XBOX 360 For Windows) +platform = windows + +[device] +make = Microsoft +model = Xbox 360 Pad +type = gamepad + +[sdl] +guid = 5e048e02000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 [default] include = universal_gamepad -hat_0_left = dpad_left -hat_0_right = dpad_right -hat_0_up = dpad_up -hat_0_down = dpad_down axis_0_neg = lstick_left axis_0_pos = lstick_right axis_1_neg = lstick_up axis_1_pos = lstick_down -button_8 = lstick_button -axis_4_neg = rstick_left -axis_4_pos = rstick_right -axis_3_neg = rstick_up -axis_3_pos = rstick_down -button_9 = rstick_button +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button button_2 = west_button button_3 = north_button -button_1 = east_button -button_0 = south_button -button_6 = select_button -button_7 = start_button button_4 = left_shoulder -axis_2_pos = left_trigger button_5 = right_shoulder -axis_2_neg = right_trigger +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/controller_xbox_360_wireless_receiver_for_windows_10_5_1_0_windows.conf b/share/fs-uae/input/controller_xbox_360_wireless_receiver_for_windows_10_5_1_0_windows.conf index 7f383343a..4fa2a4b70 100644 --- a/share/fs-uae/input/controller_xbox_360_wireless_receiver_for_windows_10_5_1_0_windows.conf +++ b/share/fs-uae/input/controller_xbox_360_wireless_receiver_for_windows_10_5_1_0_windows.conf @@ -1,28 +1,42 @@ -# Controller (Xbox 360 Wireless Receiver for Windows) +[fs-uae-controller] +name = Controller (Xbox 360 Wireless Receiver for Windows) +platform = windows + +[device] +make = Microsoft +model = Xbox 360 Pad +type = gamepad + +[sdl] +guid = 5e04a102000000000000504944564944 +buttons = 10 +hats = 1 +axes = 5 +balls = 0 [default] include = universal_gamepad -hat_0_left = dpad_left -hat_0_right = dpad_right -hat_0_up = dpad_up -hat_0_down = dpad_down axis_0_neg = lstick_left axis_0_pos = lstick_right axis_1_neg = lstick_up axis_1_pos = lstick_down -button_8 = lstick_button -axis_4_neg = rstick_left -axis_4_pos = rstick_right -axis_3_neg = rstick_up -axis_3_pos = rstick_down -button_9 = rstick_button +axis_2_neg = right_trigger +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +button_0 = south_button +button_1 = east_button button_2 = west_button button_3 = north_button -button_1 = east_button -button_0 = south_button -button_6 = select_button -button_7 = start_button button_4 = left_shoulder -axis_2_pos = left_trigger button_5 = right_shoulder -axis_2_neg = right_trigger +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up diff --git a/share/fs-uae/input/controller_xbox_one_for_windows_11_6_1_0_windows.conf b/share/fs-uae/input/controller_xbox_one_for_windows_11_6_1_0_windows.conf new file mode 100644 index 000000000..bcaf6de96 --- /dev/null +++ b/share/fs-uae/input/controller_xbox_one_for_windows_11_6_1_0_windows.conf @@ -0,0 +1,43 @@ +[fs-uae-controller] +name = Controller (XBOX One For Windows) +platform = windows + +[device] +make = Microsoft +model = Xbox One Pad +type = gamepad + +[sdl] +guid = 5e04d102000000000000504944564944 +buttons = 11 +hats = 1 +axes = 6 +balls = 0 + +[default] +include = universal_gamepad +axis_0_neg = lstick_left +axis_0_pos = lstick_right +axis_1_neg = lstick_up +axis_1_pos = lstick_down +axis_2_neg = left_shoulder +axis_2_pos = left_trigger +axis_3_neg = rstick_left +axis_3_pos = rstick_right +axis_4_neg = rstick_up +axis_4_pos = rstick_down +axis_5_pos = right_trigger +button_0 = south_button +button_1 = east_button +button_10 = menu_button +button_2 = west_button +button_3 = north_button +button_5 = right_shoulder +button_6 = select_button +button_7 = start_button +button_8 = lstick_button +button_9 = rstick_button +hat_0_down = dpad_down +hat_0_left = dpad_left +hat_0_right = dpad_right +hat_0_up = dpad_up From faded6ca5eaa7b8e1460646a30617caa7e1f44c8 Mon Sep 17 00:00:00 2001 From: Frode Solheim Date: Sat, 19 Sep 2015 16:04:15 +0200 Subject: [PATCH 25/25] Fixed make dist(check) --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 6ab4050f9..3aeea2a1d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -554,6 +554,7 @@ libfsemu_a_SOURCES = \ libfsemu/include/fs/data.h \ libfsemu/include/fs/defines.h \ libfsemu/include/fs/emu.h \ + libfsemu/include/fs/emu/actions.h \ libfsemu/include/fs/emu/audio.h \ libfsemu/include/fs/emu/benchmark.h \ libfsemu/include/fs/emu/buffer.h \ @@ -594,7 +595,6 @@ libfsemu_a_SOURCES = \ libfsemu/src/conf.c \ libfsemu/src/data.c \ libfsemu/src/emu/actions.c \ - libfsemu/src/emu/actions.h \ libfsemu/src/emu/audio.h \ libfsemu/src/emu/audio_common.c \ libfsemu/src/emu/audio_debug.c \