最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

Ballance自制圖的不斷柱子問題

2023-08-30 12:22 作者:bkt_yyc12345  | 我要投稿

Ballance自制圖中斷裂的柱子自2011年以來(或更早。由于貼吧無了,已經(jīng)找不到最早記錄了)就已被吧友發(fā)現(xiàn)并一直困惑吧友十?dāng)?shù)年。如今,這一問題終于有了科學(xué)合理的解釋。算是為在不同時(shí)期關(guān)注過,并嘗試過解決的各位吧友有了一個(gè)交代。

歷史

由于各路制圖人對于柱子斷裂問題的持續(xù)不斷地努力,多數(shù)吧友自入吧時(shí)期就從未意識到自制地圖有這樣一段柱子不能透明的時(shí)光,再加上當(dāng)初知曉這一缺陷的吧友大多已離開貼吧,請?jiān)试S我在這里對柱子問題做一個(gè)簡短的回顧。

自制地圖的柱子問題,又或者:柱子不斷,柱子不透明,所談及的都是同一個(gè)問題,即圖中的所有柱子,比如常見的燈柱,或者終點(diǎn)處的鋼柱,其下端本應(yīng)平滑漸變至透明,而實(shí)際上透明度卻戛然而止,呈現(xiàn)柱子唐突消失的現(xiàn)象。這種現(xiàn)象經(jīng)過吧友不斷摸索之后總結(jié)出了規(guī)律:無論是自制地圖還是原版地圖,只要是經(jīng)過Virtools重新保存的文件均會(huì)發(fā)生此種情況。而沒有經(jīng)過重新保存的原版地圖則不會(huì)。

自制地圖的柱子問題,常與另外幾個(gè)制圖問題,比如路燈發(fā)光問題,以及路面陰影問題,可被視為當(dāng)時(shí)Ballance制圖界最難以對付的幾個(gè)問題。其中尤其以柱子問題最為嚴(yán)重,甚至到了吧里當(dāng)時(shí)為了判斷競速使用的地圖是否被修改,以柱子是否斷裂為標(biāo)準(zhǔn)。以上的這些制圖問題中,路燈發(fā)光問題是由Ballance腳本硬編碼造成的;路面陰影問題也已在2020年7月后有了科學(xué)的解釋和解決方案。唯獨(dú)剩下自制地圖柱子問題這一片烏云。

2013年2月,勇往直前3地圖發(fā)布,此地圖實(shí)現(xiàn)了一種看起來似乎是不斷的柱子,并且作為后續(xù)一系列地圖的不斷柱子的范例。然而仔細(xì)分析后可以發(fā)現(xiàn),其實(shí)際上是將透明度斷裂的柱子貼圖的透明度突變附近的部分拉伸至整個(gè)模型,利用渲染過程中的插值過程產(chǎn)生漸變效果。但是這樣會(huì)導(dǎo)致貼圖的水平紋理丟失,并且整個(gè)柱子漸變部分被無限地平滑,看不出任何紋理,所以也不是完美的解決方案。

2018年10月,chirs241097就地圖燈影及柱子問題發(fā)表了一篇帖子,詳細(xì)地闡明了路燈發(fā)光問題的原因。而對于柱子問題卻仍未得出結(jié)論。只能找到替代方案,即修改CK2_3D.ini的TextureVideoFormat字段,讓Ballance默認(rèn)使用32位ARGB8888格式去讀取貼圖。但在結(jié)尾chirs241097仍然給出了可能的原因,并且與5年后的結(jié)論不謀而合,即文檔格式略有區(qū)別,導(dǎo)致Desired Video Format選項(xiàng)無法被讀取,游戲回退到了默認(rèn)格式,即會(huì)導(dǎo)致柱子斷裂的16位ARGB1555格式。

2019年1月,chirs241097發(fā)布了有關(guān)地圖內(nèi)嵌腳本的相關(guān)技術(shù)。此技術(shù)可以實(shí)現(xiàn)運(yùn)行游戲之外的腳本的功能,而無需加載或修改任何其他文件。此項(xiàng)技術(shù)很快被應(yīng)用于修正地圖斷裂的柱子這一問題中。通過在內(nèi)嵌腳本中,為那些透明度錯(cuò)誤的貼圖,強(qiáng)制指定他們的Video Format,可以使得柱子不再斷裂,可以正常漸變到透明。也就是優(yōu)化了2018年的妥協(xié)方案,使得不再需要去修改游戲文件來達(dá)成柱子不斷的效果。

