PageSourceSearch

https://snmetamorph.github.io/assets/js/6e095c8b.ae9762f0.js

js snmetamorph.github.io collected 2026-10-03 09:59:15 UTC 32,087 bytes, 1 lines download raw bytes

1(self.webpackChunksnmetamorph_blog=self.webpackChunksnmetamorph_blog||[]).push([[9063],{7577:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/build-process-1.dc16eb8.661.png 661w",images:[{path:s.p+"assets/ideal-img/build-process-1.dc16eb8.661.png",width:661,height:418}],src:s.p+"assets/ideal-img/build-process-1.dc16eb8.661.png",toString:function(){return s.p+"assets/ideal-img/build-process-1.dc16eb8.661.png"},placeholder:void 0,width:661,height:418},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAtElEQVR4nEWNzU7CQACEZ7e7bbG0kKUUgZu8Bw1q4gE0uuVS4nvowXf/CC2Jhy+ZSeZHn5fIe//BVx+JfUf87oiXka4/czyf+Pn7Rb5IUSqU3HH/2jqLJPaHPaq2M5KVxy08rva4R4+7+caTNhmaiMPbM5ouSxQMChYzN2hpUW0xwZLUbnhoX1qUhxxVQqVBmYYFPYzY6Xjdvrao2a1wpSNfTJhvC/xTINsVrOsNVZgN5VvwCg5fTgQ80hbMAAAAAElFTkSuQmCC"}},5724:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/build-process-finished.31e9753.661.png 661w",images:[{path:s.p+"assets/ideal-img/build-process-finished.31e9753.661.png",width:661,height:418}],src:s.p+"assets/ideal-img/build-process-finished.31e9753.661.png",toString:function(){return s.p+"assets/ideal-img/build-process-finished.31e9753.661.png"},placeholder:void 0,width:661,height:418},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAwElEQVR4nC3MSU7DMACG0d82ELtJmqEE1UkQIHGJJnTBmkEkDEJiUYYT0PtLH4uyeNunl/dX7j8eedpNTLuZ6Wdm+p6ZPmfmr2fu3h7Y/+5RVueo1EEutPpXCVtZJDFsBtTEhvQ8I73ISc48JzEh6QNJ5/FtQF5sb7eoqAv8KhCaBS5zmKXDFg67dLji6DCOAyqbEhMdWht0alBnULQ
1oCts5FMR4M6L1VSTEBUVfUvUpx5cV/jqjbVryeomM2IwDf8VmT13zPpsPAAAAAElFTkSuQmCC"}},2495:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/cmake-cache-generated.c01eb70.661.png 661w",images:[{path:s.p+"assets/ideal-img/cmake-cache-generated.c01eb70.661.png",width:661,height:418}],src:s.p+"assets/ideal-img/cmake-cache-generated.c01eb70.661.png",toString:function(){return s.p+"assets/ideal-img/cmake-cache-generated.c01eb70.661.png"},placeholder:void 0,width:661,height:418},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAt0lEQVR4nEWMPW6DQBgFPwjghWy8fzhBODg3QRQ0UCFwZHMRrj9WtkkxxUhvnqzbxv3+y77vPB8PnvvOtm0sy8K6rszzzHEcSPVeURQ5WZ5RFAUiQpIkkTRNo/d9j1y/r3S3Duc99aWOhBBwzhGCj/E0TYi1Fuct1hq8cxhj0FqjToqyquLjOI7IX900DcF7lFK8pSl5lpOdMlRZ/g/bnxbzZbGfjjqcKZsa3Z65fXR47ZFEGIaBFyaEUHs06nDKAAAAAElFTkSuQmCC"}},6024:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/ground-truth-1.9a2bd22.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/ground-truth-1.9a2bd22.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/ground-truth-1.9a2bd22.1560.png",toString:function(){return s.p+"assets/ideal-img/ground-truth-1.9a2bd22.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAk0lEQVR4nF3POwvCQBAE4Mvuzu7lUagkKMHOQtRKRKz9/z9q5C4+wGJgio+BSU3TsERFCWS6t4zo6d7RLCgKwpSpoJQSI7c8nu/czge23apCNacqqIIfBMDr7cnT5cH1ZseIgYagWoG2wBIR4TjOnKY9+2H9XbS6+gcNuQYWS39DKVD1c0Zolglv66kCAGd4EDC+AFA+QUwwo+NzAAAAAElFTkSuQmCC"}},515:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/ground-truth-2.88bae06.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/ground-truth-2.88bae06.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/ground-truth-2.88bae06.1560.png",toString:function(){return s.p+"assets/ideal-img/ground-truth-2.88bae06.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAArUlEQVR4nB2MS27DIBQAOUGxIQ8eP+M6oFqp5Ebd9P4nmypZzWJGY8a8KLkTboo4JfiIsw7xSu0PtuP5ptFyomVgFyGGjaQ73kXWVenjl/v5R90vTEgDLZMUM5onQQ+czyy+0vbrHb6uJuaBhMb3fJDqFyIbXirWZZxstM8ftJ6YqJ3lw7NYIbeT2k5Wl3C+4F0ipUHKE1NDIkrjyHdm6OwvaQW1N3QVemwUUf4ByaJO2iUFwsoAAAAASUVORK5CYII="}},9754:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/ground-truth-3.677ef73.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/ground-truth-3.677ef73.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/ground-truth-3.677ef73.1560.png",toString:function(){return s.p+"assets/ideal-img/ground-truth-3.677ef73.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAr0lEQVR4nB3PS27CQBBFUY8Cxu6u6v8Pk5AICSExyyz7X9eN7PnRfXqTuoo1DlmFUQajXanlimjBhYHGwW6m87zycVoIoVNTJ4VCLRuiFZ821DfMDq14fLqxfb0JaePx/D1K1jXEd6xv2B3GWMn9Qb+9yP2H5/vvAKtk5kUxWrDSmM4XJdf7MSWSGP0bayPiKosJGIkYSUyX04yxnhIrdlWCC3yOOzk21v2kzxgN/AN5h0o2xZxpKgAAAABJRU5ErkJggg=="}},4421:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/ground-truth-4.af8853c.1600.png 1600w",images:[{path:s.p+"assets/ideal-img/ground-truth-4.af8853c.1600.png",width:1600,height:900}],src:s.p+"assets/ideal-img/ground-truth-4.af8853c.1600.png",toString:function(){return s.p+"assets/ideal-img/ground-truth-4.af8853c.1600.png"},placeholder:void 0,width:1600,height:900},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAIAAAB1kpiRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAmUlEQVR4nD2MwQrCMBAFd9PdJCYxTdPqwdIWRaNURaGKCF70/z9KctDh3eYxAIAAiCgQEX4QszE++hqyyA8QRVHFZT/sD8fHNL3T9uJdDUyKSFLBRLLr0/32uZ5fp/G57sfyr5U0cxcBhHNhGFLbbrp2Z2YBiBTnaecqa0utrPexrJqmWVkTQEtFxLnOKoSFZC0EMbOzNvj4BZhZCgo+MZ4HAAAAAElFTkSuQmCC"}},6505:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/kitty-shell-1.e22d9ad.452.png 452w",images:[{path:s.p+"assets/ideal-img/kitty-shell-1.e22d9ad.452.png",width:452,height:601}],src:s.p+"assets/ideal-img/kitty-shell-1.e22d9ad.452.png",toString:function(){return s.p+"assets/ideal-img/kitty-shell-1.e22d9ad.452.png"},placeholder:void 0,width:452,height:601},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAANCAYAAACQN/8FAAAACXBIWXMAAAsTAAALEwEAmpwYAAABV0lEQVR4nF2RyY7bMBBE+f8fk0uOcw8yE8ewI2uxR/tia7FkUdJYA0TyC5q+DNIAQXazyOqqVrvdlsulpKkbhkGjtaZrW9q25Xq9Mo4jYRiizuczcRxzn2eCIMC2Hbbb3ziOg+PYJEmCH/io9tqSpRnT9IHneWx+bfB9n67raJqGPM9Nruq6pshztB5MIYwigjAkjhPe/YCqqvBcF3W73Tgdj5RlxfvpiHvYE/tHiiREtw29HswDJRRBEDLoHusU8+015vuu4sXTvDgdPy2fH5v9kzrPcsZhpLiUzCvozwf6c0XPC7v9H95e31BigzQ9zzNVXSPxeDzMvq4raZpgWRZKLkXZOE5Iv1/j77Lwcb8TRRFKFB0OtjFYzP4ay7IwDIPxVzm2bYAiSor/A8dpek7GdV1kCVCEpWlGURQmlxFKO+ZHMVRo+7435so4s+wJlnNZlvhBwD9Z1OGeE2hZIgAAAABJRU5ErkJggg=="}},8322:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/kitty-shell-2.bf7fd46.661.png 661w",images:[{path:s.p+"assets/ideal-img/kitty-shell-2.bf7fd46.661.png",width:661,height:418}],src:s.p+"assets/ideal-img/kitty-shell-2.bf7fd46.661.png",toString:function(){return s.p+"assets/ideal-img/kitty-shell-2.bf7fd46.661.png"},placeholder:void 0,width:661,height:418},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeUlEQVR4nI2NQQoDIRRD/1fn29KKUAqdozheQV2oh/H4KbWUoXQWXTwISUiolIKcM2qtaK190XtHSgljDJBSCkR0yCcLIYAWs0BrDWPMDyIyizHGfZH5DTGDXpoYSul98e9r59w0rLXw/gxz85D7Cas8cJHrLG5hwxOGY0p/6Eo7WAAAAABJRU5ErkJggg=="}},549:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/map-compiled.6dc6828.661.png 661w",images:[{path:s.p+"assets/ideal-img/map-compiled.6dc6828.661.png",width:661,height:434}],src:s.p+"assets/ideal-img/map-compiled.6dc6828.661.png",toString:function(){return s.p+"assets/ideal-img/map-compiled.6dc6828.661.png"},placeholder:void 0,width:661,height:434},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAHCAYAAAAxrNxjAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAxElEQVR4nFWMu0rEQBhGJ5d/LpmY7AiiIEiwWWxFq8VAEnZ9yy1ikyIhVZ7viKMELA6nOd+nrteRcfxiWRbWdY2e53lnmia2bUMliSfLNCI5Sql/pGka3bYtqiju8L6mriucszjndnxZxvByOaO0DljrY2iMQUR2rLUxHIYBZcwt1nmqv0fRGmMNWnQc/oR93
16PyPOCLihAOlGVFYQw6F5IsQbTEsOs61PPxheo+8Hh84vW9IXy8EU4PfB7ONDfN72PX8w2yiGVPfo2aqQAAAABJRU5ErkJggg=="}},8709:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/maps-list.1386617.1005.png 1005w",images:[{path:s.p+"assets/ideal-img/maps-list.1386617.1005.png",width:1005,height:153}],src:s.p+"assets/ideal-img/maps-list.1386617.1005.png",toString:function(){return s.p+"assets/ideal-img/maps-list.1386617.1005.png"},placeholder:void 0,width:1005,height:153},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAACCAYAAABhYU3QAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAS0lEQVR4nGOQV3X6r6Dm8l9cyf+/uLL/f15V//+8KqH/RZUC/4spBvwXUwr4L6wQ/J8BJCCiGPyfTy76P69cDBjzyMX+50XGsrH/AcRRHn2NzN7ZAAAAAElFTkSuQmCC"}},2485:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/neofetch.11e02c2.1280.jpg 1280w",images:[{path:s.p+"assets/ideal-img/neofetch.11e02c2.1280.jpg",width:1280,height:960}],src:s.p+"assets/ideal-img/neofetch.11e02c2.1280.jpg",toString:function(){return s.p+"assets/ideal-img/neofetch.11e02c2.1280.jpg"},placeholder:void 0,width:1280,height:960},preSrc:"data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAUI/8QAHRAAAgICAwEAAAAAAAAAAAAAAQIEEQADBSEiUf/EABQBAQAAAAAAAAAAAAAAAAAAAAH/xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAMAwEAAhEDEQA/AM7S5XFPxsdY8ciUioNl6wAxr13d/MjMVLEhUAvoYxgQGX//2Q=="}},2329:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/tvbox-map-1.e45c600.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/tvbox-map-1.e45c600.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/tvbox-map-1.e45c600.1560.png",toString:function(){return s.p+"assets/ideal-img/tvbox-map-1.e45c600.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAkElEQVR4nFXPwQrCQAwE0Oxmkm1rD7agFfGoIIp48CT+/3eNZFsLHoZcHsNEUkqM5Jxp1tC9ZSkbuncECrOCBqUEEhEC4OX64nQ8s+u2FSqcqkZVzDAlqY2P54e3+5vDeGBpesIKFUbNK5wzDhP3uxP7flgbsbT+wdgUOyOwZoWxU1R/zyzQ2wpVnWbO4nGNXzJdQRgxeDZ1AAAAAElFTkSuQmCC"}},7186:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/tvbox-map-2.40bbd7c.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/tvbox-map-2.40bbd7c.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/tvbox-map-2.40bbd7c.1560.png",toString:function(){return s.p+"assets/ideal-img/tvbox-map-2.40bbd7c.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAsElEQVR4nAXBW1bEIBBAwazAEAjQzSMkBsboeGb0+KH739i1ahq3Jzk1wqp4JwQXsbPFO6W2D+r5TWl3JikXkjvGeCQ2VA6cFZZFaf2Hfv1R9wdT0I6mGxozkgdRT6xLGFeox4N+/bKdX0ySOj5UPscdLW8E31h9wdiEDRv19YnUiylKw7ysmNmT6zulXixWsWvGWSWlQUo3phqU6Df2PBhh57CJNHt0XpHF02Qje+Ef5hxPFQMp/A4AAAAASUVORK5CYII="}},6187:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/tvbox-map-3.c0db540.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/tvbox-map-3.c0db540.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/tvbox-map-3.c0db540.1560.png",toString:function(){return s.p+"assets/ideal-img/tvbox-map-3.c0db540.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAsElEQVR4nB3Ly07DMBBA0awKaWrP+BF7nNhREZFaIdiw5v9/6yJ1fXSmEAyVhDil205vA6sd0ULIA10HMRnT+9VxuczEaFjZKbli9UDUiHkgqeFDY3I+ENeDcf8m5875+CWkHa+Gpg0fGxI3ppwbtT/Yji/qfvL8+XuB08K8KD4YXoxpXgK1fSJaUa30/eTmEhKMm8s4n19pur7NiE/U3PCLkjRzHx+UdePmAhILXhL/lDpKa7irYNEAAAAASUVORK5CYII="}},6244:(e,t,s)=>{e.exports={src:{srcSet:s.p+"assets/ideal-img/tvbox-map-4.1f86681.1560.png 1560w",images:[{path:s.p+"assets/ideal-img/tvbox-map-4.1f86681.1560.png",width:1560,height:877}],src:s.p+"assets/ideal-img/tvbox-map-4.1f86681.1560.png",toString:function(){return s.p+"assets/ideal-img/tvbox-map-4.1f86681.1560.png"},placeholder:void 0,width:1560,height:877},preSrc:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAsElEQVR4nD2NzUrDQBhFv/k3M8mMkxQEYxsUq1YLXbQLBRf6/g91JKO4ONzL5cAVEcWKUhql1i7/eOdJMVPzhDShyYI2hjresFteOLy9c7588bw/UfoJsTZgrcca3/Ju+8Tl/M3p+Mnx8MH98kruxz/ReLzvG
1NZBFH0q7JY98/zAdn4kduVXdI0r+lRJqRBCYsiVUjdspltSvEaCCxjjMFq365xHnAtobbHWErtIGSo/H3dFnvuyTFUAAAAASUVORK5CYII="}},638:(e,t,s)=>{"use strict";s.r(t),s.d(t,{assets:()=>d,contentTitle:()=>l,default:()=>p,frontMatter:()=>o,metadata:()=>i,toc:()=>A});var i=s(5645),a=s(4848),n=s(8453),r=s(547);const o={slug:"compiling-hl1-maps",title:"Compiling Half-Life 1 maps on Android TV-box",image:"./img/map-compiled.png",tags:["gamedev","half-life","xash3d","primext","android","linux","modding","mapping","termux","vhlt","zhlt","p2st","valve","cmake","crossplatform"],description:"I have been modding the legendary Half-Life 1 for these years, and somehow quite spontaneously I thought:  how interesting it would be to try to compile maps on some platform other than the usual x86 and amd64...  Then I remembered that I have an Android TV box at home that, in theory, could be used for this purpose."},l=void 0,d={image:s(3394).A,authorsImageUrls:[]},A=[{value:"What's we have?",id:"whats-we-have",level:2},{value:"Preparing",id:"preparing",level:2},{value:"Building map compilers",id:"building-map-compilers",level:2},{value:"Compiling map",id:"compiling-map",level:2},{value:"Checking the results",id:"checking-the-results",level:2},{value:"Stats of map compiled on TV-box",id:"stats-of-map-compiled-on-tv-box",level:2},{value:"Stats of map compiled on my PC",id:"stats-of-map-compiled-on-my-pc",level:2},{value:"Screenshots of map compiled on my PC",id:"screenshots-of-map-compiled-on-my-pc",level:2},{value:"Screenshots of map compiled on TV-box",id:"screenshots-of-map-compiled-on-tv-box",level:2},{value:"Resume",id:"resume",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,n.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"I have been modding the legendary Half-Life 1 for these years, and somehow quite spontaneously I thought:\nhow interesting it would be to try to compile maps on some platform other than the usual x86 and amd64...\nThen I remembered that I have an Android TV box at home that, in theory, could be used for this purpose.\nSo, why don't try it? This is how all of this were started."}),"\n",(0,a.jsx)(t.h2,{id:"whats-we-have",children:"What's we have?"}),"\n",(0,a.jsx)(t.p,{children:"In stock, I had a GoldMaster I-905 TV set-top box, which is completely unremarkable.\nIt has 16 gigabytes of internal memory, 2 gigabytes of RAM. Based on the Allwinner H313 processor.\nFrom interfaces: has two USB 2.0 ports, composite video output, HDMI port.\nNetwork access can be provided both via Wi-Fi and via an Ethernet port, but I used a wired connection."}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.th,{style:{textAlign:"center"},children:(0,a.jsx)(r.A,{img:s(2485)})})})}),(0,a.jsx)(t.tbody,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.td,{style:{textAlign:"center"},children:(0,a.jsx)(t.em,{children:"Main information about TV-box system, shown by neofetch"})})})})]}),"\n",(0,a.jsx)(t.p,{children:"Also, we need map compiler sources. For almost 30 years of the existence of the game, quite a few of their\nvariations have appeared: the original compilers from Valve, ZHLT, VHLT, P2ST, etc. I will use the map compilers\nfrom my PrimeXT project: they are the most up-to-date at the moment, they will be the easiest to build and run\nunder some exotic platform, unlike all other variations. The game itself, as well as all related utilities,\nincluding map compilers, are written in C/C++. PrimeXT uses the CMake build system."}),"\n",(0,a.jsx)(t.h2,{id:"preparing",children:"Preparing"}),"\n",(0,a.jsxs)(t.p,{children:["After a short search for information, I found out that in order to build C++ projects straight on Android, I need ",(0,a.jsx)(t.a,{href:"https://termux.dev/en/",children:"Termux"}),".\nIt should be downloaded from the ",(0,a.jsx)(t.a,{href:"https://f-droid.org/ru/packages/com.termux/",children:"F-Droid repository"}),", as the version\npublished on Google Play ",(0,a.jsx)(t.a,{href:"https://www.reddit.com/r/termux/comments/pkujfa/important_deprecation_notice_for_google_play/",children:"has been deprecated"})," and is no longer supported."]}),"\n",(0,a.jsx)(t.p,{children:"After installing Termux, just in case, update the installed packages:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"pkg upgrade\n"})}),"\n",(0,a.jsx)(t.p,{children:"Now let's install the packages that we actually need:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"pkg install cmake git openssh pkg-config ninja\n"})}),"\n",(0,a.jsx)(t.p,{children:"For more convenient work, I decided to run an SSH server on the TV-box and connect to it from my computer. For this I used a KiTTY and WinSCP. Of course, you can use any other software instead. And you can do without an SSH server at all - just write all the necessary commands into Termux manually on the device. But I will use WinSCP for convenient work with files on a remote device."}),"\n",(0,a.jsx)(t.p,{children:"Now you need to start the SSH server: the procedure is quite trivial. At first, we need to set a password to connect to the server, and then start the corresponding service."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"passwd\nsshd\n"})}),"\n",(0,a.jsxs)(t.p,{children:["After that, you can try to connect from the computer to the server. Please note that Termux uses port ",(0,a.jsx)(t.strong,{children:"8022"})," for the\nSSH server, not the usual 22. You can enter any username, but you need to enter the password\nspecified earlier. If the connection is successful, a shell will be displayed."]}
1),"\n",(0,a.jsx)(r.A,{img:s(6505),alt:"KiTTY Interface"}),"\n",(0,a.jsx)(r.A,{img:s(8322),alt:"KiTTY Shell after logging in"}),"\n",(0,a.jsx)(t.h2,{id:"building-map-compilers",children:"Building map compilers"}),"\n",(0,a.jsx)(t.p,{children:"After completing all the preparatory procedures, you can go directly to the build procedure. The first step is cloning the sources into your home directory:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"cd ~\ngit clone --recursive https://github.com/SNMetamorph/PrimeXT.git\ncd PrimeXT\n"})}),"\n",(0,a.jsx)(t.p,{children:"Next, you need to bootstrap vcpkg package manager. You can be warned about missing packages - in this case you need to install them."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"export VCPKG_FORCE_SYSTEM_BINARIES=1\nexternal/vcpkg/bootstrap-vcpkg.sh\n"})}),"\n",(0,a.jsx)(t.p,{children:"Then, you need to create and prepare the directory in which the assembly will take place."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"cmake -E make_directory ./build\ncd build\n"})}),"\n",(0,a.jsx)(t.p,{children:"And now it's time to generate the CMake cache and run the build. Since I'm only interested in map compilers,\nI disabled building game libraries, launcher, and other unrelated utilities. Also, to make the compilation of the project faster, I will set the build to 4 threads."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"cmake .. --preset utils-termux-debug\ncmake --build . --parallel 4\n"})}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.th,{style:{textAlign:"center"},children:(0,a.jsx)(r.A,{img:s(2495)})})})}),(0,a.jsx)(t.tbody,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.td,{style:{textAlign:"center"},children:(0,a.jsx)(t.em,{children:"CMake cache was successfully generated"})})})})]}),"\n",(0,a.jsx)(t.p,{children:"After executing the two commands described above, the build process will start."}),"\n",(0,a.jsx)(r.A,{img:s(7577)}),"\n",(0,a.jsx)(t.p,{children:"If the build succeeds, it will look like this. If any errors occur, it is better to restart the build process\nin one thread, so it will be easier to find out where exactly the compilation error occurred. By the way,\non this TV-box, project building with 4 threads tooks about four minutes, taking into account the\nfact that an IPTV player was running in the background and occupying some of CPU resources."}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.th,{style:{textAlign:"center"},children:(0,a.jsx)(r.A,{img:s(5724)})})})}),(0,a.jsx)(t.tbody,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.td,{style:{textAlign:"center"},children:(0,a.jsx)(t.em,{children:"Map compilers build successfully finished"})})})})]}),"\n",(0,a.jsx)(t.h2,{id:"compiling-map",children:"Compiling map"}),"\n",(0,a.jsxs)(t.p,{children:["For the final step, you need to prepare a working directory that will contain WAD files with textures, a ",(0,a.jsx)(t.code,{children:".rad"})," file, and a map source. In my case, this directory will be called ",(0,a.jsx)(t.code,{children:"gameres"}),"."]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"mkdir ~/gameres\ncd ~/gameres\n"})}),"\n",(0,a.jsxs)(t.p,{children:["Then, inside this directory, you need to create a ",(0,a.jsx)(t.code,{children:"gameinfo.txt"})," file with the following content:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:'basedir ""\ngamedir "gameres"\n'})}),"\n",(0,a.jsxs)(t.p,{children:["Important tip: in this file, the value of the ",(0,a.jsx)(t.code,{children:"gamedir"})," parameter must match the name of the working directory. Next, you need to put the used WAD files in the working directory, create a subdirectory called ",(0,a.jsx)(t.code,{children:"maps"})," inside it, and put the ",(0,a.jsx)(t.code,{children:".rad"})," file and the map source in the form of a ",(0,a.jsx)(t.code,{children:".map"})," file into this subdirectory."]}),"\n",(0,a.jsxs)(t.p,{children:["All the necessary files that I used are available at ",(0,a.jsx)(t.a,{target:"_blank","data-noBrokenLinkCheck":!0,href:s(9608).A
1+"",children:"this link"}),"."]}),"\n",(0,a.jsx)(t.p,{children:"Now you can try to compile the map, and all that remains is just wait."}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-bash",children:"cd ~/PrimeXT/build/Release/primext/devkit\n./pxcsg ~/gameres/maps/crossfire_double1_v2.map\n./pxbsp ~/gameres/maps/crossfire_double1_v2.bsp\n./pxvis ~/gameres/maps/crossfire_double1_v2.bsp\n./pxrad ~/gameres/maps/crossfire_double1_v2.bsp\n"})}),"\n",(0,a.jsxs)(t.p,{children:["The map compilation process consists of four steps. At the end of each stage, the time spent on it will be displayed.\nIf there are any problems during the compilation of the map, you can look at the log file in the ",(0,a.jsx)(t.code,{children:"maps"})," subdirectory.\nAlso, you can add the ",(0,a.jsx)(t.code,{children:"-dev 5"})," startup option to compilers to display the process in more details."]}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.th,{style:{textAlign:"center"},children:(0,a.jsx)(r.A,{img:s(549)})})})}),(0,a.jsx)(t.tbody,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.td,{style:{textAlign:"center"},children:(0,a.jsx)(t.em,{children:"Last map compiling stage was finished"})})})})]}),"\n",(0,a.jsx)(t.h2,{id:"checking-the-results",children:"Checking the results"}),"\n",(0,a.jsx)(t.p,{children:"After the map successfully compiled on the TV-box, I decided to rebuild the same map on my computer\nand then compare these two maps. Ideally, there shouldn't be any visible differences. I will test this whole thing\nin the PrimeXT mod, which is based on the Xash3D FWGS engine."}),"\n",(0,a.jsxs)(t.table,{children:[(0,a.jsx)(t.thead,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.th,{style:{textAlign:"center"},children:(0,a.jsx)(r.A,{img:s(8709)})})})}),(0,a.jsx)(t.tbody,{children:(0,a.jsx)(t.tr,{children:(0,a.jsx)(t.td,{style:{textAlign:"center"},children:(0,a.jsx)(t.em,{children:"Maps built on different architectures and platforms"})})})})]}),"\n",(0,a.jsxs)(t.p,{children:["The engine has a ",(0,a.jsx)(t.code,{children:"mapstats"})," console command that allows you to display various internal information about the map. For our situation, this is exactly what we need."]}),"\n",(0,a.jsx)(t.h2,{id:"stats-of-map-compiled-on-tv-box",children:"Stats of map compiled on TV-box"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"Object names  Objects/Maxobjs  Memory / Maxmem  Fullness\n------------  ---------------  ---------------  --------\nentities         [variable]       64780/1048576   ( 6.2%) \nplanes           2179/65536       43580/1310720   ( 3.3%) \ntextures         [variable]        4976/33554432  ( 0.0%) \nvertexes        11219/65535      134628/786420    (17.1%) \nvisibility       [variable]      199238/16777216  ( 1.2%) \nnodes            5031/32767      120744/786408    (15.4%) \ntexinfo          1383/65535       55320/2621400   ( 2.1%) \nfaces            8467/65535      169340/1310700   (12.9%) \nlightmaps        [variable]     1745778/33554432  ( 5.2%) \nclipnodes       12686/32767      101488/262136    (38.7%) \nleafs            3260/32767       91280/917476    ( 9.9%) \nmarkfaces       11552/65535       23104/131070    (17.6%) \nedges           20150/1048576     80600/4194304   ( 1.9%) \nsurfedges       40037/2097152    160148/8388608   ( 1.9%) \nmodels            142/1024         9088/65536     (13.9%) \ndeluxmaps        [variable]     1745778/33554432  ( 5.2%) \n=== Total BSP file data space used: 4.53 Mb ===\nWorld size ( 5120 5824 3920 ) units\nSupports transparency world water: No\nLighting: colored\nWorld total leafs: 2318\noriginal name: maps/crossfire_double1_v2_arm.bsp\ninternal name: desert\nmap compiler: PrimeXT Tools v.0.90 (Dec 15 2022 / 1397a04 / armv7l / android)\nmap editor: J.A.C.K. 1.1.2800 (vpHalfLife)\n"})}),"\n",(0,a.jsx)(t.h2,{id:"stats-of-map-compiled-on-my-pc",children:"Stats of map compiled on my PC"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{children:"Object names  Objects/Maxobjs  Memory / Maxmem  Fullness\n------------  ---------------  ---------------  --------\nentities         [variable]       64777/1048576   ( 6.2%) \nplanes           2179/65536       43580/1310720   ( 3.3%) \ntextures         [variable]        4976/33554432  ( 0.0%) \nvertexes        11210/65535      134520/786420    (17.1%) \nvisibility       [variable]      198643/16777216  ( 1.2%) \nnodes            5031/32767      120744/786408    (15.4%) \ntexinfo          1383/65535       55320/2621400   ( 2.1%) \nfaces            8465/65535      169300/1310700   (12.9%) \nlightmaps        [variable]     1744599/33554432  ( 5.2%) \nclipnodes       12747/32767      101976/262136    (38.9%) \nleafs            3258/32767       91224/917476    ( 9.9%) \nmarkfaces       11512/65535       23024/131070    (17.6%) \nedges           20138/1048576     80552/4194304   ( 1.9%) \nsurfedges       40013/2097152    160052/8388608   ( 1.9%) \nmodels            142/1024         9088/65536     (13.9%) \ndeluxmaps        [variable]     1744599/33554432  ( 5.2%) \n=== Total BSP file data space used: 4.53 Mb ===\nWorld size ( 5120 5824 3920 ) units\nSupports transparency world water: No\nLighting: colored\nWorld total leafs: 2316\noriginal name: maps/crossfire_double1_v2.bsp\ninternal name: desert\nmap compiler: PrimeXT Tools v.0.90 (Dec 16 2022 / 1397a04 / amd64 / win32)\nmap editor: J.A.C.K. 1.1.2800 (vpHalfLife)\n"})}),"\n",(0,a.jsx)(t.p,{children:"As you can see, there are still minimal differences in stats. It is difficult to say what exactly is the reason for\nthese differences, but most likely they are completely uncritical.\nNext, it makes sense to compare if there are any visual differences on the map itself."}),"\n",(0,a.jsx)(t.h2,{id:"screenshots-of-map-compiled-on-my-pc",children:"Screenshots of map compiled on my PC"}),"\n",(0,a.jsx)(r.A,{img:s(6024)}),"\n",(0,a.jsx)(r.A,{img:s(515)}),"\n",(0,a.jsx)(r.A,{img:s(9754)}),"\n",(0,a.jsx)(r.A,{img:s(4421)}),"\n",(0,a.jsx)(t.h2,{id:"screenshots-of-map-compiled-on-tv-box",children:"Screenshots of map compiled on TV-box"}),"\n",(0,a.jsx)(r.A,{img:s(2329)}),"\n",(0,a.jsx)(r.A,{img:s(7186)}),"\n",(0,a.jsx)(r.A,{img:s(6187)}),"\n",(0,a.jsx)(r.A,{img:s(6244)}),"\n",(0,a.jsx)(t.p,{children:"Personally, I didn\u2019t notice any visual differences in lighting or geometry at all, which of course is good.\nThe experiment can be considered successful."}),"\n",(0,a.jsx)(t.h2,{id:"resume",children:"Resume"}),"\n",(0,a.jsx)(t.p,{children:"Using the procedures described above, it is quite possible to compile maps for Half-Life 1 on almost any device that\nis based on the Android or Linux OS. Unless, on too large and detailed maps, the device may not have enough RAM\nfor compiling."}),"\n",(0,a.jsx)(t.p,{children:"Despite the fact that all this was not initially intended as something useful, it is possible to find some use cases: for example, if for some reason you don\u2019t want to load the PC, or there are no devices other than a smartphone at all (unfortunately it's pretty common nowadays, PCs stand back in favour of smartphones), but you need to compile the map somehow."})]})}function p(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(h,{...e})}):h(e)}},9608:(e,t,s)=>{"use strict";s.d(t,{A:()=>i});const i=s.p+"assets/files/crossfire_mirror_sources-fcca301f00664a4bf0922c049fe99459.7z"},3394:(e,t,s)=>{"use strict";s.d(t,{A:()=>i});
1const i=s.p+"assets/images/map-compiled-73aabb94f8a2e5245520324328f06d70.png"},5645:e=>{"use strict";e.exports=JSON.parse('{"permalink":"/posts/compiling-hl1-maps","source":"@site/blog/2023-01-20-compiling-hl1-maps/index.mdx","title":"Compiling Half-Life 1 maps on Android TV-box","description":"I have been modding the legendary Half-Life 1 for these years, and somehow quite spontaneously I thought:  how interesting it would be to try to compile maps on some platform other than the usual x86 and amd64...  Then I remembered that I have an Android TV box at home that, in theory, could be used for this purpose.","date":"2023-01-20T00:00:00.000Z","tags":[{"inline":true,"label":"gamedev","permalink":"/posts/tags/gamedev"},{"inline":true,"label":"half-life","permalink":"/posts/tags/half-life"},{"inline":true,"label":"xash3d","permalink":"/posts/tags/xash-3-d"},{"inline":true,"label":"primext","permalink":"/posts/tags/primext"},{"inline":true,"label":"android","permalink":"/posts/tags/android"},{"inline":true,"label":"linux","permalink":"/posts/tags/linux"},{"inline":true,"label":"modding","permalink":"/posts/tags/modding"},{"inline":true,"label":"mapping","permalink":"/posts/tags/mapping"},{"inline":true,"label":"termux","permalink":"/posts/tags/termux"},{"inline":true,"label":"vhlt","permalink":"/posts/tags/vhlt"},{"inline":true,"label":"zhlt","permalink":"/posts/tags/zhlt"},{"inline":true,"label":"p2st","permalink":"/posts/tags/p-2-st"},{"inline":true,"label":"valve","permalink":"/posts/tags/valve"},{"inline":true,"label":"cmake","permalink":"/posts/tags/cmake"},{"inline":true,"label":"crossplatform","permalink":"/posts/tags/crossplatform"}],"readingTime":8.54,"hasTruncateMarker":false,"authors":[],"frontMatter":{"slug":"compiling-hl1-maps","title":"Compiling Half-Life 1 maps on Android TV-box","image":"./img/map-compiled.png","tags":["gamedev","half-life","xash3d","primext","android","linux","modding","mapping","termux","vhlt","zhlt","p2st","valve","cmake","crossplatform"],"description":"I have been modding the legendary Half-Life 1 for these years, and somehow quite spontaneously I thought:  how interesting it would be to try to compile maps on some platform other than the usual x86 and amd64...  Then I remembered that I have an Android TV box at home that, in theory, could be used for this purpose."},"unlisted":false,"prevItem":{"title":"Breaking down Toshiba 00DN901 customer display","permalink":"/posts/vfd-toshiba-00dn901"},"nextItem":{"title":"Windows typical exception codes cheatsheet","permalink":"/posts/exceptions-win32"}}')}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.