From e921c6874e60c147f01d34bd9b6769bef3e31611 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sat, 16 May 2020 15:56:06 +0200 Subject: [PATCH] The Ungodly Update * Added the switch menu * Added the keyboard menu on fx-CG 50 * Added a (currently unused) bold 8x9 font on fx-CG 50 * Displayed something decent in the "Image Rendering" test on fx-CG 50 * Changed F-keys all around to unify the semantics * Improved the layout of the RAM detection test * Adapted TMU/ETMU display to the new mpu/timer.h definitions * Added a timer selector in the F-key bar in the timer test * Added an "external libraries" tab that will also test libc features * Added a libimg test --- Makefile | 10 +- assets-cg/fonts/font8x9_bold.png | Bin 0 -> 17645 bytes assets-cg/img/applejack_31x27.png | Bin 0 -> 919 bytes assets-cg/img/applejack_36x25.png | Bin 0 -> 877 bytes assets-cg/img/kbd_pressed.png | Bin 0 -> 1585 bytes assets-cg/img/kbd_released.png | Bin 0 -> 1585 bytes assets-cg/img/libimg_even_odd.png | Bin 0 -> 407 bytes assets-cg/img/libimg_odd_even.png | Bin 0 -> 555 bytes assets-cg/img/libimg_sq_even.png | Bin 0 -> 484 bytes assets-cg/img/libimg_sq_odd.png | Bin 0 -> 428 bytes assets-cg/img/libimg_train.png | Bin 0 -> 8435 bytes assets-cg/img/potion_17x22.png | Bin 0 -> 11153 bytes assets-cg/img/potion_18x22.png | Bin 0 -> 10515 bytes assets-cg/img/potion_21x22.png | Bin 0 -> 13773 bytes assets-cg/img/swords.png | Bin 3740 -> 13664 bytes assets-fx/img/keypress.png | Bin 0 -> 146 bytes assets-fx/img/keyrelease.png | Bin 0 -> 166 bytes assets-fx/img/libimg_swords.png | Bin 0 -> 1129 bytes assets-fx/img/opt_gint_timers.png | Bin 2668 -> 2602 bytes assets-fx/img/opt_main.png | Bin 3072 -> 3462 bytes assets-fx/img/opt_mem.png | Bin 3898 -> 3898 bytes assets-fx/img/opt_perf_libprof.png | Bin 1193 -> 1270 bytes assets-fx/img/opt_perf_render.png | Bin 1193 -> 1270 bytes assets-fx/img/opt_switch.png | Bin 0 -> 2614 bytes assets-fx/img/opt_switch_ctx.png | Bin 0 -> 3077 bytes include/gintctl/gint.h | 8 +- include/gintctl/libs.h | 11 ++ project.cfg | 20 ++- src/gint/bopti.c | 57 ++++++-- src/gint/dma.c | 8 +- src/gint/hardware.c | 2 +- src/gint/keyboard.c | 150 ++++++++++++++++++++++ src/gint/ram.c | 26 ++-- src/gint/switch.c | 200 +++++++++++++++++++++++++++++ src/gint/timer.c | 60 +++++---- src/gintctl.c | 38 ++++-- src/libs/libimg.c | 107 +++++++++++++++ src/mem/mem.c | 2 +- src/perf/render.c | 61 ++++----- src/util.c | 2 +- 40 files changed, 660 insertions(+), 102 deletions(-) create mode 100644 assets-cg/fonts/font8x9_bold.png create mode 100644 assets-cg/img/applejack_31x27.png create mode 100644 assets-cg/img/applejack_36x25.png create mode 100644 assets-cg/img/kbd_pressed.png create mode 100644 assets-cg/img/kbd_released.png create mode 100644 assets-cg/img/libimg_even_odd.png create mode 100644 assets-cg/img/libimg_odd_even.png create mode 100644 assets-cg/img/libimg_sq_even.png create mode 100644 assets-cg/img/libimg_sq_odd.png create mode 100644 assets-cg/img/libimg_train.png create mode 100644 assets-cg/img/potion_17x22.png create mode 100644 assets-cg/img/potion_18x22.png create mode 100644 assets-cg/img/potion_21x22.png create mode 100644 assets-fx/img/keypress.png create mode 100644 assets-fx/img/keyrelease.png create mode 100644 assets-fx/img/libimg_swords.png create mode 100644 assets-fx/img/opt_switch.png create mode 100644 assets-fx/img/opt_switch_ctx.png create mode 100644 include/gintctl/libs.h create mode 100644 src/gint/keyboard.c create mode 100644 src/gint/switch.c create mode 100644 src/libs/libimg.c diff --git a/Makefile b/Makefile index 94fd233..118cc6b 100644 --- a/Makefile +++ b/Makefile @@ -136,10 +136,10 @@ build-cg/%.S.o: %.S # Images build-fx/assets/img/%.o: assets-fx/img/% @ mkdir -p $(dir $@) - fxconv -i $< -o $@ $(FXCONVFX) name:img_$(basename $*) $(IMG.$*) + fxconv --bopti-image $< -o $@ $(FXCONVFX) name:img_$(basename $*) $(IMG.$*) build-cg/assets/img/%.o: assets-cg/img/% @ mkdir -p $(dir $@) - fxconv -i $< -o $@ $(FXCONVCG) name:img_$(basename $*) $(IMG.$*) + fxconv --bopti-image $< -o $@ $(FXCONVCG) name:img_$(basename $*) $(IMG.$*) # Fonts build-fx/assets/fonts/%.o: assets-fx/fonts/% @@ -184,11 +184,9 @@ distclean: distclean-fx distclean-cg install-fx: $(TARGET_FX) p7 send -f $< install-cg: $(TARGET_CG) - @ while [[ ! -h /dev/Prizm1 ]]; do sleep 0.25; done - @ while ! mount /dev/Prizm1; do sleep 0.25; done + @ prizm-mount @ rm -f /mnt/prizm/$< @ cp $< /mnt/prizm - @ umount /dev/Prizm1 - @- eject /dev/Prizm1 + @ prizm-eject .PHONY: all all-fx all-cg clean distclean install-fx install-cg diff --git a/assets-cg/fonts/font8x9_bold.png b/assets-cg/fonts/font8x9_bold.png new file mode 100644 index 0000000000000000000000000000000000000000..47b40101e9ef880fb2cba5fb2a3d305317a38ef8 GIT binary patch literal 17645 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 gGIqBWY>Jb0{02y>e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00RF>L_t(Y$E{btOB+!f|J*}p zhIXj!aErYR7O7BzgCs+*a5{9dLkU$^H-};h{sA32I>au5gJX>%g_6lZ13iZe4iXB2 zw1d|y8B`oPNQd`2T)$txm)s>W=@%Zn@ZP=8_s8e^BbHVg!-&$#0DxB7l6yL%eUgj} z3tY-)qkUbOO3{w?dyx{Qd={#nu7EYD0mi&;&)001=zs8-r)gdr+Ln*mAA z)@EbBF9Q!sD?{rt@NgM;gU4LyTXHSzwUBch_Cg~Jv9UA-0GOE^_Rw+GD( z1Crz%2g_S00D!~OD}4C+2LNz!q_Derjor=b;n+@u^K1*XRun?dwmA00heg-rZ(ctA z4FFi)I$;hB1un(2EoQk)!6d#6MYwkHYzu|48yI64v@mu9;)Pb)q7^e@5UbDDW;xE} zZjxv3o-+}9zSRqemIRhUF$Ms9dL28Pcc)?2=VH0tv%Jz}%EyZ%g^ASz&f&w;D<%)c zo?L&I^4bATg@EMZNHO5@)(PkEw;%Tb0NcI~Nj@0{B3xgMMFPuwBr8cMg|>YkrF=H# zdYSXx+Gz}2##6eLWaq&Py#4qPJN_|~sZzALnaKR^1sZEC5_n?ufDg_3T%_Sjm4U7O zaa4-^4;Wo72VgdqrZ6)(iiy<&1_Xc||M>Re{y5C5pB-dsXT0om6oND*xTTV-2{3wC z_U9II$4+7?m1Jv(CMTzyBn3FniM>HH6B`Q3_45u(YAusWGTCP7PAQ*F%=OqXvFN%e z`+nlkz(ZjeJ2*6 literal 0 HcmV?d00001 diff --git a/assets-cg/img/applejack_36x25.png b/assets-cg/img/applejack_36x25.png new file mode 100644 index 0000000000000000000000000000000000000000..d97574b230cdd7e764099e92dd7832348c70d4e7 GIT binary patch literal 877 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 literal 0 HcmV?d00001 diff --git a/assets-cg/img/kbd_released.png b/assets-cg/img/kbd_released.png new file mode 100644 index 0000000000000000000000000000000000000000..3dfd6e65ef3a1b53af277205dc0bc74b9dcfa43b GIT binary patch literal 1585 zcmV-12G043P) zprF9Oz}ni{|NsA379XYn000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jl`35()z# zLdn+v000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000G$Nkl zc5spMl@0e8As93Bf}>Y{=5`~*VRDwld7lx|P!iwhywB*k0+>iv96>r2KmtprnxV*z zqA)__F2>OegENkp49<)BP9zeV&^I^A+$dc5kt+yS60W3NAqdyRn;9A50^x$aOuRR9 zZgwg#MveJJfdLHTWwIYHz~E+l20L6KF z8J@;JIQj^qeMVPz9%lH6)#J;UKceqGqpy>X$0MtDUysK#8}2c}|5Gn+?$72HYI+t| z(&zasu9OuR&cX^tz{u6{Lk9YDUBC6fNU9j>PnKgSoO6&Sw%SO-MJ31r2ICBzE2RK{ zf7+1(GvJyd*ZiZj0{ml)=38aFwK+kT;nIKsoi%dJ*KjJbAmqzL*QOUoJ+73^L|}d)&o9o01{XM)4>n0}xX0#im-|=d`&yT5^!GY8Hq#sXfQ4R) zIt-1T>nlU760bAr&SKYRi3_K31?94{xInq^)45mWq4#qeO2S*c=+CqEBL$PsTmQMR z6&#C#dFbP*SRYzkR~<|ZfBziYqRm~MO(Cf~UY@w2n(g5#?!paRrE;#5lL;=~8j7X4 zJs+>aQQ~rU6_*F?Bu~Gs>n>iM=RuJ=sr-RrU42;}a9Q7S_l3WSyH}69#)JJ^-{|Tj zHc}`=;H;`RRTZbI_uS9GRTe(S?Z?Y=uIpO}*N7&r5F!_N;^Impi7If{iv}_ABkj1@ zsY2rV_#;;(-Som4j9%{Yc&%9KX1pUVMp$w~yr{mAam)PLpCfd**eMp=(4pDyDHl^l z^4rY=iPz;9LcDf8ljWhcp5#a7uRhejjf_Y7w~_I#lQ)-g_xEojqkrCP=X9Q4=myud zEZVhbWuG;v7cDN=u?Y%&R&gpHaXH~;R_+SiUasO9*KT^I77a(cxX6J{yxQ+{PI46t z;-&L}Z^|!p^84*ZQ4-u0rssp=-Sxxy^Y`;m|JF6iWBps#c-P6BdvpJ5ZnaCbRNG_I;sB`Pz2GNFIJubJt-P~K}2X&{?w{e}E=0c^L za-?tG1qyCef5i;9Ed8vKl!^;)^C0RxRH>@hQA||H8?GP7Eo7GtzcoC>ort$u_f2qT z^1F2%H9H^PucLO(-&^NzoxgSS*7@I}^JPCIcF-ihsmzBRZ|#XIf`XSwVmZk=CQ z=C@wDWbYVtbiToD1anHfATQy@<=D~rQ13^vTjy_`zjgE0`CqK_*q3gpJF`X5{rAiz zR%{3^eiL6Xt3~~N`GA$yC>b} z3ja%iX)gYkX$VW8z_n5ZDZjq8wYN0MwSkn}6XLajyywp3mxy>H-l_S}n7@SU0`Y5s j4fFTb`CI2N)uDd@8AbWH^5q=|00000NkvXXu0mjfOTZFR literal 0 HcmV?d00001 diff --git a/assets-cg/img/libimg_even_odd.png b/assets-cg/img/libimg_even_odd.png new file mode 100644 index 0000000000000000000000000000000000000000..9123979b3a742e9840342f60e340b09abd9d4102 GIT binary patch literal 407 zcmV;I0cie-P)q3la+|_DyN#0003tNklq3la+-p#H7J0005XNkl1 z2MkY)AjKDeS-7I^20 zf%oHekYcl#N}tC6l|{Q&4`*riD$?hm^`Hf+ZS`j27I~5y`TkJ0PH>UVlhnxFw^_JQ t;43(rNAq(%VTZyRyp@eeR_#Fs}+ztR8z002ovPDHLkV1mm_`8ogq literal 0 HcmV?d00001 diff --git a/assets-cg/img/libimg_sq_even.png b/assets-cg/img/libimg_sq_even.png new file mode 100644 index 0000000000000000000000000000000000000000..e366184cd6d43702f5170c78300b600cd584be84 GIT binary patch literal 484 zcmVq3la+zKr2Ms0004lNklRAmke>6Vm;>sF}JbafS2m%0%CMpq3la+qBtYyN0003?Nklb;@5S)#80Q|t$ z(!mq_1SD7KB0A_?B2ggMuArlebPZDI5~ZS~NRbLb=?00CCrk?G%pJzWhqKa3zV&%L zvpXv!@n6wV{Tz&B<7@{#wu2t$>pcOm)tD6kz1kox~M>iPKDk)It;NK%c%Zi~fqh%kyD+h3cu3KUhKIA8CJ z)vGJn&Zq02OlA|uHonpwrYcZezFydcQGD0n_p$_7$A^D{-U4(kJOC=cY#!@fMf?Eq W;YZ+aSkkNj0000q3la)Dh30rw001BWNklwC!) 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 jsxE>0{p;bO3N1|MG00000NkvXXu0mjf!G9?P literal 0 HcmV?d00001 diff --git a/assets-cg/img/potion_18x22.png b/assets-cg/img/potion_18x22.png new file mode 100644 index 0000000000000000000000000000000000000000..fb2d049c8b06494a3e86863ebe605485e3438023 GIT binary patch literal 10515 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 Dsu3P$ literal 0 HcmV?d00001 diff --git a/assets-cg/img/swords.png b/assets-cg/img/swords.png index 03493f97d8bbb090e063589212b7f40c4d521a14..1349d3fdbe7ab33e13e963b294a01b95ef8796dd 100644 GIT binary patch literal 13664 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 jnanJ}kP*xTj6xY4Fsc`GB-^McTvaJY zn~Q(lXeiaF;t^%DhX#$Qtd1Cw0gE-4ZMwG{`}gkRdL!8~<(p+2m2&1JXyW7hz0oM& z$l{=hkNB9{xFoKE_=u0Gjd-)bafaAw2TN7WeeKgj2hvgCQqtnNW`$v$bRX>3-5 z#wm_gpS098*3r=sCMQ9~VphG7RrVu` zWDwOIcgzUH({1VOUs$JnKJ*0X)wk`0YQUWQ#To#>nO{F_3SdZY(wYTQTO!p9S@p9$ zW&?)6QeC5C>jt}0-JJ^tvDor5vP)i2{>Zf%fVn;+10VPIn+h0d?irQCt5(!Z0Y-ne zJh5b5Z+I7ezYkkC*rmvb6vK$RTl_O92aKxT4x)Vk;Ltza_`wr@m2RJCfFU^v-}S|8 zHemkvmqR$?JBQLcS119D2o?bF`+YcZyj^(=L%Iw2E1()MDjxF?8D`-tZvw!K00sc2 zUD^@p2}MXQ^)RcU2g&)>Z(d-vZ*+gN)kQm`%8OJmDn7CxOHROF!NfTQ{1suk6MsLO znxT+=j@`7J9lL2c({)|RdPq%8<%O!Gw@7lPeNGeU2}PNRp9zNf$xqkfwfX}ny>o?h zdDS&KQmjr!S9Oh!;6OW6jL{h8J}kDpthBd-nGAD%Mh1U>Mi_?1cX9WhD-3^QEKjFP zWaU^HI^eHhbVbsg$SyLO#!QAGmZ@EQg%tZ(thv)-m?>8|$6YeHPms!xV+29KUol2^ zMo`U0m(1(+a<@zZV3-J+sRCxopi$AC=KBB`k!=95)kQm`gC-usOn&1c&`bv~lLk%P zC5zceVQ$&#q8(Cz6UikD_$z<-ePx5jY`~l^zFnqE#viV;SaYWhm}z&|lsWq9lR`3X zIW=d3eq(Cccn+gAXwxb!H#Q5L$#a-kf_|DubJwsoUeGV&945u;1OT?_-ty7I$*+Br z5BejFgo!4jvX2*yMJu)dzET`Lakms1#>F*LfB}Gak2H>XZ>sWWK81gIO923lZD*rq z7z6$ae!wZ7*-S-e#x)=tFqK>GKvmsgm;e|CfdB7_BR2Q0``<*@|fC+0zH{j94pJkNB z&?2KzRd*Q8UBg;5z)XJyC`OQovhwTZv*xa0Z6?ynl27^>09==qi=CTqjTtb&$U|tN zva0G1qks5^5nVD>J2HU=05C6f5 zB}KOa2sI`IfL)KsWleEY+xJf2m<`QX5fF>sNY37;ek%0x8rS-#d(04Bxi zNC{RK?T|JP5j?cHjd95k8(>5iFvp&S9D5czyN@elm>hc+8r#k)1x$5~ z&Ns3Bdv_r_ZykRCpr)!^1Po^*@)jn=G?82l742KYm}SKl4EEK9Vww?_89Z|gvASiE zcFp4AyOF!0iobvQ^NUK73;?k0xke5g+3Za7p+)!0Kfj67pI_8$si9;_tn)Im8jWWf z`laYhygxC{*4;fgUwpfCz|d=A{r!7);n|lOvF-jszP5kMAJuVPRxSYG;fG2l{aD7B zGMZ;!YUC&cLLEuOt|T%Pw`kcK;F~@yTDFD*h7tmlO_Mq5>ks0$*8J3jK;RJs4dIHmG%FST6{S) z;L+&%_|Sg?`1sHR0Dx`x7Xknts@#RzH@bOpU@CwKE2A-XqZHeoLh{E&xE#r>w?2^t zK5((#`oz%d&I%UjtYE$MiBe@POHJe#&1qR`qLS{Hvd>|noim7SePy<$rK%5I*SXH< z{xbDO{qKg{k8`^KkZu=}HROJrxg5!1{k&soQ=ET5RA%gXmESg>k>4rn1BocWZ0;J? z`jEszLH{wHL6gN~kK03iFn7mpR9tg|XgTwjtZaIwzx?C{+Q|?!bzPZXgRZk(5BLnM}}-(p6Bs*==bjYOgCUY87)a z>QDw~j0;%=zwl`bOrmQ(?sHA?wzNXPsvFdh=gh^D4T{O*bl{ipHvcxr_#5q4VH#M(>!MP|ku_QG`p**uBL&4qCHz2%`52T34 i)5S4_<9c$!0zDuvfPqm-_(ds@#o+1c=d#Wzp$P!}@E{5R literal 0 HcmV?d00001 diff --git a/assets-fx/img/keyrelease.png b/assets-fx/img/keyrelease.png new file mode 100644 index 0000000000000000000000000000000000000000..2b19fb90f0228931f14badaa81458c6bf91ed334 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61SFYwH*Nw_oCO|{#S9F3${@^GvDCf{D9B#o z>Fdh=gh^D4owqdB$Pp+cS>hT|;+&tGo0?a`;9QiNSdyBeP@Y+mq2TW68xY>eCk|Ak z;OXKR!f`$M&;S4S%tj8+{{R0!pVL?5RC-EEi_wKI%nY|~@%mDW$<+Mb6Mw< G&;$U@`7OQx literal 0 HcmV?d00001 diff --git a/assets-fx/img/libimg_swords.png b/assets-fx/img/libimg_swords.png new file mode 100644 index 0000000000000000000000000000000000000000..40164c0cebb6158d92ec8a23dc9694350f89b505 GIT binary patch literal 1129 zcmV-v1eW`WP)q4+{z@>dFSS0000PbVXQnLvL+uWo~o;Lvm$dbY)~9 zcWHEJAV*0}P*;Ht7XSbQ<4Ht8RA}DqT3e2*Fbs_mn_w^9MzY9cVO@sr4<|AyF!(XF zw;H5s+EF?6JGKwR%aY!8(euf8&&xu8I4PCKgKMo+O5xU8|Nrz(Coyx%Ifvjd^Vi^% zQaIcrZLT~C|D%${27Ava!r~-gS>@qnp;AhpMMlS2G62rW>x8&8zTjxcIb>x%qUFVBebo6Pm3y%{%JnNYbJ z>I=>{ZY~hDU{j-v8?D!+u1`7%s~FEZM-Ggh6^z#?n==WkuMg$7<~yA<3gOu&dW<4V z9){2>rE{-IxQm2*S<3DS5uHh&!pzDu>B@lY;kU+>m6pt$$1h|5^qZMxl_9+A^J zNjgiGSQEo50lZF<8*?m1Ess!**<~qrATse@E=KYC$++@6;I_16rVJ7gtQsPUh zt_QH@h>$pt=}JJ)o0|vb(aX$QHw97|B4SxatvIqwX|sLASu>%ZO_rdMrSu9GrIbQf v@?kWCFba&U!H>rAV(rPZw)xx72U!0A;bRmgS=r#V00000NkvXXu0mjf3dj=A literal 0 HcmV?d00001 diff --git a/assets-fx/img/opt_gint_timers.png b/assets-fx/img/opt_gint_timers.png index 7e541427112bcc09b1ba8d7d74e9e0de04a30d28..00af5be329d2322fdd621fb996dcdfa45c4dc24f 100644 GIT binary patch delta 2540 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 IM6N<$f?SXOWdHyG diff --git a/assets-fx/img/opt_mem.png b/assets-fx/img/opt_mem.png index f8de1f3051a601ec0bd57c8369e128c5679753a6..8079c104ee01eeaebfc0cc8e0c8d1e6704ca1dc3 100644 GIT binary patch delta 3873 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 diff --git a/assets-fx/img/opt_perf_libprof.png b/assets-fx/img/opt_perf_libprof.png index 9259a6f5056a1da863c95453cb7f7ff5de5b27c3..b0edafa55364897125764f58ef175343c7926c3c 100644 GIT binary patch delta 1199 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 literal 0 HcmV?d00001 diff --git a/assets-fx/img/opt_switch_ctx.png b/assets-fx/img/opt_switch_ctx.png new file mode 100644 index 0000000000000000000000000000000000000000..138baac26a84a831e3fcd109309b9a8d96a3371c GIT binary patch literal 3077 zcmV+g4EpnlP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3#>k|e1Oh5ye}_y~Xi!EyK@B76fM-=E0p?%DN* zcO2o$>B_3COb~ic?}>TrU;jMMKX|3u+mnm7+G`EGa?d>tKD6-jvd{Uw7DK-8U$6Li zkI%0^eE**KD4gZ}s`+zWKG(l)tlwt_`imc8`O^dPJ%9RjVjbTTr$0m#dKlr?SNr)p zXSZ|gUERo)G}L!d?-bA1Fx)uFlHA8Chw@kWtoP^~jcHcQVTTna$BI3sDB;8$_Y+4v z(cG1c{RUh$pFZ+0rD*N+u%tk@Ou)yz}-u--?ZycjVR- z87%V1e?6YRyWw|^b5i-qy|8P$dlwWK_Hfr zHbJH=Qo*LdBj)BAjrZPE(tDj!0iPmO6l}T-z{uAz)E3Gzdt@So~>Ox7DUc2_zdmn>2M}9^bJUzH$jG3m)Jj<+8 zXPbSF1$|atW!0stt-i)iTXx=M*R8wlzK2DFN{?kLR!yy0w{hUwk&{n3_2_A*pYe^_ z2i5;L{s+|J2eovO^854~HLj}qKzE4fI#V1o5KB3NxH|qyULhTUp zv@AYK#D@fVu9i+FJl0WIzB-$y&H1pQ;ESBs;_)54`=kkn{ zv5oon2}Za&@}A`AOa^CyeJbgzh-^A*b;M88gM?cS>x67Fw_6V^ShBawGKd)&F0*gg zQMC<)JhPlmOsxueh*s8aa^#utw9Pf!in2^pv(2(Y?d61{D^97C@*rtrcVez!S1Jqk z5x3O@x_r_HX5|5_Wu`v!iK~h@#zypDw#fSKYB3-_daxG{f`EpZS`d5sYH5umsr$-+gOXuGLO^&FMU>4EPm$go(pV= z)566=5nLz`*5lbPc=7H~v&`khi91gtI~7v*X$Al5QO$7bQ0tM$x2|a3* z8Xe9i^3&oaxHxebgwcXi5!UD=H+!QBOW}U*mbGfkSU_2s2pcB#<=C|L#J77Pfvega0Ghq#}n&5E^YlR~5ks3uoO-xtPsZ8YdKMt4?e-# zz>x?M1xlY%BWEnFdI*$AXK|2GJn2Qz?8`lde-R!wK#3BOt1^UGuV(cR{rIMo@vO}v zJtfNLy*s*jq}Y{Z^a|hiE8&(11jBo(ei+zZ!HN_B3b?2=VqfSj>a$3uVp_-L$p>3y zd){QOCxMeqaAO^e<|5{0Hs;_1nyfG&bV#plH3xbX%J}3JDKiSF1lGJ{K6k0*3^EsC zU(*j-#GzeWmMt?+@37j}ij)ckJ}_~f$3~oh8K*t?2b3($HALcIZQ^WJ_cOsd@vDuE zd+n351ZqT|oo@v$O|0(N)cOEPX&^28$_D_|QQAN^kv-^RAA=0}EY^ibz##ZbVH_{7 zMKkGqc_<8LIq{UbVLmfQ^xxN3)|}*A>ux2Y9E(nR(T{c)VT@)fx`EGO+A}_KTp}yw z_1fe47ag=y&Z$Hr$SK| zdlCAw$Q?40kYqkR16MIf%c|kY5r|5q-Kx*1y2qMaWNSp2 zP%1`E{%eDDFyIWiKII<302Q#=@XcF4+{cgdvHccD}=Lb#6S5f4I)K?G5X#q9ztXpiYI&XsjWXWhZ$ zDpz%AS&z=QD+m?KC<;h8rXnY)d1DT)=%-o99W$e6#tHem&5EnCux6Y$(wovCdXJ3hGfo{FyD4{( zkSzw_PbiVjn|*jfda(dB?M*#8hfx@Oq_#ajhul%~6cZjx&*{1K-Q**;A=6g?GVL1~ z<5^nPD@W)d%c|tI#CFoUEeKx!rQ4CsDQy^13k6(Af_TAtM?{&#e)|#XdU-!{Z8Z#_ zE7?`Vb-&KrbkXv5XBS%t(Kg>p;)KxK>^tZDTA@g3XL9j+AWH{HMpB#(oy_>AgMTJ1XA9g}$v-8|{^ z(G@#JblI4W2g)sGFtRr=hyUMgAJQ%n4r2n|K&uID?BA z?IvnRMBaJ#`KfGg=&A4NIfu6(ePA(<-wy+FvLS;FXP%`Q&+ZsOCzj_e7WP;418jAN z>-Id~0#?xyjFm0%uHM){RF<SFMQ3oJo5}tdY$S9k0_d=rpoU(4TfbRaYU7%+RJ3WeixOu@`r0r+3K;VBY(!mq~ z>n^{XqiWF6BgJ=2Tm^^#000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jl`8 z6e2n2{n9G{006;BL_t(Y$L&@@4!|G?6SMz+nH@|BK|lg*hh;sfTLG1VfQVxZ02nF! z^dcrV#~~bumEAWd(o_(4vp(Hg^y%sroXG3+3N9M0L_kEI5o;Rpx_(oQ1i`tx9cwJ; zA`&%?9PdZE_}Zy}X;vZ&7DTIv ziN*NFoL=&13$;qqdkUbV^czDY{Vly)MD9`b9ubiL3Wy{@dlQD7@YBirJ$ey0l;=8~ T)CY^=00000NkvXXu0mjf+zH&( literal 0 HcmV?d00001 diff --git a/include/gintctl/gint.h b/include/gintctl/gint.h index f584df2..efcf302 100644 --- a/include/gintctl/gint.h +++ b/include/gintctl/gint.h @@ -14,6 +14,12 @@ void gintctl_gint_ram(void); /* gintctl_gint_dump(): Dump memory to filesystem */ void gintctl_gint_dump(void); +/* gintctl_gint_switch(): Test the gint switch-in-out procedures */ +void gintctl_gint_switch(void); + +/* gintct_gint_keybaord: Real-time keyboard visualization */ +void gintctl_gint_keyboard(void); + /* gintctl_gint_timer(): Show the timer status in real-time */ void gintctl_gint_timer(void); @@ -25,7 +31,7 @@ void gintctl_gint_bopti(void); /* gintctl_gint_dma(): Test the Direct Access Memory Controller */ void gintctl_gint_dma(void); -#endif +#endif /* FXCG50 */ #ifdef FX9860G diff --git a/include/gintctl/libs.h b/include/gintctl/libs.h new file mode 100644 index 0000000..f986220 --- /dev/null +++ b/include/gintctl/libs.h @@ -0,0 +1,11 @@ +//--- +// gintctl:libs - External libraries +//--- + +#ifndef GINTCTL_LIBS +#define GINTCTL_LIBS + +/* gintctl_libs_libimg(): libimg-based rendering and image transform */ +void gintctl_libs_libimg(void); + +#endif /* GINTCTL_LIBS */ diff --git a/project.cfg b/project.cfg index aca2c74..aafffec 100644 --- a/project.cfg +++ b/project.cfg @@ -61,11 +61,12 @@ INCLUDE := -I include # Libraries. Add one -l option for each library you are using, and also # suitable -L options if you have library files in custom folders. To use # fxlib, add libfx.a to the project directory and use "-L . -lfx". -LIBS := -lprof +LIBS_FX := -lprof -limg-fx +LIBS_CG := -lprof -limg-cg # Base linker flags for the fxSDK, you usually want to keep these. -LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS) -lgint-fx -lgcc -LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS) -lgint-cg -lgcc +LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS_FX) -lgint-fx -lgcc +LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS_CG) -lgint-cg -lgcc # Additional linker flags, if you need any. LDFLAGS := @@ -80,6 +81,19 @@ LDFLAGS_CG += -Wl,-Map=build-cg/map # Parameters for the hexadecimal font on fx9860g FONT.hexa.png = charset:print grid.size:3x5 grid.padding:1 +FONT.font8x9_bold.png = charset:print grid.size:8x11 grid.padding:1 \ + grid.border:0 proportional:true IMG.swift.png = profile:p4 IMG.swords.png = profile:p8 + +IMG.kbd_pressed.png = profile:p4 +IMG.kbd_released.png = profile:p4 + +IMG.libimg_even_odd.png = type:libimg-image +IMG.libimg_odd_even.png = type:libimg-image +IMG.libimg_sq_even.png = type:libimg-image +IMG.libimg_sq_odd.png = type:libimg-image +IMG.libimg_train.png = type:libimg-image + +IMG.libimg_swords.png = type:libimg-image diff --git a/src/gint/bopti.c b/src/gint/bopti.c index 73b5b9f..bf3404b 100644 --- a/src/gint/bopti.c +++ b/src/gint/bopti.c @@ -1,7 +1,9 @@ #define GINT_NEED_VRAM #include #include + #include +#include /* gintctl_gint_bopti(): Test image rendering */ void gintctl_gint_bopti(void) @@ -9,25 +11,56 @@ void gintctl_gint_bopti(void) #ifdef FXCG50 extern image_t img_swift; extern image_t img_swords; - - int x = 396 - img_swords.width - 16; - int y = 16; - - int key = 0; + extern image_t img_potion_17x22, img_potion_18x22, img_potion_21x22; + extern image_t img_applejack_31x27, img_applejack_36x25; + int key = 0, x, y; while(key != KEY_EXIT) { dclear(C_WHITE); - dimage(0, 0, &img_swift); - dimage(x, y, &img_swords); + row_title("Image rendering"); + + x=51, y=25; + dtext(x, y, "E.E", C_BLACK, C_NONE); + dtext(x+35, y, "E.O", C_BLACK, C_NONE); + dtext(x+70, y, "O.E", C_BLACK, C_NONE); + dtext(x+105, y, "O.O", C_BLACK, C_NONE); + + x=52, y=40; + dtext(10, y+6, "OxE", C_BLACK, C_NONE); + dimage(x, y, &img_potion_17x22); + dimage(x+35, y+1, &img_potion_17x22); + dimage(x+71, y, &img_potion_17x22); + dimage(x+106, y+1, &img_potion_17x22); + + x=52, y=67; + dtext(10, y+6, "ExE", C_BLACK, C_NONE); + dimage(x, y, &img_potion_18x22); + dimage(x+35, y+1, &img_potion_18x22); + dimage(x+71, y, &img_potion_18x22); + dimage(x+106, y+1, &img_potion_18x22); + + x=44, y=95; + dtext(10, y+9, "OxO", C_BLACK, C_NONE); + dimage(x, y, &img_applejack_31x27); + dimage(x+35, y+1, &img_applejack_31x27); + dimage(x+71, y, &img_applejack_31x27); + dimage(x+106, y+1, &img_applejack_31x27); + + x=40, y=127; + dtext(10, y+9, "ExO", C_BLACK, C_NONE); + dimage(x, y, &img_applejack_36x25); + dimage(x+35, y+1, &img_applejack_36x25); + dimage(x+71, y, &img_applejack_36x25); + dimage(x+106, y+1, &img_applejack_36x25); + + dimage(190, 35, &img_swords); + + dtext(67, 210, "Some images by Pix3M (deviantart.com/pix3m)", + C_BLACK, C_NONE); dupdate(); key = getkey().key; - - if(key == KEY_UP) y--; - if(key == KEY_DOWN) y++; - if(key == KEY_LEFT) x--; - if(key == KEY_RIGHT) x++; } #endif } diff --git a/src/gint/dma.c b/src/gint/dma.c index 4781e1f..f78ae0f 100644 --- a/src/gint/dma.c +++ b/src/gint/dma.c @@ -96,11 +96,11 @@ void gintctl_gint_dma(void) dprint(6, 158, "Source"); dprint(96, 158, "%s", source ? "IL" : "RAM"); - fkey_button(1, "RUN"); + fkey_action(1, "RUN"); - fkey_action(4, "CHANNEL"); - fkey_action(5, "INT"); - fkey_action(6, "SOURCE"); + fkey_button(4, "CHANNEL"); + fkey_button(5, "INT"); + fkey_button(6, "SOURCE"); #endif dupdate(); diff --git a/src/gint/hardware.c b/src/gint/hardware.c index d91cda3..8ad1a5e 100644 --- a/src/gint/hardware.c +++ b/src/gint/hardware.c @@ -82,7 +82,7 @@ static void hw_cpg(int *row) } /* Direct Memory Access Controller */ -static void hw_dma(int *row) +static GUNUSED void hw_dma(GUNUSED int *row) { #ifdef FXCG50 int dma = gint[HWDMA]; diff --git a/src/gint/keyboard.c b/src/gint/keyboard.c new file mode 100644 index 0000000..e475a83 --- /dev/null +++ b/src/gint/keyboard.c @@ -0,0 +1,150 @@ +#include +#include + +#include + +void position(int row, int col, int *x, int *y, GUNUSED int *w, GUNUSED int *h) +{ + #ifdef FX9860G + *y = 10 + 6 * row; + if(row <= 4) *x = 5 + 6 * col; + if(row >= 5) *x = 6 + 7 * col; + #endif + + #ifdef FXCG50 + if(row == 0) *y=2, *x=7+29*col, *w=16, *h=16; + if(row >= 5) *y=108+23*(row-5), *x=2+35*col, *w=30, *h=17; + if(row >= 1 && row <= 4) + { + *y=28+18*(row-1), *x=2+29*col, *w=25, *h=18; + if(row == 1 && col == 4) *x=127, *y=37, *w=12, *h=12; + if(row == 1 && col == 5) *x=140, *y=24, *w=12, *h=12; + if(row == 2 && col == 4) *x=140, *y=50, *w=12, *h=12; + if(row == 2 && col == 5) *x=153, *y=37, *w=12, *h=12; + } + #endif +} + +void render_keyboard(void) +{ + GUNUSED int x, y, w, h; + + #ifdef FXCG50 + extern image_t img_kbd_pressed; + extern image_t img_kbd_released; + dimage(15, 21, &img_kbd_released); + #endif + + for(int row = 0; row < 9; row++) + { + int major = (9-row); + int key_count = (major >= 5) ? 6 : 5; + + for(int col = 0; col < key_count; col++) + { + int code = (major << 4) | (col + 1); + if(code == 0x45) code = 0x07; + + #ifdef FXCG50 + if(!keydown(code)) continue; + + position(row, col, &x, &y, &w, &h); + dsubimage(15+x, 21+y, &img_kbd_pressed, x,y,w,h, 0); + #endif + + #ifdef FX9860G + extern image_t img_keypress; + extern image_t img_keyrelease; + position(row, col, &x, &y, &w, &h); + if(keydown(code)) dimage(x, y, &img_keypress); + else dimage(x, y, &img_keyrelease); + #endif + } + } +} + +static void render(key_event_t *last_events, int counter) +{ + char const *key_names[] = { + "F1", "F2", "F3", "F4", "F5", "F6", + "SHIFT", "OPTN", "VARS", "MENU", "Left", "Up", + "ALPHA", "x^2", "^", "EXIT", "Down", "Right", + "X,O,T", "log", "ln", "sin", "cos", "tan", + "frac", "F<>D", "(", ")", ",", "->", + "7", "8", "9", "DEL", "AC/ON", "0x46", + "4", "5", "6", "*", "/", "0x47", + "1", "2", "3", "+", "-", "0x48", + "0", ".", "x10^", "(-)", "EXE", "0x49", + }; + + key_event_t ev; + dclear(C_WHITE); + + #ifdef FXCG50 + row_title("Keyboard state visualizer"); + int y0=190, dy=14, maxev=12; + int x1=230, x2=248; + #endif + + #ifdef FX9860G + row_print(1, 1, "Keyboard state"); + int y0=52, dy=8, maxev=6; + int x1=55, x2=67; + #endif + + for(int i=0, y=y0; i < maxev; i++, y-=dy) + { + ev = last_events[(counter+15 - i) % 16]; + if(ev.type == KEYEV_NONE) continue; + + int key = (ev.key == KEY_ACON ? 0x45 : ev.key); + int row = 9 - (key >> 4); + int col = (key & 15) - 1; + char const *name = key_names[6*row + col]; + + if(ev.type == KEYEV_UP) + dprint(x2, y, C_BLACK, C_NONE, "Up %s", name); + if(ev.type == KEYEV_DOWN) + dprint(x1, y, C_BLACK,C_NONE,"Down %s", name); + } + + render_keyboard(); +} + +int handle_event(key_event_t *last_events, int counter) +{ + key_event_t ev = last_events[(counter + 15) % 16]; + + if(ev.type != KEYEV_DOWN) return 0; + if(ev.key == KEY_EXIT) return 1; + if(ev.key == KEY_MENU) render(last_events, counter), dupdate(), gint_osmenu(); + + return 0; +} + +/* gintct_gint_keybaord: Real-time keyboard visualization */ +void gintctl_gint_keyboard(void) +{ + /* All initialized with type=KEYEV_NONE */ + key_event_t last_events[16] = { 0 }; + key_event_t ev; + int counter = 0; + + while(1) + { + render(last_events, counter); + dupdate(); + + /* Redraw at each event if needed */ + last_events[counter] = waitevent(NULL); + counter = (counter+1) % 16; + if(handle_event(last_events, counter)) return; + + while((ev = pollevent()).type != KEYEV_NONE) + { + last_events[counter] = ev; + counter = (counter+1) % 16; + if(handle_event(last_events, counter)) return; + } + } +} diff --git a/src/gint/ram.c b/src/gint/ram.c index bde689b..3c910c8 100644 --- a/src/gint/ram.c +++ b/src/gint/ram.c @@ -74,8 +74,8 @@ void gintctl_gint_ram(void) GUNUSED char const *reasons[] = { "Not tested yet", - "Not writable past %d bytes", - "Wraps around after %d bytes", + "%d bytes (not writable)", + "%d bytes (wraps around)", }; int key = 0; @@ -102,14 +102,20 @@ void gintctl_gint_ram(void) row_print(2, 1, "memory sections by checking how far it can " "write."); - dprint(6, 78, C_BLACK, C_NONE, "ILRAM:"); - dprint(6, 92, C_BLACK, C_NONE, "XRAM:"); - dprint(6, 106, C_BLACK, C_NONE, "YRAM:"); - dprint(6, 120, C_BLACK, C_NONE, "MERAM:"); - dprint(61, 78, C_BLACK, C_NONE, reasons[ILr], IL); - dprint(61, 92, C_BLACK, C_NONE, reasons[Xr], X); - dprint(61, 106, C_BLACK, C_NONE, reasons[Yr], Y); - dprint(61, 120, C_BLACK, C_NONE, reasons[MEr], ME); + row_print(4, 2, "ILRAM:"); + row_print(5, 2, "XRAM:"); + row_print(6, 2, "YRAM:"); + row_print(7, 2, "MERAM:"); + + row_print(4, 10, "E5200000"); + row_print(5, 10, "E5007000"); + row_print(6, 10, "E5017000"); + row_print(7, 10, "E8080000"); + + row_print(4, 21, reasons[ILr], IL); + row_print(5, 21, reasons[Xr], X); + row_print(6, 21, reasons[Yr], Y); + row_print(7, 21, reasons[MEr], ME); fkey_button(1, "ILRAM"); fkey_button(2, "XRAM"); diff --git a/src/gint/switch.c b/src/gint/switch.c new file mode 100644 index 0000000..bfc744a --- /dev/null +++ b/src/gint/switch.c @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int switches = 0; +static int fast = 0; +static int menus = 0; + +static void switch_function(void) +{ + switches++; +} + +//--- +// Saved system context visualizer +//--- + +void *driver_ctx(char const *name) +{ + extern gint_driver_t bdrv, edrv; + for(gint_driver_t *drv = &bdrv; drv < &edrv; drv++) + { + if(!strcmp(drv->name, name)) return drv->sys_ctx; + } + return NULL; +} + +#ifdef FX9860G +static void ctx_tmu() +{ + tmu_t *t = driver_ctx("TMU"); + uint8_t *TSTR = (void *)t + 3 * sizeof(tmu_t) + 6 * sizeof(etmu_t); + + for(int i = 0; i < 3; i++, t++) + { + row_print(2*i+1, 1, "TMU%d=%d CNT:%08x", i, + (*TSTR & (1 << i)) != 0, t->TCNT); + row_print(2*i+2, 1, "TCR:%04x COR:%08x", t->TCR.word, t->TCOR); + } +} +static void ctx_dd() +{ + uint8_t *STRD = driver_ctx("T6K11"); + + row_print(1, 1, "STRD:%02x", *STRD); + row_print(2, 2, "RESET:%d", (*STRD & 0x08) != 0); + row_print(3, 2, "N/F:%d", (*STRD & 0x04) != 0); + row_print(4, 2, "X/Y:%d", (*STRD & 0x02) != 0); + row_print(5, 2, "U/D:%d", (*STRD & 0x01) != 0); +} +static void ctx_rtc() +{ + uint8_t *ctx = driver_ctx("RTC"); + uint8_t RCR1=ctx[0], RCR2=ctx[1]; + + row_print(1, 1, "RCR1:%02x", RCR1); + row_print(2, 1, "RCR2:%02x", RCR2); +} +static void show_etmu(int line, int id, etmu_t *t) +{ + row_print(line, 1, "ETMU%d=%-3dCNT:%08x", id, t->TSTR, t->TCNT); + row_print(line+1, 1, "TCR:%02x COR:%08x", t->TCR.byte, t->TCOR); +} +static void ctx_etmu(int start) +{ + etmu_t *t = driver_ctx("TMU") + 3 * sizeof(tmu_t); + t += start; + + for(int i = 0; i < 3; i++, t++) + { + show_etmu(2*i+1, i+start, t); + } +} +#endif /* FX9860G */ + +#ifdef FXCG50 +static void ctx_tmu() +{ +} +static void ctx_dd() +{ +} +static void ctx_rtc() +{ +} +#endif /* FXCG50 */ + +static void system_contexts(void) +{ + int key=0, tab=0; + + while(key != KEY_EXIT) + { + dclear(C_WHITE); + + #ifdef FX9860G + extern image_t img_opt_switch_ctx; + dimage(0, 56, &img_opt_switch_ctx); + #endif + + #ifdef FXCG50 + row_title("System context visualizer"); + fkey_button(1, "TMU"); + fkey_button(2, "R61524"); + fkey_button(3, "RTC"); + #endif + + if(tab == 0) ctx_tmu(); + if(tab == 1) ctx_dd(); + if(tab == 2) ctx_rtc(); + + #ifdef FX9860G + if(tab == 3) ctx_etmu(0); + if(tab == 4) ctx_etmu(3); + #endif + + dupdate(); + + key = getkey().key; + if(key == KEY_F1) tab = 0; + if(key == KEY_F2) tab = 1; + if(key == KEY_F3) tab = 2; + + #ifdef FX9860G + if(key == KEY_F4) tab = 3; + if(key == KEY_F5) tab = 4; + #endif + } +} + +//--- +// Interactive in-out switching +//--- + +/* Render VRAM for this screen, used when returning to menu */ +void render(void) +{ + dclear(C_WHITE); + + #ifdef FX9860G + extern 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); + + dimage(0, 56, &img_opt_switch); + #endif + + #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); + fkey_button(1, "SWITCH"); + fkey_button(2, "FAST"); + fkey_button(3, "MENU"); + fkey_action(6, "SYSTEM"); + #endif +} + +/* gintctl_gint_switch(): Test the gint switch-in-out procedures */ +void gintctl_gint_switch(void) +{ + int key = 0; + + while(key != KEY_EXIT) + { + render(); + dupdate(); + + 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) + { + /* Render next frame in advance. When we return from + the main menu, our VRAM will be displayed but + GetKeyWait() will not give control back until a key + is pressed. This will make it look like we render a + new frame right away. */ + menus++; + render(); + dupdate(); + + gint_osmenu(); + while(keydown(KEY_F3)) waitevent(NULL); + } + if(key == KEY_F6) system_contexts(); + } +} diff --git a/src/gint/timer.c b/src/gint/timer.c index 0af9d4d..8013bf8 100644 --- a/src/gint/timer.c +++ b/src/gint/timer.c @@ -54,30 +54,38 @@ static int y[] = { 24, 24, 24, 84, 84, 84, 144, 144, 144 }; void show_tmu(void) { - volatile uint8_t *TSTR; - timer_address(0, &TSTR); + tmu_t *TMU = SH7305_TMU.TMU; + volatile uint8_t *TSTR = &SH7305_TMU.TSTR; - tmu_print(x[0], y[0], "TMU0", timer_address(0, NULL), *TSTR & 0x1); - tmu_print(x[1], y[1], "TMU1", timer_address(1, NULL), *TSTR & 0x2); - tmu_print(x[2], y[2], "TMU2", timer_address(2, NULL), *TSTR & 0x4); + if(isSH3()) + { + TMU = SH7705_TMU.TMU; + TSTR = &SH7705_TMU.TSTR; + } + + tmu_print(x[0], y[0], "TMU0", &TMU[0], *TSTR & 0x1); + tmu_print(x[1], y[1], "TMU1", &TMU[1], *TSTR & 0x2); + tmu_print(x[2], y[2], "TMU2", &TMU[2], *TSTR & 0x4); } void show_etmu_1(void) { - etmu_print(x[3], y[3], "ETMU0", timer_address(3, NULL)); + etmu_t *ETMU = isSH3() ? SH7705_ETMU : SH7305_ETMU; + etmu_print(x[3], y[3], "ETMU0", &ETMU[0]); if(isSH3()) return; - etmu_print(x[4], y[4], "ETMU1", timer_address(4, NULL)); - etmu_print(x[5], y[5], "ETMU2", timer_address(5, NULL)); + etmu_print(x[4], y[4], "ETMU1", &ETMU[1]); + etmu_print(x[5], y[5], "ETMU2", &ETMU[2]); } void show_etmu_2(void) { - if(isSH3()) return; + etmu_t *ETMU = SH7305_ETMU; - etmu_print(x[6], y[6], "ETMU3", timer_address(6, NULL)); - etmu_print(x[7], y[7], "ETMU4", timer_address(7, NULL)); - etmu_print(x[8], y[8], "ETMU5", timer_address(8, NULL)); + if(isSH3()) return; + etmu_print(x[6], y[6], "ETMU3", &ETMU[3]); + etmu_print(x[7], y[7], "ETMU4", &ETMU[4]); + etmu_print(x[8], y[8], "ETMU5", &ETMU[5]); } /* gintctl_gint_timer(): Show the timer status in real-time */ @@ -87,13 +95,14 @@ void gintctl_gint_timer(void) hence ask getkey() to never wait. (The processor is still sleeping during the DMA transfer to the screen on fxcg50, limiting the program to ~90 FPS.) */ - int key = 0, timeout = 1; + int key=0, timeout=1; + int tid=0; #ifdef FX9860G int tab = 1; #endif - while(key != KEY_EXIT) + while(!keydown(KEY_EXIT)) { dclear(C_WHITE); @@ -104,6 +113,9 @@ void gintctl_gint_timer(void) extern image_t img_opt_gint_timers; dimage(0, 56, &img_opt_gint_timers); + + if(tid < 3) dprint(23, 56, C_BLACK, C_NONE, "TMU%d", tid); + else dprint(23, 56, C_BLACK, C_NONE, "ETMU%d", tid-3); #endif #ifdef FXCG50 @@ -113,18 +125,19 @@ void gintctl_gint_timer(void) show_etmu_1(); show_etmu_2(); - fkey_button(1, "SLEEP"); + fkey_action(1, "SLEEP"); + + if(tid < 3) dprint(72, 210, C_BLACK, C_NONE, "TMU%d", tid); + else dprint(72, 210, C_BLACK, C_NONE, "ETMU%d", tid-3); #endif dupdate(); - key = getkey_opt(GETKEY_DEFAULT, &timeout).key; + clearevents(); /* On F1, pretend to sleep and just see what happens */ - if(key == KEY_F1) + if(keydown(KEY_F1)) { volatile int flag = 0; - int tid = 0; - int free = timer_setup(tid, timer_delay(tid, 1000000), 0, timer_timeout, &flag); if(free == tid) timer_start(tid); @@ -132,9 +145,12 @@ void gintctl_gint_timer(void) #ifdef FX9860G /* On F4, F5 and F6, switch tabs */ - if(key == KEY_F4) tab = 1; - if(key == KEY_F5) tab = 2; - if(key == KEY_F6) tab = 3; + if(keydown(KEY_F4)) tab = 1; + if(keydown(KEY_F5)) tab = 2; + if(keydown(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(); } } diff --git a/src/gintctl.c b/src/gintctl.c index 8a7e098..26d3ef2 100644 --- a/src/gintctl.c +++ b/src/gintctl.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -37,7 +38,8 @@ struct menu menu_gint = { { "Hardware", gintctl_gint_hardware }, { "RAM discovery", gintctl_gint_ram }, { "Memory dump", gintctl_gint_dump }, - { "Keyboard", NULL }, + { "Switching to OS", gintctl_gint_switch }, + { "Keyboard", gintctl_gint_keyboard }, { "Timers", gintctl_gint_timer }, #ifdef FXCG50 { "DMA Control", gintctl_gint_dma }, @@ -62,6 +64,14 @@ struct menu menu_perf = { { NULL, NULL }, }}; +/* External libraries */ +struct menu menu_libs = { + _("Libraries", "External libraries"), .entries = { + + { "libimg", gintctl_libs_libimg }, + { NULL, NULL }, +}}; + //--- // Main application //--- @@ -74,16 +84,22 @@ void gintctl_main(void) row_print(3, 1, "F2:gint tests"); row_print(4, 1, "F3:Performance"); - row_print(5, 1, "F5:MPU registers"); - row_print(6, 1, "F6:Memory map/dump"); + row_print(5, 1, "F4:Libraries"); + row_print(6, 1, "F5:MPU registers"); + row_print(7, 1, "F6:Memory map/dump"); #endif /* FX9860G */ #ifdef FXCG50 row_title("gint @%07x for fx-CG 50", GINT_VERSION); - row_print(1, 1, "F2: gint features and driver tests"); - row_print(2, 1, "F3: Performance benchmarks"); - row_print(3, 1, "F5: MPU register browser"); - row_print(4, 1, "F6: Hexadecimal memory editor"); + row_print(1,1, "F2: gint features and driver tests"); + row_print(2,1, "F3: Performance benchmarks"); + row_print(3,1, "F4: External libraries"); + row_print(4,1, "F5: MPU register browser"); + row_print(5,1, "F6: Hexadecimal memory browser"); + + row_print(7,1, "This add-in is running a unikernel called gint by"); + row_print(8,1, "Lephe'. Information about the project is available"); + row_print(9,1, "on planet-casio.com."); #ifdef GINT_BOOTLOG extern char gint_bootlog[22 * 8]; @@ -101,6 +117,7 @@ int main(GUNUSED int isappli, GUNUSED int optnum) int top = _(1, 0), bottom = _(1, 0); menu_init(&menu_gint, top, bottom); menu_init(&menu_perf, top, bottom); + menu_init(&menu_libs, top, bottom); /* Start the profiling library */ prof_init(PROFCTX_COUNT, 2); @@ -118,10 +135,13 @@ int main(GUNUSED int isappli, GUNUSED int optnum) #ifdef FX9860G extern image_t img_opt_main; dimage(0, 56, &img_opt_main); - #else + #endif + + #ifdef FXCG50 fkey_action(1, "INFO"); fkey_menu(2, "GINT"); fkey_menu(3, "PERF"); + fkey_menu(4, "LIBS"); fkey_button(5, "REGS"); fkey_button(6, "MEMORY"); #endif @@ -135,6 +155,8 @@ int main(GUNUSED int isappli, GUNUSED int optnum) menu = &menu_gint; if(key == KEY_F3) menu = &menu_perf; + if(key == KEY_F4) + menu = &menu_libs; if(key == KEY_F5) gintctl_regs(); if(key == KEY_F6) diff --git a/src/libs/libimg.c b/src/libs/libimg.c new file mode 100644 index 0000000..baae8e3 --- /dev/null +++ b/src/libs/libimg.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +#ifdef FX9860G +#include +static void render(void) +{ + extern img_t img_libimg_swords; + + img_render_vram_gray(img_libimg_swords, 8, 8); +} + +void gintctl_libs_libimg(void) +{ + int key = 0; + gray_start(); + + while(key != KEY_EXIT) + { + gclear(C_WHITE); + render(); + gupdate(); + + key = getkey().key; + } + + gray_stop(); +} +#endif + +#ifdef FXCG50 +static void render(void) +{ + extern img_t img_libimg_sq_even; + extern img_t img_libimg_sq_odd; + extern img_t img_libimg_even_odd; + extern img_t img_libimg_odd_even; + extern img_t img_libimg_train; + + #define sq_even img_libimg_sq_even + #define sq_odd img_libimg_sq_odd + #define even_odd img_libimg_even_odd + #define odd_even img_libimg_odd_even + #define train img_libimg_train + + img_t in[4] = { sq_even, sq_odd, odd_even, even_odd }; + img_t out = img_vram(); + + img_fill(out, 0xffff); + img_fill(img_sub(out, 138, 0, 28, -1), 0xc618); + + for(int i=0, y=8; i<4; i++, y+=52) + { + img_rotate (in[i], img_at(out, 8, y), 90); + img_rotate (in[i], img_at(out, 8, y+26), 0); + img_rotate (in[i], img_at(out, 34, y), 180); + img_rotate (in[i], img_at(out, 34, y+26), 270); + img_upscale(in[i], img_at(out, 60, y+1), 2); + img_hflip (in[i], img_at(out, 110, y)); + img_vflip (in[i], img_at(out, 110, y+26)); + img_render (in[i], img_at(out, 140, y+13)); + img_dye (in[i], img_at(out, 248, y), 0x25ff); + img_dye (in[i], img_at(out, 248, y+26), 0xfd04); + + img_t light = img_copy(in[i]); + img_t dark = img_copy(in[i]); + + for(int k=0, x=172; k<=2; k++, x+=26) + { + img_whiten(light, light); + img_darken(dark, dark); + + img_render(light, img_at(out, x, y)); + img_render(dark, img_at(out, x, y+26)); + } + + img_destroy(light); + img_destroy(dark); + } + + img_t light = img_lighten_create(train); + img_t dark = img_darken_create(train); + + img_render(light, img_at(out, 282, 24)); + img_render(train, img_at(out, 282, 56+24)); + img_render(dark, img_at(out, 282, 56+56+24)); + + img_destroy(light); + img_destroy(dark); +} + +void gintctl_libs_libimg(void) +{ + int key = 0; + + while(key != KEY_EXIT) + { + dclear(C_WHITE); + render(); + dupdate(); + + key = getkey().key; + } +} +#endif diff --git a/src/mem/mem.c b/src/mem/mem.c index 5b2db95..8bd0c24 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -92,7 +92,7 @@ void gintctl_mem(void) for(int i = 0; i < lines; i++) { - int status = line(mem, header, bytes, ascii, size); + GUNUSED int status = line(mem,header,bytes,ascii,size); #ifdef FX9860G dtext( 5, 6*i + 1, view_ascii ? ascii : header, diff --git a/src/perf/render.c b/src/perf/render.c index 7cf8c55..2d8c214 100644 --- a/src/perf/render.c +++ b/src/perf/render.c @@ -15,21 +15,16 @@ struct elapsed { uint32_t fs_r5g6b5; }; +#define test(out, command) { \ + prof_clear(PROFCTX_RENDER); \ + prof_enter(PROFCTX_RENDER); \ + command; \ + prof_leave(PROFCTX_RENDER); \ + out = prof_time(PROFCTX_RENDER); \ +} + static void run_test(struct elapsed *time) { - #define test(out, command) { \ - prof_clear(PROFCTX_RENDER); \ - prof_enter(PROFCTX_RENDER); \ - command; \ - prof_leave(PROFCTX_RENDER); \ - out = prof_time(PROFCTX_RENDER); \ - } - - extern image_t img_swift; - - test(time->update, - dupdate() - ); test(time->clear, dclear(C_WHITE) ); @@ -44,12 +39,11 @@ static void run_test(struct elapsed *time) ); #ifdef FXCG50 + extern image_t img_swift; test(time->fs_r5g6b5, dimage(0, 0, &img_swift) ); #endif - - #undef test } char *printtime(uint32_t us) @@ -95,31 +89,32 @@ void gintctl_perf_render(void) row_print(4, 1, "Press F1 to start the test."); + row_print(6, 2, "dclear():"); + row_print(7, 2, "dupdate():"); + row_print(8, 2, "drect() 32x32 (even position):"); + row_print(9, 2, "drect() 32x32 (odd position):"); + row_print(10, 2, "drect() 396x224:"); + row_print(11, 2, "dimage() 396x224 (p4):"); + if(test) { - print(6, 90, "dclear:"); - print(6, 105, "%s", printtime(time.clear)); - - print(83, 90, "dupdate:"); - print(83, 105, "%s", printtime(time.update)); - - print(160, 90, "rect1:"); - print(160, 105, "%s", printtime(time.rect1)); - - print(237, 90, "rect2:"); - print(237, 105, "%s", printtime(time.rect2)); - - print(314, 90, "rect3:"); - print(314, 105, "%s", printtime(time.rect3)); - - print(6, 130, "fullscreen img:"); - print(6, 145, "%s", printtime(time.fs_r5g6b5)); + row_print(6, 35, "%s", printtime(time.clear)); + row_print(7, 35, "%s", printtime(time.update)); + row_print(8, 35, "%s", printtime(time.rect1)); + row_print(9, 35, "%s", printtime(time.rect2)); + row_print(10, 35, "%s", printtime(time.rect3)); + row_print(11, 35, "%s", printtime(time.fs_r5g6b5)); } fkey_button(1, "START"); #endif - dupdate(); + /* Make the test here as we don't want to re-update the screen. + Because of triple buffering this would display an old + frame such as the application's main menu. */ + test(time.update, + dupdate() + ); key = getkey().key; if(key == KEY_F1) run_test(&time), test = 1; diff --git a/src/util.c b/src/util.c index 0b6ce8d..eaabdd4 100644 --- a/src/util.c +++ b/src/util.c @@ -26,7 +26,7 @@ #ifdef FXCG50 #define ROW_X 6 -#define ROW_W 0 +#define ROW_W 8 #define ROW_Y 20 #define ROW_YPAD 2 #define ROW_H 14