時(shí)至今日,多數(shù)自制地圖的柱子都已通過內(nèi)嵌腳本技術(shù)不再斷裂。很多新入坑的玩家都不再在意柱子的事情。但柱子斷裂的問題并不是不存在了,他只是被各種技術(shù)壓制了,不再表現(xiàn)出來罷了,壓制并不等于不存在,它還在那,還是一朵飄在制圖人頭頂?shù)臑踉啤?/p>

本文的目的,就是徹底擊碎這最后一塊壓在制圖人心頭的巨石。還柱子問題一個(gè)科學(xué),清晰的解釋。并給出一些現(xiàn)階段可行的解決方案。本文的最終目的是取代地圖內(nèi)嵌腳本實(shí)現(xiàn)的柱子不斷,轉(zhuǎn)而通過原生方式實(shí)現(xiàn)。這樣以來,許多地圖就不再需要內(nèi)嵌腳本來強(qiáng)制保證柱子不斷了,也降低了新手制圖人入門的門檻,畢竟不是所有人都會(huì)制作內(nèi)嵌腳本。

科學(xué)解釋

在Virtools升級換代過程中,一個(gè)CKStateChunk(Virtools底層存儲(chǔ)格式)中的Identifier(標(biāo)識符)被修改了,從0x002ff000(Ballance可以讀取此Identifier)被修改為0x00fff000(Ballance不可讀取此Identifier)。這導(dǎo)致其隨后的數(shù)據(jù)塊不可被讀取。此數(shù)據(jù)塊存有CKTexture(貼圖)的Video Format數(shù)據(jù)。丟失了Video Format數(shù)據(jù)的CKTexture被迫回退為CK2_3D.ini中指定的默認(rèn)格式,而默認(rèn)格式又不能正確地處理透明度,最終導(dǎo)致了柱子的斷裂。

研究與驗(yàn)證

本次研究主要是基于doyaGu所作的有關(guān)CK2及CK2_3D的IDA反編譯文檔展開的。沒有doyaGu的這些文檔,一些工作開展起來就會(huì)非常困難,亦或者無法開展。在此鄭重地感謝doyaGu及其所作的工作。

那么在驗(yàn)證前,首先還需要介紹一下我所用的工具LibCmo和Unvirt。由于Virtools SDK屏蔽了很多技術(shù)細(xì)節(jié)以及Virtools底層代碼,導(dǎo)致我不能隨心所欲地去自由地分析Virtools文件。于是我開發(fā)了LibCmo,一個(gè)著重復(fù)現(xiàn)Virtools 2.1版本文件讀寫功能的靜態(tài)庫。LibCmo基于doyaGu的反編譯結(jié)果,基本完整地重新實(shí)現(xiàn)了Virtools文件,以及作為Virtools內(nèi)部底層數(shù)據(jù)存儲(chǔ)單元CKStateChunk的讀寫操作。而Unvirt則是一款借助LibCmo提供的函數(shù),可以交互式的處理用戶需求的命令行程序,例如加載和保存Virtools文件,顯示CKStateChunk的核心數(shù)據(jù)等。Unvirt的名稱來源于Luigi Auriemma開發(fā)的同名軟件,其可以粗略地解析Virtools文件,但其深度不夠,不足以解析到我需要的階段。LibCmo和Unvirt目前仍處于開發(fā)階段,但對于現(xiàn)階段的研究需求來說足矣。

在前人研究的基礎(chǔ)上,我們不難總結(jié)出是由于Virtools版本更迭造成的柱子斷裂,而且很有可能是因?yàn)橄Я四承┍仨毜臇|西造成的。那么既然我們有了這一猜想,接下來就是找所謂的“某些東西”是什么,以及驗(yàn)證它確實(shí)有影響。先前各路人馬的研究已經(jīng)幾乎排除了大部分的可能,只剩下CKStateChunk這一Virtools嚴(yán)密保護(hù),不對外公開具體內(nèi)部結(jié)構(gòu)的黑盒未被探索。因此在研究開始,我就將柱子斷裂的研究方向集中于CKStateChunk。

