From 02571b8957f0fc9fc76798f4fb898ba13e99b2d6 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sat, 6 Feb 2021 16:42:43 +0100 Subject: [PATCH] various improvements in GUI, mainly on fx-9860G * True convention for F-keys: -> Corner = change tab -> Round (button) = perform action -> White = other display changes with no consequence * mem: Move quickly with Shift * mem: Jump to destination with F1 * gint/cpumem: More interesting values * abuse mini font, scrollbars instead of triangles, quick moves * fix a fair amoutn of warnings --- CMakeLists.txt | 1 + assets-fx/fonts/fxconv-metadata.txt | 9 ++ assets-fx/fonts/mini.png | Bin 0 -> 16089 bytes assets-fx/img/opt_dump.png | Bin 2575 -> 2597 bytes assets-fx/img/opt_gint_bopti.png | Bin 4981 -> 5010 bytes assets-fx/img/opt_gint_gray.png | Bin 2570 -> 2771 bytes assets-fx/img/opt_gint_ram.png | Bin 2401 -> 2419 bytes assets-fx/img/opt_gint_rtc.png | Bin 13327 -> 13193 bytes assets-fx/img/opt_gint_spuram.png | Bin 2195 -> 2281 bytes assets-fx/img/opt_gint_timer_callbacks.png | Bin 2206 -> 2279 bytes assets-fx/img/opt_gint_timers.png | Bin 2602 -> 2651 bytes assets-fx/img/opt_gint_tlb.png | Bin 3020 -> 3069 bytes assets-fx/img/opt_main.png | Bin 3462 -> 3525 bytes assets-fx/img/opt_mem.png | Bin 3898 -> 3918 bytes assets-fx/img/opt_switch.png | Bin 2614 -> 2245 bytes assets-fx/img/tlb_cells.png | Bin 3496 -> 3453 bytes include/gintctl/menu.h | 9 +- include/gintctl/util.h | 18 ++- src/gint/bopti.c | 1 - src/gint/cpumem.c | 134 ++++++++++------ src/gint/ram.c | 49 +++--- src/gint/spuram.c | 17 +- src/gint/switch.c | 18 +-- src/gint/timer.c | 14 +- src/gint/tlb.c | 177 ++++++++++----------- src/gintctl.c | 7 +- src/libs/openlibm.c | 1 + src/libs/printf.c | 49 +++--- src/mem/mem.c | 134 +++++++++++++--- src/menu.c | 20 ++- src/util.c | 23 +++ 31 files changed, 447 insertions(+), 234 deletions(-) create mode 100644 assets-fx/fonts/mini.png diff --git a/CMakeLists.txt b/CMakeLists.txt index c51e027..6c0e852 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ set(SOURCES ) set(ASSETS_fx assets-fx/fonts/hexa.png + assets-fx/fonts/mini.png assets-fx/fonts/uf5x7 assets-fx/img/bopti_1col.png assets-fx/img/bopti_2col.png diff --git a/assets-fx/fonts/fxconv-metadata.txt b/assets-fx/fonts/fxconv-metadata.txt index c0613ab..1ada7a3 100644 --- a/assets-fx/fonts/fxconv-metadata.txt +++ b/assets-fx/fonts/fxconv-metadata.txt @@ -5,6 +5,15 @@ hexa.png: grid.size: 3x5 grid.padding: 1 +mini.png: + type: font + name: font_mini + charset: ascii + proportional: true + height: 5 + grid.size: 5x6 + grid.padding: 1 + uf5x7: type: font name: font_uf5x7 diff --git a/assets-fx/fonts/mini.png b/assets-fx/fonts/mini.png new file mode 100644 index 0000000000000000000000000000000000000000..a29757cee7af9b17de5ace95f9d08cab03a42f88 GIT binary patch literal 16089 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 literal 0 HcmV?d00001 diff --git a/assets-fx/img/opt_dump.png b/assets-fx/img/opt_dump.png index 67bd0f09071a2a69471bb14f0e86f6055d92d942..46a22122150565f143b90db86fd40c6ec703b3f5 100644 GIT binary patch delta 2534 zcmVYyMfkA{7jCLl-ff+y@Yi@R?>VDyvf@cKYCLiCJZYw!O0-myhP0BUo0Q{8 zhZt+VSvcl=a(U-Qkv#J$v7}P{nJi10Maw9;oP0|uHI)1vOM3gxx8F&Foi%Z3PArzV z<-b0|UtREbo@OUfqm;aVnCVk1;>y`^NM6R`uUrNo$-Z!FufRW^-;eMMumuF$EAt@1 z758U}-O^8Pl}CWWb&cbPUrE$a%a0|My&J)#0tB(A(o#=Ra+Z{8$pe5Ek>^tL27%OC zR)Wm6lnyon99yX?B# z?pyZQbFTw^PCf1PBWIj>mS!zlwP{z;p;OmQ7b=BYZ@c}<9e3VkaLtNUYt~I{*tGSH z+83(-@%$f9OJAse<%g7CC*P=XR>T*2OCb|KLM0EUZp#OYLgvrI>ZrnWrsrkp#AU6~%H z-J;~Cwx{hKY@BIDUM6`mKoiH47ZMcFAr^*WC;S)las27q%Awj9hK{-F&D0B5X|@h1OxFJqy)*6J#z394O zDKNNG`3?_UW8w?boo8!aySb${HW<}8mMqK)q|Tg-z&aqQKDEK`twqSW*;(Mw9Sa73 zqekkb4!x+AM2p2Hcq|5nmA#xW`5^FwzufLO_qRkR+JUm@SiTUB?E$XEeQskL zGjlrv^c!E27_tmB)6h)a*%Wd;inv*SB^&{auZ2u76SmEBQ+qwu=3uRg1}kp)>P0p$ zjZ%G1B*v?Kxkb71DFsyss)e157GhmJ<_^-68KCcd4o*Q*4Ligw+Z-8L*|=pH?UDQ& zJcq4YZb;Q4>X1{p1?aKBo3P)5+(b7~25ptJ%d5eGFJr7;N!#ukBj)R zz=rEOBrt;^3Z`duI2kYwo1w}p;Y@zB@SVK8$)x+_@GL_Uiq6<2nL1y87{n|8;%|@P zmlOEM!>n6N&xgx+V*obH@NdZI z*RULpr^JLi%XeH|J+AS8Yg`Tc(e^om0e|9xnph{(N@um;fnk6kW*!$_?tP2mVo&(- zn^Ef1KBDCwX#dkOeI|Q}GHAJAocAc9Ks2tEU51Zgh0rLayIYq>8E(~2TrjfM9nrCq z$M_)|s#7SV*}idMbq%1xS|W`*F$^z?z7P1x%}z?Pomjt6!4F3~C?GJLpNB*JXQme4BEx{aiKEhg= zMJ97eV^ENZ%+_{qtqh#!4Rz13@B#&h@NfUD;Y(sB^OpdV7zrJJy_ZsmsJJWx{J1&te>1Pr z#ReWtbx1o1pTo5`llmaqp5pm%*xZ`3pwY-8tMs z_~1}q*V&YH+v>$RCe*gdg delta 2537 zcmV(LC~&C`pPR$+F6jBVDrWd_|-L$=|W0x9@oS?bO-%BreT~#S*vt z*CYJh1;2Bc?MRJM@?xfcPpyb6XU8FV8O5Ku3_y~7;Z|RPe;nVB@C&d4g7uZTli-Z& zv&5?DC%5DgK)9}Q{_rd5an$l-Nn!6wFiC(Qwj?#R6g6i}sYvbsG>JS*$qNKht@#jS zE+P$VIy_=;?$PwF%{6~MM=Ib`rHO*gkO^3&RQRK%!=YKFmRf6nt6F;bl0FIi>P)t0Wl z#+n=Y?6T`_TX)}M&y$awa_VVEPe0?#n=Vuex7>Q$)!Xm5)8Lwk6|2@vt=q8qjoKHg z|8e{esHHE|@e!qVXGjeQ%T2jj`o``ja=(pRpw@qfTmBv7fbuKsF0GFlh`;kj3=1pc)OqZl)I`i0>x|T_m2*~0rKLT8M=Y3Cy76#dn`yF}>aOr8 z#nYtPiAch%7hQ(^?QSxot-6P*wQU3*`!bP{NMN72m94eid-^2&U>%sw9p|QP9$ZYP zuG&_&C8zI1VscwqD-GkeUQHe`<|J=L4j1ch+O68c!|ZDBoec))~k+C9|P?iM@S zhAstmA#J;V^T4T%#_SmN1iF2KcP(F_7f+T&@jF^UuZ>v7d!1zYd8VQJ4za7l!?Y`h z+>WhbYXw_gT_wULH?!E9+E%rAvGt{pW8F=kxDz0kW!}WCwu)@H5%nrvdL#`4HfLfZ z{c#%Kd!~(b5E^Xvh~g4IzwgkMzb^UckgNs@=3noBps4DO!Q-tbeY-h4U>Fo^w=OAp|m_PhO8x#P}SR=_H*Rwy5 zfQw-PfG{b`W!!S$ON7D@M0Q$KETxN1f&*;bbIuouHt01sO?Q5$PEvCMqYj|o0{TZ8UX5eWhyfO*4~ zx~$_!KWt#zgnh@uLSzYfEZw_Pw7JJxjq-NQ*d5eg*J<{c6%yP~r!;GI!sK3bU9l7x z+^Bqm2d**oh3U?tR7@8l$Gs3u166!tArzefbq4E31+~yv2Uuc$J*$uRnTC;EnmIJ=A|LU z=R{(>r%ksgS3aen3gH}KC!>W}J05cb>A?)p*4i7VAgPKS;+A#vjI69*nMQjg{|e7x z>(U!iv4}c!7j6N1Ebu1mcOy4F3!`@mT+*Xa(YnXBi!Gqk67k!Gy1f(?iFnX|k(DwR z6YvD~eU`dx;6Pj#@K!~6_`@onR1b}6XKGV=61r_{LAh!zq&g4gjTl|i*hA5$#shIk zS>5#UCXcbX{nW2!7q^UB*e}os$g{t=I{YQSKA`1Gm=+nGN9W3Sw&%9`nnEk(U^#@I zBQ|oUx;sWJv23pQ@`=rJyw@pzk}Kv0afiFGw(QCy19$&oRFIz(V(>38zz`X5zf~BD zEEaYzbWeN}TS>1K;YQV|MPEoS`kkA1o#i6Dv=xR?Dv5vNIVQ;bAaDjBCnk7Y#E%75 zT-PCi84OV{Js*dY0b{cns=ONZ;5Q53>C2l;nokbTGEPF#8M`D?=L>^>c;R3C%X9eU z1Gh{T!#_!FFtR}B_K9UOM?N5s8@bXu=$FhCwI7mIWE*bv=>{%%kHIoXl!14lQkmlB zd2dO1Q)qX_>Ml`k#QZ_3Jpmyw!6E(S@xAXTOngt*z2ocR9nu>H6;3#l%W8Mp#>Vs7 zmz)>6_YN?Kh{oQZIaFDHT?EplC9`kFf%4(P#q;7rO7@9g(+ifGKHUzV$MnK}{avsF z&|XE|Pp?k~Zr1Q`F8Vz41kO8gBYfQ*IdjP-%8w7@petmW`I_kc(%;wwQTy*$RHbuy z-#Hnd{IoG9;Ww$>e3pCqL4H1=G8eTFnN*nT4!?L6pqcm~AH%DEKBnRZl5i)f=efM^ zR}3oQI&hpR3-TeArs35PW#dLL9ahoo&AoCc4L}(`C|jmGY^EG1WZgbw^~rdMqVZJF zUi`{-6Cbo_Z~Lk>c~v%p1NO>5A#Lmq{vZ9geG3&c_wrZUHhpUMk_2lB3-(FD2Z-t2 z>lTJNI<-5bt=)2ett^VLX#ieVZ}dn z2Pnx%-~-M9@X+Q08Aco2__!b%C|YIP<*1hC-PDXgFfazILce3d>ux^%KQM5Y@Nd}A z(#XtDN38$=010qNS#tmY3ljhU3ljkVnw%H_000McNlit62jdJH69q0Ak$u$w006j2 zL_t(Y$JJKb3cw%;&FKGs**ydyI?a;Ed>Bl2yd3Q`K*UlC0F*7u0KaR&;+t${M5OE> zBK6CxLHIOIq}9_F*@Mc42>?A@r)j*7G)A%@+>Vo$eOfbJ6#8U->a0sS?BzWH@2Ct? z<2eVv-N{K@&@bDPBHQ#axMa=AK8qto>@Dk+YxS!Vw4r?rKGh8^k+X~^j)g|l@HG4E z8*3Zv-wD@l;Dqe6<#YB9dq0A5q!;0Nc;B!O`H#0VA_}sc00000NkvXXu0mjfyy^N$ diff --git a/assets-fx/img/opt_gint_bopti.png b/assets-fx/img/opt_gint_bopti.png index 838821688b62a208db158f7e5991ca5dda0dd312..7989bb06d863ed2b03eec9b31143ae1d3754e56b 100644 GIT binary patch delta 4994 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 Z@c@k?(cHDJy!ZeB002ovPDHLkV1kCOo`nDa delta 2363 zcmV-B3B>mE65$e%Bmq;AB_Drjk{r1WM*rt2d<23U$m4JUB76fM-w#=>mS#NRkt19w zRaNH#g7_Ao9{bln{rLy4EUiDa>FBff#H-Fa^Ww`$KVSCs`8g-4zVAO?^7SsyuNS_r zXTBCb%jZw6U+2r$`5!m-?@t2##RX}9dZ2u-pMPCg*Z0Et4;k4>ntp$Mji3MB?{K%z z?pE!Tp?@~@S>pK-h8s6kD(_>RL;2tMuJ189Mq24eO*fsiIgU)pQj$xR`^XX(lgsCk zLyk3DRz7n+xxD8_(LD1hsYt1Dh-WRc+%ifoCtE3{J|%zWBJaBMUGK5?>O6{#f;09s_8OU)Yuq_uoW zGS^Z%*bI2Y+B~E3-kV$goJT6)(@HN2HnS|is8M#5E9r&^a(mLu$=|Tws=FMiniS zWD9Jrr1eM#!fKM6%QtpEk^61j9%}t}xaHqL?g{Ar56I=m%Aaui3)F5n;dv4Js4!}p z3hJv|>)Wljr@OPXbMjIVt9aA6%}?2@ao6UmpZs3m(|UhDc#&UL-<@wV?{!Ub??a~E zY;L`_uf_v?lEj>ig|7K~W?Y?#Zd2;;WVWXF#nrebRlSSPM|U~Xy#lG}v18Qu;*H%( zBJwihp|JB}dDdp>5~^=m`wcujk>E6cRwBc*Z)FqJy57BKgAu-0KcgJUn}rCdPNY8O z3NVRUY~6oVZ5E2tbw8LXH{#RR4)xHQ$I%J7rq#)%W#i3dM=m1v$z?jZ$k4m8FO5{5 zeT(`oxz~F)E>py)XNq_bE%ZC_9}+qBejHd6MtaFOM)pqu-s z3c74=^~c`WHZ-cieQ=wB8ZrKS!IE%#1MY*l)Q|2o65S5cEaDg6v#Db~$>@DxcdT-MQ z9iOnfpgk(cgQzxwED)5_U(YtUBiqR5dM0-fAHWAq{T!6j5Z9t^IaIn2@mpKTG6SphnS679Et*sbjZud%!*oumk3jVlK={OMvf}nS%=43J_ zWH^*+zAYQhgk|F}(}P9zRy|dpb*lW(UKqwUB#OgI_x7r$Zm~8-DuaUL&X)^g0O5bl z6AdF0%JO*MjSj@FkCez$m1)S5eKhE2koiHP@YM%Yg1SZFD&&Rm?yc;RH(IN*%R=$E zBg`jWxgjCk;vgEic2_)hnK??Zm~=<4l)i5|0Q=p{CYN^P5q+}8B-Uc zLrGy?ki2iEOXBCpOBS5isFUN{ovr!=2e>$GxBI*0qxb(+1(E2dhJP#}JI5@d1Q;f2 zz>ug0-eq)=b?<^JZ%4>4d!`tO?)5gI5lU+^D$AnKPO~}8(hwUKV9;T1jL3iUS>0mi zg#(WDZLfN6!KVm2?^IiA4O5BQ)p#a6v0_4wz7w-`I~c};5F2_Qq(Z-yScQ%jvj7QY zhMe4SOKcN!f}=7+F(bcp%uRQF^WOTPO$=$~{aH*BO^Jei7CZMW0`9o-Sqr(uTCb4! zZ5BbwXbiEBXMQDk+0lt)EZTp5$QHz3OQ9_@23)mIy)Xuv^%2x-<%Ao6(K*B7hu^hv zmd=>@?hgtj86OgTydiR^crxt(F5K6Q?_>cASii{h+=z?GjT?-LTNG_3jN#H8D^`fn z(>d0w@lbj=`Ddtrc%7yOZ}?F|FKR5ogawXt8S@cCi_eZwXtwY`Q(1pE{HLT3hayax z8f3hw#MV*&&M*qxHr6_Wku$f0n~`F}9UDYPc~%F*ic35Asw_q~rEW#3WMfpJj?YV1 z2`Ak&=nN1+Nu`_;EQG3wDViCS4HxYEt`D8c7Wzn!-s2LUJV)G{E>W8DEQdF9mvv)ENli0dq}glhHA-+KFOF?}kn@f4vhnZlKN+^j z{rNY>N01z#IiZ07000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jmI~6ag$oRq_!4 z005y$L_t(Y$K`)kTMob=2%~2Azq0!lqZ#Ft0Y-%{4 h0pBDi1iYHQ7dNn<=D^*~cDn!o002ovPDHLkV1j>dtq1@B diff --git a/assets-fx/img/opt_gint_rtc.png b/assets-fx/img/opt_gint_rtc.png index 33006d3ae98cc513d82f75b1acf9faff8037fcbf..74b727f6247c174e2bf5dc9bea17f54e30f273b4 100644 GIT binary patch literal 13193 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 diff --git a/assets-fx/img/opt_gint_spuram.png b/assets-fx/img/opt_gint_spuram.png index 3878f438b1fd82ca815e395569c9f157c7cc0dbf..9f38e263531448f2801e1dbe6a18a55d23f76663 100644 GIT binary patch delta 2216 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 delta 2141 zcmV-j2%`7r5uOo{Bms(%B_DrllH|Azg#YUlJ_5lP$m8$n(Hei9go1ekyF!HT?c4%{VREb+-O2oe9{t-S#MIKPkQ7h($xwio8X0$19f z5WC4wZIxF5g>jARM_-~hSj(?UDswlIkpcy&OKH+2Y0fHAOCAuk$UK*tHw;K?`I2O= zrF6I%=!m&_N97%xTmC$!RN$wTUKDO-S&&t0LqA#v8d|Ni+FF0>P1|U*t*4h>d+WVx zkD6Orv})6?szax)QAQnY^r2&nIo8axP?Bx-sdLOZ*J939pVby`FGj4j^DevYw)@sS z_T1|rpHoje{pcBIo^|srx88R9)jRII%fyh4L)th%$A3lA3v-ZX6 zpU(e*HThyKzf6C{IQ?dgr>YU?4I$w(EjWX*Tm{B87(mcDI7>rn&B0u7mS(0ZS|-UB z++0cPkq(8`BsZ6D?tU`&+q^ws{dc_O-(l_v>i!SR<;Th&c>4?1ZaCq28T(XWV44cm zXWK2;KIVGJe{fSA3#;?Cb=|J?QrtUnrgZQ1-rc2kIctBWidl)JtHoE=A?3*C{pa?a zW~tMMzOSZTeebhl;0Cw|(yFOzI=Gw~RK@Kzo9%+yR=2wR(NjnswTy`+L(au7$1O;x z>9p*7UEbDOV$`U;9J`Z+k78Hl8q=>%Mu@}DNp7ZRfrIA&Mz!2LQaLB*u}vD&v3i*9 zx9uYlw5NY9I>Z*4a#q53I?5E23f6R+LM_SHf_tW}ETd~;+&(5=L(?s@wb0&S+c?%T%QXL{L+ z2r+%LV^!}x#In3snh_}yw>K0O=5(#;)`I==aEpI_FOlxG>J#5P+tJxBy&dKx(jASq zI!C<0R-v$l$^|;shOFXtz$oov=G0(g#Wt5B$#hy$GidiRXG+bI$~;arll=*sErApS zCA7B@;FCKFJl^TnvsgQA2f1c@2GbiW@LZ?WaOkZj-R3np+=hHNETYHb2L0s7#8f|U zf!BXM$AUZR9~JfrduqEyLw>b4sf+#6Z}ABiA{ReWajN2@bcVnTiOG0{p3)7tIt+nI z&#awFM>l8hi>tJA2I9V_s637zoPJH$4HuDEI4<1R{IDZpBlL&xXJbcly(6qQmp&o{ zD^+ahLDFU@j{l5^TT@z8BgAH!T6K5AhvA2zHSHMd%*4&2lFEvI4S~AU0a%Sv2t~~VNTlG|+$d`W&YU4vE9cCxfG(0r(#B}QX|Wsm(4v}FzZZJ20|o`MNt z=_C@GUFazW(hzods1iEEjl7JZF)B!LW&)v>^w#v?NiW`IzkV~?8|+H9ea`!2hE&*3 z!Pq7uO^aOz|NALZA37bCqi^#%ndX60mcD~Nx;Kp(9VJq5#gOf^8D@WJeN$Ggqq)Ye z!N%NAMO%e^8eXk+q3=;~ppQ3F>#?0c4s;77QQ~E#4N{jOP|cmXv|bR;LuFQkzXPa+ zq~CTyO}}lG1;<(n`k|Ze;laI%iV1*&4l?VUQZ(g52 z{QxMJp7{J5=W!KDpM(Pc43hx}9)IKp5E3;XuEXh80001|Nkl+m_H2`f&{s2E(?ynBB7k;i>GzOr2wBJ6}7i63zxHppG zvEIA)JNSXK697O&h>Sj2!xp TIA(ww00000NkvXXu0mjffa)|e diff --git a/assets-fx/img/opt_gint_timers.png b/assets-fx/img/opt_gint_timers.png index 00af5be329d2322fdd621fb996dcdfa45c4dc24f..48b2d125d4f6f81e058423341d55ce2eadc8ede5 100644 GIT binary patch delta 2615 zcmV-73dr@U6x$S#Bmp{+B_DrVk~FCeh2L3)mjDP5EQgySyaO-apQ!Gh-{XmyafCag zE3>jl5IPqr!~NGkE&PMOETx4~wYSk)ulw?K|9fEjIWy58{E+JJ9+02)^REl*{8>2vM?`b}$EJTi+xhx8JKgMl zb~j5S4ehh3&l2H#8U`-1B=51tq5M~_^&Nww#~F7j@x&b$$4(>VB+*hyC#0Dy-E=tb zw286go0W6UJIlM*Mf1p8q9iGPB+Dv8j&#Yg^A(X2B>%*c-n!$hw^L{3lNg#4lO-Pc z(IHB6K1UvcBp``fq$a{X7h<-dbmaOnOI$mMY5cewolYR8>$Kg2#N^qfXP zeaDQaW>*WlyCtu4RBWLD7Sap*8*|(}tl^6>)_UvOYUF=?t&36Wp6vf(TvcP5OvGec z)||SlKfm+P#W*Grg4Swg%WAZ|_TldJDDy6iU09;rtMEu~-MHnD?NQ$3gVF*qE!h%@BKgPeiJrV- zhyV26R~k_ zD|MYALEGu|bj=e>^2~Rsw|hCjZQ20exwW4xYZ&4YsI9j^ZM(C5QToT^m zrP7c^O{Nrb1|<@_6S?o!J73L%S-WvDN6QaVw!wdv#t2?qnr>J(2eoH_N<~lcQi`lj z0n$vGAS0^%oD9eM(SCc<H2 zWSuNlC$2TAR=&AV@k+8J{TD85({Q4GlL4XLJI03#oisQX;1m2vrFvk0at?lxOi*EI z9yQtIvqC|!?`-(zQrR0>+kh9ta$P#4FD-xP7=k$A;4fD1K%18=-#kja@G0K5(p)aU zG7J@yf19XH_c~=k%i9p(8Wo4NMP1vz3B))|=YA15h`H*j$DWAYce3`cbuc`zbb@Ai zK(!%oIJ6FbjA`;kDF|*gIwB_?Q{E>Vh=i#)RBq{>Sf(pq7WU3CuOkFLkV6K(iezbog@o9xxg;ws5R$l7ZPN~!FhHeC;!A;Q#2m8CA zdtpagLv_J1*=zJXHJ0nG`Bsy*Q1?&0;ThKQ)!_^fETv4tIS4@L?vj9*F z`f2k}?{9mFr%@SJsP)Tc)j)r4I^R3kU9KCs*#36G<<-G7n`&6-h~UkDFwG8ZrB}h6 z#EGVppUvpldU@Oe%ai!gP2E7K!o-m$Qi%C~C+z27vvl6ShU3=P?OIL*5ka_lwnL^6NRMW#E6-rqn5 zX0(P{SAEEL$Vx3Ll@@a?&9ALs!H~KaeuU=pG%FV_Qx&e1lN)W5khO+sQWgF2l|Ho# zV&U}fodO4^rwoEM9dE7dy;a~1Punz%ykX$jmb^5)U;FVQp$t9jmQ8x|K)t66p{=Qo zgupJ`Ex%Vzs*2OwyeEINcdl%ZzNx=<0uSysX_scf;h9YE!*oL->;sS)a>JFn5m#yL}9ug79WKG{#$L5emhYo{7quqcMed0F)Yx z9a>^$!0YVV8AV zX3i2P;Mga77MXEWZ_GA+NMEr#z{20l?ry3KknK*r=-f!ZH<&D>0jEE>`y;MVd+4QK zhlsV%Wij(Ke<4rLC8`q+HBkqJ9y@)vT`)b+Ym;^7zT_5>6D^HE5X=j+H*e;E6Qw5a zsayBY@}h8PF`|F*!8cSoO0I?8p#m4KvtC4r<{nj(Du%<2xSeC00@M-&!&PAG@|p_F z>xtGK@Ac-0TD*Qyscav&!J1&nKA&p4-h25z-V@vx$Ewp^2_h5?zD$*yBGQPnjde5b zyE}5J72`J-vRE{u;54F?{Tt%uHE_Vj%Wu z!Mqi_Bz}YSMd~;|Gqt!}*wVwLw>V_N1r+`bd~N%=`sor!00009a7bBm000XU000XU z0RWnu7ytkO2XskIMF-^q1{Dk)0H|(b0002ANklD&Tt<(bQdR#QlM-@Rq>E3phY0Wi$$Q3xpEuo3p1?~4gR)(^~)0T~J{%wTk9>#3q zsPvC*BtvkHTMD6jLRc58c>@0WHRW1Q$E_njo%k#M$G(2HJ!1v8_tA-nvHHU?w4fae ZzW_pk`@0!IZ3>!BnxS#n@%#$ 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 KPDBK*LSTY*<=74Y diff --git a/assets-fx/img/opt_main.png b/assets-fx/img/opt_main.png index 3083554bb5d7497b1eec312e1ade53a66a245a25..9ad426ae79e25e92aa5edc0bf66f4ed1ccd7ef2e 100644 GIT binary patch delta 3468 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 diff --git a/assets-fx/img/opt_mem.png b/assets-fx/img/opt_mem.png index 8079c104ee01eeaebfc0cc8e0c8d1e6704ca1dc3..44ba00b0c59a1c3d083fcbd771975680cdc4620e 100644 GIT binary patch delta 3893 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 Du`!9{ delta 3873 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 IM6N<$f?V~)F#rGn delta 3472 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 #include #include +#include #include #include -#define put(...) row_print(++(*row), 1, __VA_ARGS__) +/* TODO: Include */ +extern uint32_t cpu_getVBR(void); + +/* Some symbols from the linker script */ +extern uint32_t + brom, srom, /* Limits of ROM mappings */ + sdata, rdata, /* User's data section */ + sbss, rbss; /* User's BSS section */ +#ifdef FX9860G +extern uint32_t sgmapped; /* Permanently mapped functions */ +#endif -#define load_barrier(x) { \ - if(!((x) & HW_LOADED)) { \ - put(" (not loaded)"); \ - return; \ - } \ -} /* MPU type and processor version */ void show_mpucpu(void) @@ -35,8 +40,8 @@ void show_mpucpu(void) }; char const *calc_names[] = { "Unknown", - "SH3 fx-9860G*", - "SH4 fx-9860G*", + "fx-9860G-like", + "fx-9860G-like", "Graph 35+E II", "Prizm fx-CG 20", "fx-CG 50/Graph 90+E", @@ -46,69 +51,101 @@ void show_mpucpu(void) int mpu = gint[HWMPU]; int calc = gint[HWCALC]; - char const *str_calc = _("Model", "Calculator model"); - if(calc < 0 || calc > 6) - row_print(1, 1, "%s: ", str_calc, calc); - else - row_print(1, 1, "%s: %s", str_calc, calc_names[calc]); + /* Generate a default calc name if invalid values are found */ + char calc_default[16]; + sprintf(calc_default, "", calc); + char const *str_calc = calc_default; + if(calc >= 0 && calc < 7) str_calc = calc_names[calc]; - if(mpu < 0 || mpu > 4) - row_print(_(2,3), 1, "MPU: ", mpu); - else - row_print(_(2,3), 1, "MPU: %s", mpu_names[mpu]); + /* Generate a default MPU name if invalid values are found */ + char mpu_default[16]; + sprintf(mpu_default, "", mpu); + char const *str_mpu = mpu_default; + if(mpu >= 0 && mpu < 5) str_mpu = mpu_names[mpu]; volatile uint32_t *CPUOPM = (void *)0xff2f0000; - uint32_t SR; - __asm__("stc sr, %0" : "=r"(SR)); + uint32_t SR, r15; + __asm__("stc sr, %0" : "=r"(SR)); + __asm__("mov r15, %0" : "=r"(r15)); #ifdef FX9860G - if(isSH3()) - { - row_print(4, 1, " SR %08x", SR); - return; + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); + + dprint(1, 10, C_BLACK, "Model: %s", str_calc); + dprint(1, 16, C_BLACK, "MPU: %s", str_mpu); + + print_prefix(29, 24, "SR", "%08X", SR); + dline(29, 24, 29, 46, C_BLACK); + if(isSH3()) { + print_prefix(29, 30, "PVR", ""); + print_prefix(29, 36, "PRR", ""); + print_prefix(29, 42, "CPUOPM", ""); } - row_print(4, 1, " SR %08x", SR); - row_print(5, 1, " PVR %08x", gint[HWCPUVR]); - row_print(6, 1, " PRR %08x", gint[HWCPUPR]); - row_print(7, 1, " CPUOPM %08x", *CPUOPM); + else { + print_prefix(29, 30, "PVR", "%08X", gint[HWCPUVR]); + print_prefix(29, 36, "PRR", "%08X", gint[HWCPUPR]); + print_prefix(29, 42, "CPUOPM", "%08X", *CPUOPM); + } + print_prefix(85, 24, "VBR", "%08X", cpu_getVBR()); + print_prefix(85, 30, "R15", "%08X", r15); + dline(85, 24, 85, 34, C_BLACK); + dfont(old_font); #endif #ifdef FXCG50 + row_print(1, 1, "Calculator model: %s", str_calc); + row_print(3, 1, "MPU: %s", str_mpu); row_print(4, 1, " Status Register: %08x", SR); row_print(5, 1, " Processor Version Register: %08x", gint[HWCPUVR]); row_print(6, 1, " Product Register: %08x", gint[HWCPUPR]); row_print(7, 1, " CPU Operation Mode: %08x", *CPUOPM); + row_print(8, 1, " Current VBR: %08x", cpu_getVBR()); + row_print(9, 1, " Current stack pointer: %08x", r15); #endif } /* Memory */ static void show_memory(void) { - uint32_t base_rom = 0x80000000; - uint32_t base_ram = 0x88000000; - uint32_t base_uram = (uint32_t)mmu_uram(); - - int rom = gint[HWROM]; - int ram = gint[HWRAM]; - int uram = mmu_uram_size(); - #ifdef FX9860G - row_title("Basic memory layout"); - row_print(3, 2, "%08x %4dk ROM", base_rom, rom >> 10); - row_print(4, 2, "%08x %4dk RAM", base_ram, ram >> 10); - row_print(5, 2, "%08x %4dk URAM", base_uram, uram >> 10); - row_print(6, 2, "Mapped %4dk", gint[HWURAM] >> 10); + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); + print_prefix(28, 10, "brom", "%08X", &brom); + print_prefix(28, 16, "rdata", "%08X", &rdata); + print_prefix(28, 22, "rbss", "%08X", &rbss); + print_prefix(28, 28, "rreloc", "%08X", mmu_uram()); + + print_prefix(98, 10, "srom", "%06d", &srom); + print_prefix(98, 16, "sdata", "%06d", &sdata); + print_prefix(98, 22, "sbss", "%06d", &sbss); + print_prefix(98, 28, "sreloc", "%06d", &sgmapped); + + dprint(1, 38, C_BLACK, "ROM: %dk, RAM: %dk", + gint[HWROM] >> 10, gint[HWRAM] >> 10); + dprint(1, 45, C_BLACK, "User RAM: %08X (%dk, P0 %dk)", + mmu_uram(), mmu_uram_size() >> 10, gint[HWURAM] >> 10); + dfont(old_font); #endif #ifdef FXCG50 + uint32_t base_ram = 0x88000000; if(gint[HWCALC] == HWCALC_FXCG50) base_ram = 0x8c000000; - row_print(1, 1, "ROM: %dM", rom >> 20); - row_print(2, 2, "%08X ... %08X", 0x80000000, 0x80000000+rom-1); - row_print(3, 1, "RAM: %dM", ram >> 20); - row_print(4, 2, "%08X ... %08X", base_ram, base_ram+ram-1); - row_print(5, 1, "Userspace RAM: %dk blocked", uram >> 10); - row_print(6, 2, "%08X ... %08X", base_uram, base_uram+uram-1); - row_print(7, 1, "Total mapped RAM: %dk", gint[HWURAM] >> 10); + + row_print(1, 1, "RAM: %dM, RAM: %dM (starts at %08X)", + gint[HWROM] >> 20, gint[HWRAM] >> 20, base_ram); + row_print(2, 1, "Userspace RAM: %08X (%dk continuous block)", + mmu_uram(), mmu_uram_size() >> 10); + row_print(3, 1, "Total RAM mapped in P0: %dk", + gint[HWURAM] >> 10); + + print_prefix(80, row_y(5), "brom", "%08X", &brom); + print_prefix(80, row_y(6), "rdata", "%08X", &rdata); + print_prefix(80, row_y(7), "rbss", "%08X", &rbss); + + print_prefix(240, row_y(5), "srom", "%06d", &srom); + print_prefix(240, row_y(6), "sdata", "%06d", &sdata); + print_prefix(240, row_y(7), "sbss", "%06d", &sbss); #endif } @@ -164,6 +201,7 @@ void gintctl_gint_cpumem(void) if(tab == 1) show_memory(); #ifdef FX9860G + row_title("CPU and memory"); extern bopti_image_t img_opt_gint_cpumem; dimage(0, 56, &img_opt_gint_cpumem); #endif diff --git a/src/gint/ram.c b/src/gint/ram.c index 19fbdc2..d9105b3 100644 --- a/src/gint/ram.c +++ b/src/gint/ram.c @@ -127,31 +127,31 @@ static void show_region(int row, struct region *r) /* Out-of-bounds rows */ if(row < 1 || row > 9 || (row == 1 && r)) return; - extern font_t font_hexa; - font_t const *old_font = dfont(&font_hexa); - int y = (row - 1) * 6; + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); + int y = (row - 1) * 6 + 2 * (row > 1); if(!r) { dprint( 1, y, C_BLACK, "Area"); - dprint(24, y, C_BLACK, "Address"); - dprint(60, y, C_BLACK, "Size"); - dprint(80, y, C_BLACK, "Reason"); + dprint(26, y, C_BLACK, "Address"); + dprint(62, y, C_BLACK, "Size"); + dprint(82, y, C_BLACK, "At end"); dfont(old_font); return; } - char const *reasons[] = { "", "Read-only", "Loops", "" }; + char const *reasons[] = { "Not tested", "Read-only", "Loops", "" }; dprint( 1, y, C_BLACK, "%s", r->name); - dprint(24, y, C_BLACK, "%08X", r->mem); + dprint(26, y, C_BLACK, "%08X", r->mem); if(r->reason != 0) - { - dprint(60, y, C_BLACK, "%dk", r->size >> 10); - dprint(80, y, C_BLACK, "%s", reasons[r->reason]); - } + dprint(62, y, C_BLACK, "%dk", r->size >> 10); + else + dprint(62, y, C_BLACK, "-"); + dprint(82, y, C_BLACK, "%s", reasons[r->reason]); dfont(old_font); } #endif @@ -172,7 +172,7 @@ static void show_region(int y, struct region *r) row_print(y, 9, "Address"); row_print(y, 18, "AS"); row_print(y, 22, "Size"); - row_print(y, 35, "Reason"); + row_print(y, 35, "At end"); return; } @@ -207,6 +207,7 @@ void gintctl_gint_ram(void) /* List scroll no fx-9860G */ GUNUSED int scroll = spu_zero(); + key_event_t ev; int key = 0; while(key != KEY_EXIT) { @@ -214,13 +215,13 @@ void gintctl_gint_ram(void) #ifdef FX9860G show_region(1, NULL); + dhline(6, C_BLACK); for(int i = 0; i < region_count; i++) { show_region(i+2-scroll, &r[i]); } - - if(scroll > 0) triangle_up(7); - if(scroll < region_count - 8) triangle_down(49); + scrollbar_px(/* view */ 8, 54, /* range */ 0, region_count, + /* visible */ scroll, 8); extern bopti_image_t img_opt_gint_ram; dimage(0, 56, &img_opt_gint_ram); @@ -242,7 +243,8 @@ void gintctl_gint_ram(void) dupdate(); - key = getkey().key; + ev = getkey(); + key = ev.key; if(key == KEY_F1) { explore_region(&r[0]); @@ -271,8 +273,17 @@ void gintctl_gint_ram(void) } #ifdef FX9860G - if(key == KEY_UP && scroll > 0) scroll--; - if(key == KEY_DOWN && scroll < region_count - 8) scroll++; + int scroll_max = region_count - 8; + if(key == KEY_UP) + { + if(ev.shift || keydown(KEY_SHIFT)) scroll=0; + else if(scroll > 0) scroll--; + } + if(key == KEY_DOWN) + { + if(ev.shift || keydown(KEY_SHIFT)) scroll=scroll_max; + else if(scroll < scroll_max) scroll++; + } #endif } } diff --git a/src/gint/spuram.c b/src/gint/spuram.c index 6a7a0d7..4a98fcf 100644 --- a/src/gint/spuram.c +++ b/src/gint/spuram.c @@ -41,7 +41,7 @@ static void restore(volatile uint32_t *area, uint32_t *save, int pages) } #ifdef FX9860G -static void render_header(int y, int bank_count) +static void render_header(int y, GUNUSED int bank_count) { y = 9 + 6*y; dtext( 1, 9, C_BLACK, "Area"); @@ -166,6 +166,8 @@ void gintctl_gint_spuram(void) int cur_bank = 0; int cur_page = 0; + int switch_key = _(KEY_F6, KEY_F1); + #ifdef FX9860G int tab = 0; #endif @@ -178,7 +180,7 @@ void gintctl_gint_spuram(void) row_title("SPU memory banking"); extern font_t font_hexa; - font_t *old_font = dfont(&font_hexa); + font_t const *old_font = dfont(&font_hexa); if(tab == 0) { @@ -204,7 +206,8 @@ void gintctl_gint_spuram(void) dfont(old_font); extern bopti_image_t img_opt_gint_spuram; - dimage(0, 56, &img_opt_gint_spuram); + dsubimage(0, 56, &img_opt_gint_spuram, 0, 0, + (tab == 1 ? 128 : 107), 8, DIMAGE_NONE); #endif #ifdef FXCG50 @@ -244,20 +247,20 @@ void gintctl_gint_spuram(void) if(key == KEY_DOWN && cur_bank == 0) cur_bank++; - if(key == KEY_F1 && cur_bank == 0 && _(tab == 1, 1)) + if(key == switch_key && cur_bank == 0 && _(tab == 1, 1)) { SPU.PBANKC0 ^= (1 << cur_page); SPU.PBANKC1 ^= (1 << cur_page); } - if(key == KEY_F1 && cur_bank == 1 && _(tab == 1, 1)) + if(key == switch_key && cur_bank == 1 && _(tab == 1, 1)) { SPU.XBANKC0 ^= (1 << cur_page); SPU.XBANKC1 ^= (1 << cur_page); } #ifdef FX9860G - if(key == KEY_F2) tab = 0; - if(key == KEY_F3) tab = 1; + if(key == KEY_F1) tab = 0; + if(key == KEY_F2) tab = 1; #endif } diff --git a/src/gint/switch.c b/src/gint/switch.c index 7300700..d62074e 100644 --- a/src/gint/switch.c +++ b/src/gint/switch.c @@ -12,7 +12,6 @@ #include static int switches = 0; -static int fast = 0; static int menus = 0; static void switch_function(void) @@ -230,8 +229,7 @@ void render(void) extern bopti_image_t img_opt_switch; row_print(1, 1, "Switch to OS"); row_print(3, 1, "Switches done: %d", switches); - row_print(4, 1, "Fast done: %d", fast); - row_print(5, 1, "Menus done: %d", menus); + row_print(4, 1, "Menus done: %d", menus); dimage(0, 56, &img_opt_switch); #endif @@ -239,11 +237,9 @@ void render(void) #ifdef FXCG50 row_title("Hot switching between gint and OS"); row_print(2, 1, "Switches done: %d", switches); - row_print(3, 1, "Fast done: %d", fast); - row_print(4, 1, "Menus done: %d", menus); + row_print(3, 1, "Menus done: %d", menus); fkey_button(1, "SWITCH"); - fkey_button(2, "FAST"); - fkey_button(3, "MENU"); + fkey_button(2, "MENU"); fkey_action(6, "SYSTEM"); #endif } @@ -260,10 +256,8 @@ void gintctl_gint_switch(void) key = getkey().key; if(key == KEY_F1) gint_switch(switch_function); - /* TODO: Fast gint switch in gintctl */ - if(key == KEY_F2) {} - /* Wait for F3 to be released before calling next getkey() */ - if(key == KEY_F3) + /* Wait for F2 to be released before calling next getkey() */ + if(key == KEY_F2) { /* Render next frame in advance. When we return from the main menu, our VRAM will be displayed but @@ -275,7 +269,7 @@ void gintctl_gint_switch(void) dupdate(); gint_osmenu(); - while(keydown(KEY_F3)) waitevent(NULL); + while(keydown(KEY_F2)) waitevent(NULL); } if(key == KEY_F6) system_contexts(); } diff --git a/src/gint/timer.c b/src/gint/timer.c index 8e7d90f..183e993 100644 --- a/src/gint/timer.c +++ b/src/gint/timer.c @@ -98,7 +98,6 @@ void gintctl_gint_timer(void) program to ~90 FPS.) */ int key=0, tid=0; GUNUSED int timeout=1; - volatile int flag = 0; #ifdef FX9860G int tab = 1; @@ -116,8 +115,11 @@ void gintctl_gint_timer(void) extern bopti_image_t img_opt_gint_timers; dimage(0, 56, &img_opt_gint_timers); - if(tid < 3) dprint(23, 56, C_BLACK, "TMU%d", tid); - else dprint(23, 56, C_BLACK, "ETMU%d", tid-3); + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); + if(tid < 3) dprint(24, 57, C_BLACK, "\x01 TMU%d \x02", tid); + else dprint(24, 57, C_BLACK, "\x01 ETMU%d \x02", tid-3); + dfont(old_font); #endif #ifdef FXCG50 @@ -155,7 +157,9 @@ void gintctl_gint_timer(void) if(key == KEY_F6) tab = 3; #endif - if(key == KEY_UP) tid = (tid+timer_count()-1) % timer_count(); - if(key == KEY_DOWN) tid = (tid + 1) % timer_count(); + if(key == KEY_LEFT) + tid = (tid + timer_count() - 1) % timer_count(); + if(key == KEY_RIGHT) + tid = (tid + 1) % timer_count(); } } diff --git a/src/gint/tlb.c b/src/gint/tlb.c index 1c5e2a3..05d23a8 100644 --- a/src/gint/tlb.c +++ b/src/gint/tlb.c @@ -37,8 +37,8 @@ static void draw_rom_cell(int x, int y, int status) #ifdef FX9860G #define PAGE_COUNT 0x80 -#define SQUARE_WIDTH 4 -#define SQUARE_HEIGHT 4 +#define SQUARE_WIDTH 5 +#define SQUARE_HEIGHT 5 #define LINE_SIZE 16 #define TLB_VIEW 8 @@ -61,44 +61,6 @@ static int rom_cell_y(int page_number) return (page_number / LINE_SIZE) * SQUARE_HEIGHT; } -#ifdef FX9860G -void triangle_up(int y) -{ - int x=118; - dpixel(x+2, y, C_BLACK); - dline(x+1, y+1, x+3, y+1, C_BLACK); - dline(x, y+2, x+4, y+2, C_BLACK); -} -void triangle_down(int y) -{ - int x=118; - dline(x, y, x+4, y, C_BLACK); - dline(x+1, y+1, x+3, y+1, C_BLACK); - dpixel(x+2, y+2, C_BLACK); -} -#endif - -#ifdef FXCG50 -void triangle_up(int y) -{ - int x=370; - dpixel(x+3, y, C_BLACK); - dline(x+2, y+1, x+4, y+1, C_BLACK); - dline(x+1, y+2, x+5, y+2, C_BLACK); - dline(x, y+3, x+6, y+3, C_BLACK); - dline(x, y+4, x+6, y+4, C_BLACK); -} -void triangle_down(int y) -{ - int x=370; - dline(x, y, x+6, y, C_BLACK); - dline(x, y+1, x+6, y+1, C_BLACK); - dline(x+1, y+2, x+5, y+2, C_BLACK); - dline(x+2, y+3, x+4, y+3, C_BLACK); - dpixel(x+3, y+4, C_BLACK); -} -#endif - static void explore_pages(uint8_t *pages, uint32_t *next_miss) { extern uint32_t srom; @@ -177,44 +139,48 @@ void show_utlb(int row, int E) char const *access_str[] = { "K:r", "K:rw", "U:r", "U:rw" }; uint16_t fg = valid ? C_BLACK : C_RGB(24,24,24); - #define fg_ fg, C_NONE + #define fg_ fg, C_NONE, DTEXT_LEFT, DTEXT_TOP - row_print_color(row, 2, fg_, "%d", E); - row_print_color(row, 5, fg_, "%08X", src); - row_print_color(row, 14, fg_, "%08X", dst); - row_print_color(row, 23, fg_, "%s", size_str[size]); - row_print_color(row, 28, fg_, "%s", access_str[data.PR]); - row_print_color(row, 34, fg_, "%s", (data.SH ? "SH" : "-")); - row_print_color(row, 37, fg_, "%s", (data.WT ? "WT" : "CB")); - row_print_color(row, 40, fg_, "%s", (data.C ? "C" : "-")); - row_print_color(row, 42, fg_, "%s", (addr.D || data.D ? "D" : "-")); - row_print_color(row, 44, fg_, "%s", (addr.V && data.V ? "V" : "-")); + int y = row_y(row) + 2 * (row > 1); + + dprint_opt( 14, y, fg_, "%d", E); + dprint_opt( 38, y, fg_, "%08X", src); + dprint_opt(110, y, fg_, "%08X", dst); + dprint_opt(182, y, fg_, "%s", size_str[size]); + dprint_opt(222, y, fg_, "%s", access_str[data.PR]); + dprint_opt(270, y, fg_, "%s", (data.SH ? "SH" : "-")); + dprint_opt(294, y, fg_, "%s", (data.WT ? "WT" : "CB")); + dprint_opt(318, y, fg_, "%s", (data.C ? "C" : "-")); + dprint_opt(334, y, fg_, "%s", (addr.D || data.D ? "D" : "-")); + dprint_opt(350, y, fg_, "%s", (addr.V && data.V ? "V" : "-")); } #endif #ifdef FX9860G void show_utlb(int row, int E) { - extern font_t font_hexa; - font_t const *old_font = dfont(&font_hexa); - int y = (row - 1) * 6; + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); + int y = (row - 1) * 6 + 2 * (row > 1); if(E == -1) { - dprint( 1, y, C_BLACK, "ID"); - dprint(12, y, C_BLACK, "Virtual"); - dprint(47, y, C_BLACK, "Physical"); - dprint(82, y, C_BLACK, "Len"); - dprint(98, y, C_BLACK, "Mode"); + dprint( 1, y, C_BLACK, "ID"); + dprint( 12, y, C_BLACK, "Virtual"); + dprint( 47, y, C_BLACK, "Physical"); + dprint( 82, y, C_BLACK, "Len"); + dprint( 97, y, C_BLACK, "Pr"); + dprint(115, y, C_BLACK, "CD"); dfont(old_font); return; } char const *size_str[] = { "1k", "4k", "64k", "1M" }; - char const *access_str[] = { "K:r", "K:rw", "U:r", "U:rw" }; + char const *access_str[] = { "Kr", "Krw", "Ur", "Urw" }; + char const *cd_str[] = { "--", "-D", "C-", "CD" }; uint32_t src, dst; - int valid, size, pr; + int valid, size, pr, cd; if(isSH3()) { @@ -232,6 +198,7 @@ void show_utlb(int row, int E) dst = data.PPN << 10; pr = data.PR; + cd = (data.C << 1) | data.D; } else { @@ -244,16 +211,18 @@ void show_utlb(int row, int E) valid = (addr.V != 0) && (data.V != 0); size = (data.SZ1 << 1) | data.SZ2; pr = data.PR; + cd = (data.C << 1) | data.D; } dprint( 1, y, C_BLACK, "%d", E); if(valid) { - dprint(12, y, C_BLACK, "%08X", src); - dprint(47, y, C_BLACK, "%08X", dst); - dprint(82, y, C_BLACK, "%s", size_str[size]); - dprint(98, y, C_BLACK, "%s", access_str[pr]); + dprint( 12, y, C_BLACK, "%08X", src); + dprint( 47, y, C_BLACK, "%08X", dst); + dprint( 82, y, C_BLACK, "%s", size_str[size]); + dprint( 97, y, C_BLACK, "%s", access_str[pr]); + dprint(115, y, C_BLACK, "%s", cd_str[cd]); } dfont(old_font); @@ -271,23 +240,29 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll) #endif row_title(_("TLB management", "TLB miss handler and TLB management")); + #ifdef FX9860G + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); + #endif + if(tab == 0) { - row_print(_(2,1), 1, _("srom=%x (%d pages)", - "Size of ROM sections: %08X (%d pages of 4k)"), + #ifdef FXCG50 + row_print(1, 1, "Size of ROM sections: %08X (%d pages of 4k)", rom_size, rom_pages); + #endif - for(uint p=0, y=_(19,36); p < PAGE_COUNT; p += 2*LINE_SIZE) + for(uint p=0, y=_(12,36); p < PAGE_COUNT; p += 2*LINE_SIZE) { - dprint(_(4,18), y, C_BLACK, _("%06x","%08X"), + dprint(_(5,18), y, C_BLACK, "%08X", 0x00300000 + (p << 12)); y += 2*SQUARE_HEIGHT; } for(uint p = 0; p < PAGE_COUNT; p++) { - draw_rom_cell(_(44,88) + rom_cell_x(p), - _(20,36) + rom_cell_y(p), pages[p]); + draw_rom_cell(_(39,88) + rom_cell_x(p), + _(11,36) + rom_cell_y(p), pages[p]); } #ifdef FXCG50 @@ -308,18 +283,18 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll) else if(tab == 1) { row_print(_(2,1), 1, "Legend:"); - draw_rom_cell(_(8,18), _(17,36), 0); - draw_rom_cell(_(64,200), _(17,36), 1); - draw_rom_cell(_(8,18), _(25,50), 2); - draw_rom_cell(_(64,200), _(25,50), 3); + draw_rom_cell(_(8,18), _(15,36), 0); + draw_rom_cell(_(64,200), _(15,36), 1); + draw_rom_cell(_(8,18), _(22,50), 2); + draw_rom_cell(_(64,200), _(22,50), 3); - dprint(_(16,30), _(16,36), C_BLACK, + dprint(_(16,30), _(15,36), C_BLACK, _("Unused", "Unused in add-in")); - dprint(_(72,212), _(16,36), C_BLACK, + dprint(_(72,212), _(15,36), C_BLACK, _("Unmapped", "Currently unmapped")); - dprint(_(16,30), _(24,50), C_BLACK, + dprint(_(16,30), _(22,50), C_BLACK, _("Data", "Data still mapped")); - dprint(_(72,212), _(24,50), C_BLACK, + dprint(_(72,212), _(22,50), C_BLACK, _("Mapped", "Currently mapped")); #ifdef FXCG50 @@ -327,7 +302,7 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll) dprint(30, 64, C_BLACK, "Next page to load"); row_print(6, 1, - "The MISS key will load an unmapped page to TLB by"); + "The LOAD key will load an unmapped page to TLB by"); row_print(7, 1, "performing a TLB miss, which calls %%003 on fx9860g"); row_print(8, 1, @@ -341,12 +316,16 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll) #endif #ifdef FX9860G + dprint(1, 30, C_BLACK, "Size of ROM text: %X (%d pages)", + rom_size, rom_pages); + if(next_miss != 0xffffffff) - row_print(5, 1, "Next load: %x", next_miss); + dprint(1, 36, C_BLACK, "Next load: %08x", next_miss); else - row_print(5, 1, "No page left to load!"); - row_print(6, 1, "MISS: TLB miss"); - row_print(7, 1, "TIMER: From timer"); + dprint(1, 36, C_BLACK, "No page left to load!"); + + dprint(1, 43, C_BLACK, "F5: Load a page by TLB miss"); + dprint(1, 49, C_BLACK, "F6: Do it from a timer callback"); #endif } @@ -356,11 +335,23 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll) for(int i = 0; i < TLB_VIEW; i++) show_utlb(i+2, tlb_scroll+i); - if(tlb_scroll > 0) triangle_up(_(7,38)); - if(tlb_scroll < TLB_VIEW_MAX) triangle_down(_(49,192)); + #ifdef FX9860G + dhline(6, C_BLACK); + #endif + + #ifdef FXCG50 + dline(12, 34, 363, 34, C_BLACK); + #endif + + scrollbar_px( + /* view */ _(8,37), _(54,201), + /* range */ 0, TLB_VIEW_MAX + TLB_VIEW, + /* visible */ tlb_scroll, TLB_VIEW); } #ifdef FX9860G + dfont(old_font); + extern bopti_image_t img_opt_gint_tlb; dimage(0, 56, &img_opt_gint_tlb); #endif @@ -369,7 +360,7 @@ static void draw(int tab, uint8_t *pages, uint32_t next_miss, int tlb_scroll) fkey_menu(1, "ROM"); fkey_menu(2, "INFO"); fkey_menu(3, "TLB"); - fkey_action(5, "MISS"); + fkey_action(5, "LOAD"); fkey_action(6, "TIMER"); #endif } @@ -408,13 +399,17 @@ void gintctl_gint_tlb(void) if(tab == 2 && key == KEY_UP) { - if(ev.shift) tlb_scroll = 0; - else if(tlb_scroll > 0) tlb_scroll--; + if(ev.shift || keydown(KEY_SHIFT)) + tlb_scroll = 0; + else if(tlb_scroll > 0) + tlb_scroll--; } if(tab == 2 && key == KEY_DOWN) { - if(ev.shift) tlb_scroll = TLB_VIEW_MAX; - else if (tlb_scroll < TLB_VIEW_MAX) tlb_scroll++; + if(ev.shift || keydown(KEY_SHIFT)) + tlb_scroll = TLB_VIEW_MAX; + else if (tlb_scroll < TLB_VIEW_MAX) + tlb_scroll++; } if(key == KEY_F5 && next_miss != 0xffffffff) diff --git a/src/gintctl.c b/src/gintctl.c index 393df3e..622589b 100644 --- a/src/gintctl.c +++ b/src/gintctl.c @@ -170,6 +170,7 @@ int main(GUNUSED int isappli, GUNUSED int optnum) dfont(&font_uf5x7); #endif + key_event_t ev; int key = 0; struct menu *menu = NULL; @@ -177,7 +178,9 @@ int main(GUNUSED int isappli, GUNUSED int optnum) { draw(menu); dupdate(); - key = getkey().key; + + ev = getkey(); + key = ev.key; if(key == KEY_F1) menu = NULL; @@ -195,7 +198,7 @@ int main(GUNUSED int isappli, GUNUSED int optnum) if(!menu) continue; if(key == KEY_UP || key == KEY_DOWN) - menu_move(menu, key, 0); + menu_move(menu, key, ev.shift || keydown(KEY_SHIFT),0); if(key == KEY_EXE) menu_exec(menu); } diff --git a/src/libs/openlibm.c b/src/libs/openlibm.c index bd92b14..8223e57 100644 --- a/src/libs/openlibm.c +++ b/src/libs/openlibm.c @@ -3,6 +3,7 @@ #include #include +#include #define __BSD_VISIBLE 1 #include diff --git a/src/libs/printf.c b/src/libs/printf.c index 7fb54dc..3cded69 100644 --- a/src/libs/printf.c +++ b/src/libs/printf.c @@ -12,7 +12,7 @@ #define NAN __builtin_nan("") #define INFINITY __builtin_inf() -#define SCROLL_HEIGHT _(8,12) +#define SCROLL_HEIGHT _(9,12) struct printf_test { char const *format; @@ -198,27 +198,26 @@ static void draw(struct printf_test const *tests, char answers[][16], dclear(C_WHITE); #ifdef FX9860G - extern font_t font_hexa; - font_t const *old_font = dfont(&font_hexa); + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); dprint( 1, 0, C_BLACK, "ID"); dprint(13, 0, C_BLACK, "Format"); dprint(43, 0, C_BLACK, "Output"); - dprint(91, 0, C_BLACK, "Valid"); + dprint(99, 0, C_BLACK, "%d/%d", total_passed, total); + dhline(6, C_BLACK); for(int i = 0; i < SCROLL_HEIGHT; i++) { struct printf_test const *t = &tests[offset+i]; - int y = (i+1) * 6; + int y = (i+1) * 6 + 2; dprint( 1, y, C_BLACK, "%d", offset+i+1); dprint(13, y, C_BLACK, "%s", t->format); dprint(43, y, C_BLACK, "%s", answers[offset+i][0] ? answers[offset+i] : ""); - dprint(91, y, C_BLACK, "%s", passed[offset+i]?"Ok":"Err"); + dprint(99, y, C_BLACK, "%s", passed[offset+i]?"Ok":"Err"); } - dfont(old_font); - row_print(8, 1, "Passed %d of %d.", total_passed, total); #endif #ifdef FXCG50 @@ -228,25 +227,28 @@ static void draw(struct printf_test const *tests, char answers[][16], row_print(1, 5, "Format"); row_print(1, 13, "Argument"); row_print(1, 29, "Answer"); + dline(12, 34, 355, 34, C_BLACK); for(int i = 0; i < SCROLL_HEIGHT; i++) { struct printf_test const *t = &tests[offset+i]; - row_print(i+2, 2, "%d", offset+i+1); - row_print(i+2, 5, "%s", t->format); - row_print(i+2, 13, "%s", t->argument_as_string); + int y = row_y(i+2) + 2; + dprint( 14, y, C_BLACK, "%d", offset+i+1); + dprint( 38, y, C_BLACK, "%s", t->format); + dprint(102, y, C_BLACK, "%s", t->argument_as_string); int fg = passed[offset+i] ? C_RGB(0,31,0) : C_RGB(31,0,0); - row_print_color(i+2, 29, fg, C_NONE, "%s", answers[offset+i][0] - ? answers[offset+i] : ""); + dprint_opt(230, y, fg, C_NONE, DTEXT_LEFT, DTEXT_TOP, "%s", + answers[offset+i][0] ? answers[offset+i] : ""); } row_print(14, 1, "Passed: %d/%d", total_passed, total); #endif - if(offset > 0) triangle_up(_(7,38)); - if(offset < total - SCROLL_HEIGHT) triangle_down(_(49,192)); - + scrollbar_px( + /* view */ _(8,37), _(60,201), + /* range */ 0, total, + /* visible */ offset, SCROLL_HEIGHT); dupdate(); } @@ -267,9 +269,16 @@ void gintctl_libs_printf(void) draw(tests, answers, passed, offset); key = (ev = getkey()).key; - if(key == KEY_UP && offset > 0) offset--; - if(key == KEY_UP && ev.shift) offset = 0; - if(key == KEY_DOWN && offset < total - SCROLL_HEIGHT) offset++; - if(key == KEY_DOWN && ev.shift) offset = total - SCROLL_HEIGHT; + int scroll_max = total - SCROLL_HEIGHT; + if(key == KEY_UP) + { + if(ev.shift || keydown(KEY_SHIFT)) offset = 0; + else if(offset > 0) offset--; + } + if(key == KEY_DOWN) + { + if(ev.shift || keydown(KEY_SHIFT)) offset = scroll_max; + else if(offset < scroll_max) offset++; + } } } diff --git a/src/mem/mem.c b/src/mem/mem.c index 5f3c5f6..e877909 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -53,7 +53,7 @@ int line(uint8_t *mem, char *header, char *bytes, char *ascii, int n) /* Read single bytes when possible, but longwords when in SPU memory */ for(int k = 0; k < n; k++) { - uint32_t addr = mem; + uint32_t addr = (uint32_t)mem; int c = 0x11; /* XRAM, YRAM, PRAM */ @@ -78,10 +78,23 @@ int line(uint8_t *mem, char *header, char *bytes, char *ascii, int n) return 0; } +void draw_input(int x, int y, char *text, int cursor_pos) +{ + int w, h; + int next = text[cursor_pos]; + text[cursor_pos] = 0; + dsize(text, NULL, &w, &h); + text[cursor_pos] = next; + + dtext(x, y, C_BLACK, text); + dline(x+w, y, x+w, y+h-1, C_BLACK); +} + /* gintctl_mem(): Memory browser */ void gintctl_mem(void) { uint32_t base = 0x88000000; + key_event_t ev; int key = 0; #ifdef FX9860G @@ -97,6 +110,16 @@ void gintctl_mem(void) int size = 8; int lines = _(9,14); + char input[9]; + int input_pos = -1; + int input_len = -1; + int input_keys[16] = { + KEY_0, KEY_1, KEY_2, KEY_3, + KEY_4, KEY_5, KEY_6, KEY_7, + KEY_8, KEY_9, KEY_XOT, KEY_LOG, + KEY_LN, KEY_SIN, KEY_COS, KEY_TAN, + }; + while(key != KEY_EXIT) { dclear(C_WHITE); @@ -129,36 +152,111 @@ void gintctl_mem(void) } #ifdef FX9860G - extern bopti_image_t img_opt_mem; - dsubimage(0, 56, &img_opt_mem, 0, 0, 128, 8, DIMAGE_NONE); + if(input_pos < 0) + { + extern bopti_image_t img_opt_mem; + dsubimage(0, 56, &img_opt_mem, 0, 0, 128, 8, + DIMAGE_NONE); + if(view_ascii) dsubimage(23, 56, &img_opt_mem, 23, 9, + 21, 8, DIMAGE_NONE); + } + else + { + extern font_t font_mini; + font_t const *old_font = dfont(&font_mini); - if(view_ascii) dsubimage(23, 56, &img_opt_mem, 23, 9, 21, 8, - DIMAGE_NONE); + dtext(1, 57, C_BLACK, "Go to:"); + draw_input(24, 57, input, input_pos); + + dfont(old_font); + } #endif #ifdef FXCG50 row_title("Memory browser"); - fkey_button(1, "JUMP"); - fkey_action(3, "ROM"); - fkey_action(4, "RAM"); - fkey_action(5, "ILRAM"); - fkey_action(6, "ADDIN"); + if(input_pos < 0) + { + fkey_button(1, "JUMP"); + fkey_action(3, "ROM"); + fkey_action(4, "RAM"); + fkey_action(5, "ILRAM"); + fkey_action(6, "ADDIN"); + } + else + { + dtext(4, 210, C_BLACK, "Go to:"); + draw_input(52, 210, input, input_pos); + } #endif dupdate(); - key = getkey().key; + ev = getkey(); + key = ev.key; - if(key == KEY_UP) base -= size * lines; - if(key == KEY_DOWN) base += size * lines; + int move_speed = 1; + if(ev.shift || keydown(KEY_SHIFT)) move_speed = 8; + + if(key == KEY_UP) base -= move_speed * size * lines; + if(key == KEY_DOWN) base += move_speed * size * lines; + + if(key == KEY_F1 && input_pos < 0) + { + input[0] = 0; + input_pos = 0; + input_len = 0; + } + if(key == KEY_EXIT && input_pos >= 0) + { + input_pos = -1; + input_len = -1; + /* Don't quit the memory viewer */ + key = 0; + } + if(key == KEY_EXE && input_pos >= 0) + { + /* Parse string into hexa */ + uint32_t target = 0; + for(int k = 0; k < input_len; k++) + { + target <<= 4; + if(input[k] <= '9') target += (input[k] - '0'); + else target += (input[k] - 'A' + 10); + + base = target & ~7; + } + + input_pos = -1; + input_len = -1; + } + + for(int i = 0; i < 16; i++) + if(key == input_keys[i] && input_pos >= 0 && input_len < 8) + { + /* Insert at input_pos, shift everything else right */ + for(int k = 8; k >= input_pos; k--) + input[k + 1] = input[k]; + input[input_pos++] = i + '0' + 7 * (i > 9); + input_len++; + } + if(key == KEY_DEL && input_pos > 0) + { + /* Shift everything after input_pos left one place */ + for(int k = input_pos - 1; k < 8; k++) + input[k] = input[k + 1]; + input_pos--; + input_len--; + } + if(key == KEY_LEFT && input_pos > 0) input_pos--; + if(key == KEY_RIGHT && input_pos < input_len) input_pos++; #ifdef FX9860G - if(key == KEY_F2) view_ascii = !view_ascii; + if(key == KEY_F2 && input_pos < 0) view_ascii = !view_ascii; #endif - if(key == KEY_F3) base = 0x80000000; - if(key == KEY_F4) base = 0x88000000; - if(key == KEY_F5) base = 0xe5200000; - if(key == KEY_F6) base = 0x00300000; + if(key == KEY_F3 && input_pos < 0) base = 0x80000000; + if(key == KEY_F4 && input_pos < 0) base = 0x88000000; + if(key == KEY_F5 && input_pos < 0) base = 0xe5200000; + if(key == KEY_F6 && input_pos < 0) base = 0x00300000; } #ifdef FX9860G diff --git a/src/menu.c b/src/menu.c index 8648f09..142694e 100644 --- a/src/menu.c +++ b/src/menu.c @@ -25,12 +25,24 @@ void menu_init(struct menu *menu, int top, int bottom) } /* menu_move(): Move the cursor in a menu */ -void menu_move(struct menu *menu, int key, int wrap) +void menu_move(struct menu *menu, int key, int quick, int wrap) { int visible = menu->bottom - menu->top; int max_offset = max(menu->len - visible, 0); - if(key == KEY_UP && menu->pos > 0) + /* Quick moves */ + if(key == KEY_UP && quick) + { + menu->pos = 0; + menu->offset = 0; + } + else if(key == KEY_DOWN && quick) + { + menu->pos = menu->len - 1; + menu->offset = max_offset; + } + /* Normal move up and wrapping move up */ + else if(key == KEY_UP && menu->pos > 0) { menu->pos--; menu->offset = min(menu->offset, menu->pos); @@ -40,8 +52,8 @@ void menu_move(struct menu *menu, int key, int wrap) menu->pos = menu->len - 1; menu->offset = max_offset; } - - if(key == KEY_DOWN && menu->pos + 1 < menu->len) + /* Normal move down and wrapping move down */ + else if(key == KEY_DOWN && menu->pos + 1 < menu->len) { menu->pos++; if(menu->pos > menu->offset + visible - 1 diff --git a/src/util.c b/src/util.c index 40e5248..2ac8308 100644 --- a/src/util.c +++ b/src/util.c @@ -134,6 +134,29 @@ int row_y(int y) return ROW_Y + ROW_H * (y - 1) + ROW_YPAD; } +//--- +// General rendering +//--- + +/* scrollbar_px(): Pixel-based scrollbar */ +void scrollbar_px(int view_top, int view_bottom, int range_min, int range_max, + int range_pos, int range_view) +{ + int view_x = _(127, 391); + int view_width = _(1, 2); + int view_height = view_bottom - view_top; + + /* Bring virtual range to 0..range_max */ + range_max -= range_min; + range_pos -= range_min; + + int bar_pos = (range_pos * view_height + range_max/2) / range_max; + int bar_height = (range_view * view_height + range_max/2) / range_max; + + drect(view_x, view_top + bar_pos, view_x + view_width - 1, + view_top + bar_pos + bar_height, C_BLACK); +} + //--- // Other drawing utilities //---