From e35dad635fa5caa0746cfc5a6917846f50b12abc Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 13 Apr 2020 02:24:34 +0900 Subject: [PATCH] working tiling for text draw --- EGA8x14.png | Bin 4139 -> 4279 bytes src/net/torvald/tsvm/VMGUI.kt | 6 +- .../tsvm/peripheral/GraphicsAdapter.kt | 54 ++++++++++-------- terranmon.txt | 1 + 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/EGA8x14.png b/EGA8x14.png index 306d468c33e45fe541e21446d387b35c54d7cd21..f53260d3579b89264f6c7775e2797951a5d3b694 100644 GIT binary patch delta 4269 zcmV;e5K`}}Ah#iqB!6ycLqkw$V`BgSD3NuM%_~Gv7{-6bh!|P0kSy*3QKlwJmW;)0 zCTUOxn>%;D)V2tpJAdA9s8jVis(Ssu@6XYa z&3OjYH3^Rxj$0BQ6Hcy_9K{>L9Y#^l3hxUKx^h6_3#DfQepFlt_*JnxlbV2#>Zuie zaOMXaMb{GU7w)mlvhjT$b(2WWo}HH3C9@lk6ba&JWGJ(QNr|XbTQd9G7pwXvSr(5W ze}@XLI0_WSJAWu@S-R$==0(rRXHrqQ|IX9P4-W<1BXMYW@coxwXxxI&P2c}G@cqw2 zsK19ZyXIe(oJQY7->hjpd(gH9C+9USvkj-~(0S+Ru3nYuWrp&3cs_>KG_+qq^Fol- z_c}+nFtaL8bO}4V&?o!b7QX-$SZEX(;eY}F000SaNRy%g5`XVWL_t(|+U;G5j-)sY zr4j%C%e|Ls#HJGaJs%K=EsdtDC?JR9`}oa)!Cx7=WFc=VX2q40i)BUozV8a4-)jmi^`=z;#DCF%zpoGm??_nrd!~xI{ zp@-N}EUbNI`>w;fQSAUxp#|lO=mJPW&D-!QzE?1D)@N4iL-kf%`$-3c8?fJm`xd(NhL!M zYaEFh|Ll~qbz-#+qn({J>UoP?MAiuufw0#1Xr4On=4!qZ_8oh~1Q1hfq^`?OQX5~? z_)%{nix`q~$*LxbzJT+fyqIfUw9(>Oksy=oj(_~{JxU|R6fmp{^*)-k0F4JBRnz@Rmd~idk<8#k~T>rd7A4O8GJ9iOhXzANoGhess*)kU{zgd10~9d%~E(x1xr41 zD}M>MEZ%D^f!hOo0c8qa903aQV4v-zKh+GoGy2!&h^M*xp4Ua~BDqhQa^@NTk} zN%I!?at1MiSmZ*qNedRMpx0M`XctemR!Vyr!UE6*Ly@Re`MlmbL~TTVBUu)ie7u>| z>M$Wt^XE%{vpV|7Dkqs@ugEvZNbSnDsee$(p;@U*y^}FAeQL=QS6l25FQ&&Afl^8< z6`Ud_u(!!*$XUD4SD(NUTaY}eUh{3FY_qeIjS9tLBUl(7eJ5%42#Xmqg0^nyY9Jy5 zpb;_N&@jtMMivu|D9V;aq~aB+hM-6Rigg{2yo446L1G@B=7Ug$?QJ4oz#GG^XMdl2 zk=&*&XqM~-)VmhpR%OQRECwecSaws`E(-oQ;S_CHCbjEGuhBc=~z z6By%)WfGF(WMWXNK;abR<<_7n!UGMuNW76Ji z)|n9^TZR~wc8wTUmj(Ryy`2X}=-H^8;L+1rA&cqe5sf&}b^sLt${w~Zlz%C>5TKwC zpr8<-U`?RCfnFUoLc(XY5aj)gGmOzoB^f{}prG~D)hcfwh~=#^D!oT54#CJRS=2;Sy|?lPE)8W0E`J0lC7lRigyBQ4d!qJnUD&6}rr3%&Qh1yCDG?>A`U zOeEHyUEh7C1?>HOwPD6v%FUbHX+=B)S#Ci9r1K}+f9Fa=N%rP5Mx%5s!0XLpEP+pv zl1Jl@%xJn32`FEHHh(zO5%cu^fEnp*cOk(ZeTsTKRf>zdiib;TQgpA16qF3$D)AN}6ndUzy?>Xv&r*p4eg0j-b=MMj zm);tcEo6xr&bCp^rvHE7b^QV|i%rhHnP~`sS^=$v7`0Q&7HigO5L@aUMv`)C+qmA? z5q2Z3-;QE5;>*LGPR#wY1fwt%aw-I1`ttR>b(%L%dp_D% zP?Jrp-b{)AA_y7rd=C{=*MEDtFMw@CIqN&pDAKloGw6z7mYD-)mPdes$%MdyLV$uv zU@Bk0O#1N^@(3DUu9=q^Q}?tKV1;0mUd2*WmD4J?T7NZ=>K^`ZU`*jX3VX2Lq?W{Z zy-_Siv+3MdrI%})GYj=;kzi-NNm?R>CA}Oe_?&%$JlVmcd7Kv?d9F5ht6AG!EZRbj zq(NW3$(o$u%?{S?NAn`JjkT7unTLrwws)0Qoes*C-Nxqs(lwHi;7_G^n zz23Xb$$y*`8HUtvJM|5;^t7{d(m?fDR?kJgw+NLQ!Z0i`!w%r0)?Nfy4c<2YZufAM zjI4kJY(VPc5MV2B;L=c*z{OZsOTqSx7kR^@SpE3?n>#9dM8zA9o};a)7NQ0jf=2xU zw9lx3G*ZKm=W9lkh{)ya@p<|lM75gf?awah>VHwval{58jV8TC8neb{wUr>xN6hQz z@4mkOXaPOl^G(w3+cg+AW&MOgGSrRMqk$)SLpcJ>z)l_4M?na(~SVECC%IT z(Q=&~Pjt2MtLMgy?~q7}wa@}9U1wis7V@ewOk)S=IY7KsE*SwU`}+ALNMzL8l<{tv z!hedO2f9E}8o^z_Aa^#K%A6l7vwWF?k>2wjAxgVH?R)m9&2PPl zBYhpIuEBO0(W+~pRZZ@qgov#J@km;{rhj{TbClkXWbQ=h@u(-$`tEZ=%-LXejv7YV zwjm{8t`xricn5!l(I8Q@PcDyQL2z%Xnsv>X7y-sWb)be7DR$n=r##oai%oma0!qD& z<|aK;GjO%fbY%zkNE&Nv{tRNYz){y9uZI(sOIDaf?pHH|Q2zC17LYCUvGNasD1U8s z(~t#dyu;I(x}eWSy{ev+gi3c0msGk{Hm6l%rPJq0A4lbz9&z9Bwc;`rVI#4ypY6xK_jO52j-ZBx>6Wh66B@bANV6|-Ts|wl% zAv9CD&4CP_mw|^)bkUV|T z3D=Nhzq@=Ziv(AY_KcYfSw#UBhaFL0r2o&@ z-22=<&)YBosl}IZ!nEgm-+v$Re9L=xL*%Tsv%{*?%j;lX2`o%#Og`wt7|F_?*#GmSjq zC&x(-4_6Per7B|#QQy7I;*752Bn&E0}F};6chp!6ao}12dXp3E5vvNw)XiMsasl` zwYLYist9n$0%Z9Tv}dgt(JVHNid`DZ^Vhqu0<9}g|JZ1IlNI$yfuea9J zjiLbA8Oql-3y5qB7g1!Y$8WV09!Xs+zkl--$lB2|Z)YJeD-5j1_pYcv z*gJuquH~bXD#=)0>ezb+gjAXuI6H5y!jw+xgW3UVffq)Ag7?CsoIx{n+1RDw2*FDp^r1xiy?O@!olEjVZqD=a=MX!CMMv$!rAJGPl zE8L-8@_*irMe~EquIhSH<_>lNEtDY2iDS73b#^_)&JnGWLo9&VNW`3arC{Z)1vn!W zo0bK5Wdtvuw6cKA`6Cj1M)QpnEkN=EFz!kQo7vzGja_**U-N_XuFo!z9#KJ=5s96d zQuLjh5#3KYbZi^w4ALfNIq|5b@RouNGtOfwUm`$x_O6FY3@HRCSQ-8TS~BtFEPZQ@BIV zrj~{Gh5Kzepzwv#wF*Bf&Q$nSu|1oZ0Ke)P$<(k`!+O>>h5Lk~X0E9JoJZXxWaQ^& zq;|>d#v#EZF(PObSs{nZfYiKX_P1~F+c!l)Ji7cXO4#DakQHygs72{&NKK1w$d{v} za{ryDlO7(bbPvU#{=xHJdLXz3pJmVcIPkpBL#VrlvwYQGkeo)}L@!sh=pKaE;pDuk zY1?qR0iAbN%1(Vtbu#_wG&~#Z= zDzu<{5nTXD2--moK>52SA9*Q8OEqZMzj;MU+pu<`{I6ug>(+?7x7?qqUOIlrTh`#e?lPo(WvJwauHc4 zPz1tS$I(1>-p$o~C+rwU#0Maz*hpQM{YY(oQS(Q=i7aAB&LyjwDEb1flk#G&b< zsI&k`JRCYdO^dNUZ+Ul5^Xd6h*m%Gp0x+9}c&(7=6lnpajrJ}8yGiKtyGZ^Lg0{b% zmXGOq2(tnjMw)xM!j02hOP6Tp}Vv9 zOY{GrF?ZSmOV&B$nb83&tfWX8CK8D09zC5Eve?AZNW_V@13ZDc78Dc|6ciK`6hvwstd#E6Q6nUL zRtrJKXPjY-7NZ&3(0+klXVu7=cc8g>qcHAKH0-ERlC`A`VO2IO=15^*!PQyw)*rSVE+Q(>h7S&3jS%n(2EQ9C*Kh+rG zDis?sc&4?<+dv7Kd!{=&!e z@=xT%NZvN7Tr0wcA~scP(~inX%skUPg|jS91)It?wFJ+GYLr#L>+l8dfuok7WB`{z zBT^{zyvzD5^PHs;2m1b1!gbdYxJqx0$`-Oj4QJaZcGLgA@VI^fnZ+h|-^?@wK&^n* zLX6s}Ws5ayHHajpa3cXIAQx z*6cfXHXsL14@cERG`*Yk!Am)PQKUDUbY~`qrm=vi#>}e(#2w`mYj)CO>;PV)6Z8Bo z!6*!c+zJ7hzI;7zo#xHc-jDVb)MOK@H&f!j2tr1@-$MmaZ|Y+KZSB7M7*i~PPey`l zd1B{)nSz3Xf`WqGWq_UZ;~DY@8eXoMml;#{7IpxSy7Yw2XT7dS1y^f!Q*{r&I|(OD z;XMj_vfiYY#CW|?EJm~G+_TclqYO9M)Tc#)gY_n9i4>Ofa-`sM_6hQ22amp^XBhI- zF|?Ys-Nm9U`m6>3~zR@_B@&wsco!f{j>vnW}Yey37#t8-D%#Zrfytam{F3i z<`QKWvo}X;a%ivjE^{(>MTQ~uV<)V|2Uz;@Y5Fdz=OVvbgh~xz7?zk}2MECq#%=lL z1d^wH|A+Bnz0u>v2Ba1g+=~L#61<0X^(fepF_1Sr%EEUeTE1k?&+{H_O|=j;$PhH@ z7r=x&A@TjlWSJg=h-SiUe%AaveGj5q&Gh!?kaYDZLrBC1A&n-zMH;i_XSJ0e??=q* z*WZ5qF6o|6l6If2!LTs{DgrQ8F18pn+EzCDy5_h-=g(gEY!GWeqP?4lnUj?XSfM5R zx<`oeUSIKT%=}JiFl(U&R=Uos#s=dcT$JqL)l$|WOUWnaINK8cKan=-DJDXa*3 zq6-wI5iGNK5ycy+CFzV!KDT!Q4SP? z3knLJ4plAmr7U0;-}g3dMuJtC%3ofa0orzsnIk(-mVLM598sJ9(}CW=tR)Lk;k4=+ zXjPL{ln}9XARbAJ*Ys!~j?(*)%$*259`$5e$G#@STn%Q|s9~gS8&U#hrttk~Gkr!k zv8h^5Rw1oX#Sv@9#0W6z{fQb@q}X{cpYmMyE;h^KBTBuEzD;_kX5eby>B}Jg;U3q5SK~EFfFxW91(NQQGXLAq&uWho>`jL7$C!RXr&Q zmF^z?c7xEUkmBg{dD6#G`KE^~St;~TZktpDLK7gfg}{-}stL8Mw2XvgG1L@gsfn+4Q6VsP=YBm~Izx_R2tX)V~8kgA!8vt#_=70w+tUpnDP z9XzdK2V%y)169eG#BZaV@27;DvVb`UX-wDY8w=!HL zHiyne+)<^}h+cvtby-uRVQ-lvC`NhfEal##HH~adA)>){SwJ7E|F5tE9JMX;?HQGU zRj@yn_9V&PzrBD1CJQL)x)%5lNxm(0d1k!dGVXy0VbZ@$<*kDK;LxOT4GG?m8T5Dr zC<;&%peVpg;k<5iuZ5h31g-Gl?J>@K!^Rbb8z1!=7}>*50>DwA!9I{{Bb=$nfAX@6H@Q`uWp>c?@Qv zN3)=#-cKQb7xPg4(>hM{`y+LG3ptKlCu=N234x^r6chp!6ao|! z0u;Ou=vp%o8p4Wd))C`-ymVGcpAAYiVP5!l-IXQXav zZPuP1+^QnLiUr8>C1~$@V?=X$%{?YHDkC*)CW6kGL$um>S|d+cJv-8muKDY&HFcvX zKz2rR34sNL00o5r1%&_wg#ZNw1qB6GmDT$Kv}aD%^AW%rsjQ*skv)pp4(B5XOAPTE zKUNw~wBi<8ztb*-`VzDYlTN;@PXe_e)S0Q9n zj=XIuh1lM&_c6U}v{LXbL?B1+8?&g;=-txyNoMtkIi8~ekCv1v@8Ym6&sf&tnR|4i zW?O5q_kT;zfe;x$TQpB87KX2FB`qsWuzDM+QK9Jdv8>$|*}+kpZw=(=ow!+u*c)3y znCLkUvx8@`fXKFR5k;nY{8l^Rk<`U}0BdVFt2{lVS|^mHvBom5H2 z@>0j%7%7Xh8&nIng_g2{f`Wn~_jiV~mLNyHV%aGYteP>mWA^DpyMxX==_?9d_e|@O z-k&wMlX1sNDhZ;CGU?YAz4nQT9ocH|8Ew#*;STkZ_jWFtA7mHy#3ZDI#siExRiTt1 z%86rn26cArN;O7JJf^Y$W+M@E>P*4PTMKYUDz+^P@X82YK51nEnct5{@EOfFQnUcc z55Tx98Ej^QKQwmb*?i3p(!0L9Kzc?6Wkw`+W=hd3HzT^Aa_HQ=yhn=rW4mUqFoZnO p*mP@aT$y_3LZyZk0u;O%{sMPoZ*vlkZixT@002ovPDHLkV1oCP*yaEL diff --git a/src/net/torvald/tsvm/VMGUI.kt b/src/net/torvald/tsvm/VMGUI.kt index 96d4160..db1f675 100644 --- a/src/net/torvald/tsvm/VMGUI.kt +++ b/src/net/torvald/tsvm/VMGUI.kt @@ -90,11 +90,11 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() for (k in 0 until 2240) { // text foreground - vm.poke(-(254820 + k + 1) - hwoff, 239.toByte()) // white + vm.poke(-(254912 + k + 1) - hwoff, (Math.random().times(255f).roundToInt()).toByte()) // white // text background - vm.poke(-(257060 + k + 1) - hwoff, -1) // transparent + vm.poke(-(254912 + 2240 + k + 1) - hwoff, (Math.random().times(255f).roundToInt()).toByte()) // transparent // texts - vm.poke(-(259300 + k + 1) - hwoff, k.toByte()) + vm.poke(-(254912 + 2240*2 + k + 1) - hwoff, (Math.random().times(255f).roundToInt()).toByte()) } } diff --git a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt index 9ff0617..eb45d25 100644 --- a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt +++ b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt @@ -148,8 +148,14 @@ class GraphicsAdapter : PeriBase { rendertex = Texture(framebuffer) + batch.shader = null batch.begin() + // clear screen + batch.color = Color.BLACK + batch.draw(faketex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat()) + + // initiialise draw batch.color = Color.WHITE batch.shader = paletteShader @@ -181,7 +187,7 @@ class GraphicsAdapter : PeriBase { val back = spriteAndTextArea[3940 + 2240 + addr].toInt().and(255) val fore = spriteAndTextArea[3940 + addr].toInt().and(255) - textPixmap.setColor(Color(paletteOfFloats[4 * char], paletteOfFloats[4 * char + 1], paletteOfFloats[4 * char + 2], paletteOfFloats[4 * char + 3])) + textPixmap.setColor(Color(0f, 0f, char / 255f, 1f)) textPixmap.drawPixel(x, y) textBackPixmap.setColor(Color(paletteOfFloats[4 * back], paletteOfFloats[4 * back + 1], paletteOfFloats[4 * back + 2], paletteOfFloats[4 * back + 3])) textBackPixmap.drawPixel(x, y) @@ -205,13 +211,15 @@ class GraphicsAdapter : PeriBase { faketex.bind(0) batch.shader = textShader - textShader.setUniformi("tilesAtlas", 1) textShader.setUniformi("foreColours", 4) textShader.setUniformi("backColours", 3) textShader.setUniformi("tilemap", 2) + textShader.setUniformi("tilesAtlas", 1) textShader.setUniformi("u_texture", 0) textShader.setUniformf("tilesInAxes", TEXT_COLS.toFloat(), TEXT_ROWS.toFloat()) textShader.setUniformf("screenDimension", WIDTH.toFloat(), HEIGHT.toFloat()) + textShader.setUniformf("tilesInAtlas", 16f, 16f) + textShader.setUniformf("atlasTexSize", chrrom0.width.toFloat(), chrrom0.height.toFloat()) batch.draw(faketex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat()) } @@ -233,17 +241,22 @@ class GraphicsAdapter : PeriBase { } private fun peekPalette(offset: Int): Byte { + if (offset == 255) return 0 // palette 255 is always transparent + val highvalue = paletteOfFloats[offset * 2] // R, B val lowvalue = paletteOfFloats[offset * 2 + 1] // G, A return (highvalue.div(15f).toInt().shl(4) or lowvalue.div(15f).toInt()).toByte() } private fun pokePalette(offset: Int, byte: Byte) { - val highvalue = byte.toInt().and(0xF0).ushr(4) / 15f - val lowvalue = byte.toInt().and(0x0F) / 15f + // palette 255 is always transparent + if (offset < 255) { + val highvalue = byte.toInt().and(0xF0).ushr(4) / 15f + val lowvalue = byte.toInt().and(0x0F) / 15f - paletteOfFloats[offset * 2] = highvalue - paletteOfFloats[offset * 2 + 1] = lowvalue + paletteOfFloats[offset * 2] = highvalue + paletteOfFloats[offset * 2 + 1] = lowvalue + } } @@ -316,9 +329,9 @@ uniform sampler2D foreColours; uniform sampler2D backColours; uniform sampler2D tilemap; -uniform ivec2 tilesInAtlas = ivec2(16, 16); -uniform ivec2 atlasTexSize = ivec2(128, 224); -ivec2 tileSizeInPx = atlasTexSize / tilesInAtlas; // should be like ivec2(16, 16) +uniform vec2 tilesInAtlas = ivec2(16.0, 16.0); +uniform vec2 atlasTexSize = ivec2(128.0, 224.0); +vec2 tileSizeInPx = atlasTexSize / tilesInAtlas; // should be like ivec2(16, 16) ivec2 getTileXY(int tileNumber) { return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x)); @@ -345,44 +358,39 @@ void main() { // default gl_FragCoord takes half-integer (represeting centre of the pixel) -- could be useful for phys solver? // This one, however, takes exact integer by rounding down. // + vec2 overscannedScreenDimension = tilesInAxes * tileSizeInPx; // how many tiles will fit into a screen; one used by the tileFromMap vec2 flippedFragCoord = vec2(gl_FragCoord.x, screenDimension.y - gl_FragCoord.y); // NO IVEC2!!; this flips Y // get required tile numbers // - vec4 tileFromMap = texture2D(tilemap, flippedFragCoord / tilesInAxes); // raw tile number - vec4 foreColFromMap = texture2D(foreColours, flippedFragCoord / tilesInAxes); - vec4 backColFromMap = texture2D(backColours, flippedFragCoord / tilesInAxes); + vec4 tileFromMap = texture2D(tilemap, flippedFragCoord / overscannedScreenDimension); // raw tile number + vec4 foreColFromMap = texture2D(foreColours, flippedFragCoord / overscannedScreenDimension); + vec4 backColFromMap = texture2D(backColours, flippedFragCoord / overscannedScreenDimension); int tile = getTileFromColor(tileFromMap); ivec2 tileXY = getTileXY(tile); - // cauculate the UV coord value for texture sampling // - - vec2 coordInTile = mod(flippedFragCoord, tileSizeInPx) / tileSizeInPx; // 0..1 regardless of tile position in atlas + // calculate the UV coord value for texture sampling // // don't really need highp here; read the GLES spec - vec2 singleTileSizeInUV = vec2(1) / tilesInAtlas; // constant 0.00390625 for unmodified default uniforms - - vec2 uvCoordForTile = coordInTile * singleTileSizeInUV; // 0..0.00390625 regardless of tile position in atlas - - vec2 uvCoordOffsetTile = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1) + vec2 uvCoordForTile = (mod(flippedFragCoord, tileSizeInPx) / tileSizeInPx) / tilesInAtlas; // 0..0.00390625 regardless of tile position in atlas + vec2 uvCoordOffsetTile = tileXY / tilesInAtlas; // where the tile starts in the atlas, using uv coord (0..1) // get final UV coord for the actual sampling // - vec2 finalUVCoordForTile = (uvCoordForTile + uvCoordOffsetTile);// where we should be actually looking for in atlas, using UV coord (0..1) + vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1) // blending a breakage tex with main tex // vec4 tileCol = texture2D(tilesAtlas, finalUVCoordForTile); // apply colour - if (tileCol.a > 0.1) { + if (tileCol.r > 0) { gl_FragColor = foreColFromMap; } else { gl_FragColor = backColFromMap; } - } diff --git a/terranmon.txt b/terranmon.txt index 2fa0fb5..832b1cc 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -67,6 +67,7 @@ ELSE FI 512 bytes Palette stored in following pattern: 0b rrrr gggg, 0b bbbb aaaa, .... + Palette number 255 is always full transparent (bits being all zero) MMIO