首先我們需要一個(gè)參照,我這里使用的是原版關(guān)卡第二關(guān),其名為Level_02.NMO。將其加載入游戲,傳送至關(guān)卡結(jié)束部分,我們可以看到關(guān)卡結(jié)束部分的鐵柱子和普通燈柱均有平滑的透明漸變。這是我們之后進(jìn)行對比的地方。

接下來就是利用Virtools Dev 3.5讀取原版第二關(guān),然后保存它。這里我采用的是右鍵Level - Save as這一傳統(tǒng)保存方式。保存后的文件命名為Level_02.new.NMO。此時(shí)將其加載進(jìn)游戲,可以發(fā)現(xiàn)關(guān)卡末尾部分,無論是鐵柱子,還是普通燈柱,均沒有透明度了。這是符合柱子斷裂的描述的。

接下來我使用了Unvirt加載了Level_02.new.NMO,即被Virtools 3.5保存的第二關(guān)。具體操作是先使用encoding 1252設(shè)置文檔編碼,然后使用load shallow Level_02.new.NMO指令加載文件。接下來通過使用ls obj 頁碼的方式瀏覽該文件內(nèi)存儲(chǔ)的物體數(shù)據(jù),找到名為Column_beige_fade,類型為CK_TEXTURE的物體。這個(gè)物體是普通燈柱下半透明部分的貼圖。這里我找到的編號是320。然后使用chunk obj 320顯示它的底層存儲(chǔ)結(jié)構(gòu)CKStateChunk中的數(shù)據(jù),如下圖所示。該指令為我們列出此物體具有3個(gè)Identifiers。

為了有對比性,我使用unload指令卸載當(dāng)前加載的文件。然后再加載原生的第二關(guān)Level_02.NMO。加載方式如上文所述。然后按照同樣的方式找到同一個(gè)物體。我這里找到的編號是319。用chunk obj 319顯示其底層數(shù)據(jù),如下圖所示??梢园l(fā)現(xiàn)其也具有3個(gè)Identifiers,且與上文的輸出極其相似。

上文輸出的兩個(gè)數(shù)據(jù)極其相似,只有一點(diǎn)不同,即其中一個(gè)Identifier從0x002ff000變?yōu)榱?x00fff000。那么到這里我們只能說這個(gè)Identifier有很大嫌疑會(huì)造成這個(gè)bug,但并不能絕對肯定,接下來我們需要繼續(xù)找證據(jù)佐證它。

首先我查閱了Virtools文檔中有關(guān)此Identifier的定義。此Identifier被定義在CKdefines2.h中。在Virtools 2.5 SDK的這個(gè)文件中,如下圖所示,可以觀察到對于0x002ff000的注解是“Kept for compatibility”,而對于0x00fff000的注解是“Save Only Texture Data”,顯而易見,0x00fff000取代了0x002ff000。這可能會(huì)導(dǎo)致兼容問題,我對于它會(huì)造成此bug更加堅(jiān)信了。

接下來我打開了doyaGu分析完畢的反編譯IDA文檔。CKTexture的相關(guān)定義都在CK2_3D里面,只需直接進(jìn)去查找CKTexturex::Load()這一虛函數(shù)的定義。在打開定義后,可以很輕松地找到Identifier常量0x002ff000,如下圖所示。在其相關(guān)數(shù)據(jù)解析部分中,可以找到對Video Format相關(guān)的設(shè)置,具體的情況是在Identifier后隨的數(shù)據(jù)區(qū)塊中的第三個(gè)DWORD位存放了VX_PIXELFORMAT,該數(shù)值指示了該以何種Video Format加載此CKTexture。

回到我們打開了Level_02.NMO的Unvirt中,Unvirt不僅為我們列出了Identifier,還提供了其對應(yīng)數(shù)據(jù)區(qū)的內(nèi)存指針和大小,在這里我們可以找到0x002ff000對應(yīng)數(shù)據(jù)區(qū)的指針是0x00cf6830,大小是3 DWORD?,F(xiàn)在我們需要一款內(nèi)存編輯器,因?yàn)閁nvirt暫時(shí)還沒有直接修改內(nèi)存的功能。我這里用的是Cheat Engine,你也可以用你自己習(xí)慣的軟件。首先用CE打開Unvirt,然后轉(zhuǎn)到內(nèi)存視圖,復(fù)制Unvirt提供的內(nèi)存地址,在內(nèi)存視圖中跳轉(zhuǎn)到該地址,如下圖所示。然后向后閱讀到第三個(gè)DWORD,其數(shù)值為2。通過查閱有關(guān)VX_PIXELFORMAT的定義,如下圖所示,可快速得知此值代表的正是32位ARGB8888格式。

卸載當(dāng)前加載文件,并用Unvirt加載回Level_02.new.NMO,再次用CE查看Identifier 0x00fff000對應(yīng)的數(shù)據(jù)區(qū)內(nèi)容,如下圖所示。注意到這兩個(gè)Identifier所引導(dǎo)的數(shù)據(jù)區(qū)塊內(nèi)容完全一致。那么至此可以基本確定就是這個(gè)Identifier導(dǎo)致了柱子斷裂的bug。接下來就是要驗(yàn)證我們的猜想。方法也很簡單,就是針對Level_02.new.NMO,將其0x00fff000改回為0x002ff000。觀察是否解決柱子斷裂問題即可驗(yàn)證。

仍然是借助CE的修改內(nèi)存功能,首先復(fù)制Unvirt提供的0x00fff000對應(yīng)數(shù)據(jù)的地址,然后在CE中向前找2個(gè)DWORD,即可找到我們的Identifier本身0x00fff000,如下圖所示。用CE將其修改為0x002ff000。然后再用Unvirt打印當(dāng)前CKTexture的Identifiers??梢园l(fā)現(xiàn)其Identifier已改變,如下圖所示。

接下來使用save Level_02.mod.NMO將修改后的所有物體數(shù)據(jù)保存到一個(gè)新的Virtools文件,Level_02.mod.NMO。然后進(jìn)入游戲?qū)⑵浼虞d,導(dǎo)航到關(guān)卡末尾,可以觀察到我們的普通燈柱部分已經(jīng)具有漸變的透明,然鐵柱子部分則仍然斷裂,如下圖所示。這是因?yàn)槲覀冎惶幚砹似胀ㄖ拥臄?shù)據(jù),并沒有處理鐵柱子的,二者用的不是同一個(gè)貼CKTexture。這也變相地進(jìn)行了修改數(shù)據(jù)與沒修改數(shù)據(jù)的同臺對比,證明了我們猜想的正確性。至此柱子斷裂問題宣告解決。

解決方案

理論上而言,可以通過編寫一些代碼,來實(shí)現(xiàn)批量地修正貼圖問題。然目前我需要一些時(shí)間修整,寫這些代碼耗費(fèi)了我大量精力,我無暇再去顧及這些了。故此處介紹2個(gè)目前暫時(shí)可行的解決方案。

基礎(chǔ)解決方案

首先你需要在你的Virtools Dev的偏好設(shè)置中,將你輸出的文件格式設(shè)置為不壓縮。因?yàn)榻?jīng)過Virtools壓縮后的數(shù)據(jù)完全不可讀,你將無從操作。

然后保存你的地圖文件。接著使用任意十六進(jìn)制編輯器,例如HxD等打開它,全局搜索0x00fff000,并將它們替換為0x002ff000。然后保存。

這種方案的優(yōu)點(diǎn)顯而易見,那就是非常容易操作。但缺點(diǎn)也是非常明顯的,你非常有可能將一些重要數(shù)據(jù)誤替換。因?yàn)椴⒉皇侵挥蠭dentifier處會(huì)出現(xiàn)0x00fff000,可能文件的別處也會(huì)恰巧出現(xiàn)0x00fff000的匹配項(xiàng)且恰好是某個(gè)關(guān)鍵數(shù)據(jù)。倘若誤替換會(huì)導(dǎo)致最后文件無法打開。

進(jìn)階解決方案

進(jìn)階解決方案需要使用Unvirt及配套的內(nèi)存編輯器(此處以CE為例),按照類似上文研究與驗(yàn)證章節(jié)相似的手段進(jìn)行操作。

具體方法則是,先使用encoding 1252設(shè)定文檔編碼格式,1252是Windows用于西歐字符的代碼頁,設(shè)置此項(xiàng)后,將解決讀取文檔時(shí)可能會(huì)拋出的編碼錯(cuò)誤提示。
然后使用load shallow file.NMO加載文件。其中file.NMO是你的地圖文件。而shallow代表著淺加載,即只加載到CKStateChunk階段。與之相對的是deep,即深加載,會(huì)加載到CKObject階段。目前由于LibCmo完全沒有實(shí)現(xiàn)各個(gè)CKObject的加載機(jī)制,所以深加載和淺加載效果基本一致。但按目的而言,這種修改只需要淺加載即可。
接著你可以使用ls obj 頁面的命令來瀏覽當(dāng)前文件包含的項(xiàng)目。此外如果覺得默認(rèn)一頁顯示的項(xiàng)目數(shù)過少,可以通過items 個(gè)數(shù)指令改變一頁顯示的項(xiàng)目個(gè)數(shù)。
當(dāng)找到目標(biāo)CKTexture后,記下其序號,序號在列表指令中以#前綴進(jìn)行輸出。以210舉例,此時(shí)執(zhí)行chunk obj 210顯示其底層數(shù)據(jù),找到0x00fff000對應(yīng)的數(shù)據(jù)地址,在CE內(nèi)存視圖中打開,向前找2個(gè)DWORD,找到Identifier本身,然后修改其為0x002ff000。然后再次運(yùn)行一遍chunk obj 210,確認(rèn)修改成功。如法炮制對所有需要修改的CKTexture進(jìn)行此操作。
操作完畢后,執(zhí)行save new.NMO將當(dāng)前加載的文件保存為一個(gè)新文件new.NMO。至此修改已完成,可以執(zhí)行unloadexit指令退出Unvirt。

這樣的修改操作固然麻煩,但不會(huì)出錯(cuò),且可以處理壓縮的Virtools文件,不需要去調(diào)整Virtools Dev的壓縮設(shè)置。

有關(guān)Unvirt可進(jìn)行的更多操作,可以使用help指令查看。還請注意,Unvirt目前仍在開發(fā)階段,可能會(huì)存在崩潰或缺失功能的情況。

結(jié)語

本次的研究是建立在Ballance的逆向工作極度豐富的情況下的。手握如此巨量的逆向工作成果,讓人很難不想試一試搞出一些成果。自2jjy與chirs241097聯(lián)合反混淆了Ballance的各個(gè)核心腳本文件后,針對Ballance的各類逆向工作層出不窮。Gamepiaynmo逆向了一個(gè)可用的Virtools 2.1庫并在此基礎(chǔ)上寫出了BallanceModLoader,結(jié)束了Ballance沒有SDK的一大痛苦歷史。在這之后doyaGu完成了對Player.exe本體,以及各類Virtools核心文件的逆向,包括CK2,CK2_3D等,并在此基礎(chǔ)上創(chuàng)作出了新的Virtools 2.1 SDK,新Player,新BallanceModLoader,CKRasteriazer等一系列新事物。Ballance的開發(fā)從未像現(xiàn)在這樣如此簡單過。幾年前我們還在為修改Ballance而犯難,現(xiàn)在則可以對Ballance做我們想做的任何修改了。

我堅(jiān)信,所有有關(guān)Ballance的難題,最終都會(huì)有一個(gè)科學(xué)的解釋,只是過程中我們需要付出很多。試想在十年前,沒有這些便利的工具的情況下,想搞明白柱子斷裂的原理,是要花費(fèi)很多很多時(shí)間的。正是有一波波熱愛Ballance制圖與技術(shù)的吧友,不斷奉獻(xiàn),才能有我們今天有關(guān)原理的揭示。

為科學(xué)技術(shù)獻(xiàn)上崇高的敬意與贊美。


Ballance自制圖的不斷柱子問題的評論 (共 條)

分享到微博請遵守國家法律
绥芬河市| 吴堡县| 富源县| 永清县| 虞城县| 民乐县| 吉安市| 洛川县| 乐亭县| 怀集县| 玛纳斯县| 博白县| 林州市| 晋宁县| 新津县| 荃湾区| 望都县| 韶关市| 新龙县| 夹江县| 西充县| 鄯善县| 定边县| 仙游县| 淄博市| 新丰县| 界首市| 永康市| 望奎县| 沾益县| 瓦房店市| 南宁市| 林口县| 抚宁县| 上饶市| 定州市| 陈巴尔虎旗| 青铜峡市| 黄浦区| 滨州市| 沙湾县|