`
RednaxelaFX
  • 浏览: 3052594 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

[脚本分析] 从Quartett!的脚本得到资源列表

阅读更多
听汉公的说明,看来LittleWitch所使用的FFD System在ver4之后解起来就有点麻烦。游戏里的资源归档文件里虽然还是有文件列表,但并没有保存原始的文件名而只是保存了文件名的MD5。这使得解出文件有困难,如果事先不知道想要解的文件的名字,即使把内容能解出来,其文件名也让人不知所云。

但总有办法的。在System.dat里有些定义界面元素用的*.def文件。例如这样:
Music.def
引用
# サウンド定義ファイル
# "条件式", "サウンドファイル名", "サムネイルファイル名", "見出し"

"1" ,"m/BGM_01.ogg" , "SAM/music_thumb.bmp", "Regret"
"1" ,"m/BGM_02.ogg" , "SAM/music_thumb.bmp", "夕影"
"1" ,"m/BGM_03.ogg" , "SAM/music_thumb.bmp", "Reminiscene"
"1" ,"m/BGM_04.ogg" , "SAM/music_thumb.bmp", "Introduction"instrument
"1" ,"m/BGM_05.ogg" , "SAM/music_thumb.bmp", "陽春"
"1" ,"m/BGM_06.ogg" , "SAM/music_thumb.bmp", "沙友"
"1" ,"m/BGM_07.ogg" , "SAM/music_thumb.bmp", "透花 op02"
"1" ,"m/BGM_08.ogg" , "SAM/music_thumb.bmp", "透花"
"1" ,"m/BGM_09.ogg" , "SAM/music_thumb.bmp", "エマ op02"


这些列表能提供足够信息解出相当多的资源,例如说背景音乐、CG等。但有些重要的资源文件名却不在*.def里,像是我们关心的脚本文件。

前一篇里介绍了如何将Quartett!的二进制脚本转变回到一般可读的形式,这里就稍微说明一下我是如何从解出来的脚本中得到一份脚本里引用过的文件列表。

从前一篇的分析可以知道,token类型为0x83的是字符串token。在FFD脚本里,好几种内容都可能会是字符串类型:1、剧情文本;2、一般参数,如图像渐变的模式"Fade",图像的形状"Rect"之类;3、资源文件路径;等等。不进行文法分析的话,没有办法准确判断这些字符串中到底哪些代表资源文件的路径。但有些偷懒的方式可以试试。

我浏览了一下Quartett!的脚本,假定其引用的资源文件路径中必然有分隔符“.”。但是有一些剧情文本里也有“.”,为了尽量排除掉它们,我写了这样的判断方法:
static bool Match( string tokenString ) {
    return ( tokenString.Contains( "." ) && !tokenString.Contains( "..." )
        && !tokenString.Contains( ">.." ) && !tokenString.Contains( ",.." )
        && !tokenString.Contains( "..<" ) && !tokenString.Contains( "\u3000.." )
        ) || tokenString.Contains( "<IMG" );
}

将前一篇里提到的“反编译器”稍微修改了一下,让它收集所有脚本中满足上面的判断的token,并输出到一个单一的文本文件中。

于是得到了类似这样的一个文件:
(片段)
../
Script/BaseInstruction.txt
Back/Lesson01.bmp
<FONT size=18 face='G'>フィル君.<BR>まだ<TYPE interval=500 speed=500 style='Spring'>~
I/100221/0221-#03b-02-2.bmp
BGM/B02_Juni.ogg
I/100221/0221-#03b-02-3.bmp
I/100221/0221-#03b-02-4.bmp
I/100221/0221-#03b-03-1.bmp
Face/Juni11R.png
<TYPE interval=55 style='Fade'>なっ ..なんて<BR>わかりやすい<BR>ゴマカシを・・・・・・ <TYPE style='Fade'><IMG src='Em/Ase18.png'>

使用UltraEdit打开该文件,并使用文件->排序->高级排序/选项。选择“升序”和“删除重复”,并开始排序。对这里的例子排序的话,结果是:
../
<FONT size=18 face='G'>フィル君.<BR>まだ<TYPE interval=500 speed=500 style='Spring'>~
<TYPE interval=55 style='Fade'>なっ ..なんて<BR>わかりやすい<BR>ゴマカシを・・・・・・ <TYPE style='Fade'><IMG src='Em/Ase18.png'>
BGM/B02_Juni.ogg
Back/Lesson01.bmp
Face/Juni11R.png
I/100221/0221-#03b-02-2.bmp
I/100221/0221-#03b-02-3.bmp
I/100221/0221-#03b-02-4.bmp
I/100221/0221-#03b-03-1.bmp
Script/BaseInstruction.txt

可以看到,如果有重复的资源文本,它们已经被UltraEdit清除掉了。而且有一些我们所不关心的内容也堆在了一起,可以方便的选取并删除。
这里我们对FONT和TYPE标签都没兴趣,但在实际删除它们之前,留意到有些行里有IMG标签,里面有我们感兴趣的src属性指向的是资源文件,得留下。这部分我是自己做了苦力,在UltraEdit里逐个搜索<IMG src并将与其在同一行上的非文件路径内容都删除掉。再做一个排序,确认所有IMG标签都处理好了,然后把FONT、TYPE等标签,以及排在后面的纯剧情文本都删除掉。

经过处理,提取出来的记录里就只剩下这样的内容了:
BGM/B01_Charlotte.ogg
BGM/B02_Juni.ogg
BGM/B03_Shuhua.ogg
BGM/B04_MyHome.ogg
BGM/B05_Serious.ogg
BGM/B07_AcademiaMusicae1.ogg
BGM/B08_AcademiaMusicae2.ogg
BGM/B09_AcademiaMusicae3.ogg
BGM/B10a_Bar1.ogg
BGM/B10b_Bar2.ogg
BGM/B11a_Title.ogg


我把这样的文件列表给了汉公,但之后又得到了新的要求:要把这个列表按归档文件拆分开来。
这是件简单的事。首先得知道路径上什么是归档的文件名,什么是归档里内容的文件名。通过分析,发现路径上最后一个/之后的是归档里内容的文件名,而在那之前的都是归档自身的路径。于是写了个简短的程序来对文件列表做二次处理:
split.cs
// split.cs, 2007/12/21
// by RednaxelaFX

/*
 * Copyright (c) 2007 着作权由RednaxelaFX所有。着作权人保留一切权利。
 *
 * 这份授权条款,在使用者符合以下三条件的情形下,授予使用者使用及再散播本
 * 软件包装原始码及二进位可执行形式的权利,无论此包装是否经改作皆然:
 *
 * * 对于本软件源代码的再散播,必须保留上述的版权宣告、此三条件表列,以
 *   及下述的免责声明。
 * * 对于本套件二进位可执行形式的再散播,必须连带以文件以及/或者其他附
 *   于散播包装中的媒介方式,重制上述之版权宣告、此三条件表列,以及下述
 *   的免责声明。
 * * 未获事前取得书面许可,不得使用RednaxelaFX之名称,
 *   来为本软件之衍生物做任何表示支持、认可或推广、促销之行为。
 *
 * 免责声明:本软件是由RednaxelaFX以现状("as is")提供,
 * 本软件包装不负任何明示或默示之担保责任,包括但不限于就适售性以及特定目
 * 的的适用性为默示性担保。RednaxelaFX无论任何条件、
 * 无论成因或任何责任主义、无论此责任为因合约关系、无过失责任主义或因非违
 * 约之侵权(包括过失或其他原因等)而起,对于任何因使用本软件包装所产生的
 * 任何直接性、间接性、偶发性、特殊性、惩罚性或任何结果的损害(包括但不限
 * 于替代商品或劳务之购用、使用损失、资料损失、利益损失、业务中断等等),
 * 不负任何责任,即在该种使用已获事前告知可能会造成此类损害的情形下亦然。
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

sealed class Splitter {

	static void Main( string[ ] args ) {
        if ( !File.Exists( args[ 0 ] ) ) return;

        string infilelist = args[ 0 ];

		// get the file names and sort them out by the archive they belong to
		// paths that doesn't seem to be in an archive are ignored
		Dictionary<string, List<string>> dic = new Dictionary<string, List<string>>( );
		using ( StreamReader reader = new StreamReader(
			File.OpenRead( infilelist ), Encoding.GetEncoding( "utf-16le" ), true ) ) {
			string line = null;
			while ( ( line = reader.ReadLine( ) ) != null ) {
				int seperateIndex = line.LastIndexOf( "/" );
				if ( -1 == seperateIndex ) continue;

				string path = line.Substring( 0, seperateIndex );
				string filename = line.Substring( seperateIndex + 1 );
				if ( dic.ContainsKey( path ) ) {
					List<string> list = dic[ path ];
					list.Add( filename );
				} else {
					List<string> list = new List<string>( );
					list.Add( filename );
					dic.Add( path, list );
				}
			} // while
		} // using

		// write the file lists out
		foreach ( string path in dic.Keys ) {
			int seperateIndex = path.LastIndexOf( "/" );
			if ( -1 != seperateIndex ) {
				Directory.CreateDirectory( path.Substring( 0, seperateIndex ) );
			}
			using ( StreamWriter writer = new StreamWriter(
				File.Create( path + ".lst" ), Encoding.GetEncoding( 932 ) ) ) {
				foreach( string filename in dic[ path ] ) {
					writer.WriteLine( filename );
				} // foreach
			} // using
		} // foreach
	}
}


完事。来看看其中一个分离出来的lst文件长什么样:
Face.lst
Char01L.png
Char04L.png
Char04R.png
Char15L.png
Gise12R.png
Gise17R.png
Hans03L.png
Hans03R.png
Juni05R.png
Juni10L.png
Juni10R.png
Juni11R.png
Lina02L.png
Lina06L.png
Lina06R.png
May15L.png
May16R.png
Phil00L.png
Phil00R.png
Phil02L.png
Phil02R.png
Phil03L.png
Phil03R.png
Phil04L.png
Phil04R.png
Phil05R.png
Phil07L.png
Phil07R.png
Phil12L.png
Shuh00R.png
Shuh11R.png
Sign09R.png
Sign10R.png


嗯,基本上满足要求了。

==========================================================

进一步的精确分析确实需要写出parser来做。我现在肯定是没时间做,不过计划以后做的时候用ANTLR来完成。难点是要设计出一个精确的上下文无关文法。到时候再说吧~
分享到:
评论

相关推荐

    Quartett!文本插入程序

    "Quartett!文本插入程序"是一个用于在特定文件中插入文本的工具,它主要处理tkn格式的文件。这个程序可能对程序员或系统管理员非常有用,因为它允许他们自动化一些文本处理任务,例如批量添加注释、修改配置文件或者...

    quartett-app

    此外,项目的版本控制可能采用了Git,这可以从"quartett-app-master"这个文件名推断出来,"master"通常指的是Git仓库中的主分支,意味着这是项目的主要代码版本。 开发者可能还使用了Maven或Gradle作为构建工具,...

    ysoserial-master.zip

    ysoserial是一个用于生成利用不安全的Java对象反序列化的有效负载的概念验证工具。它包含一系列在常见Java库中发现的"gadget chains",可以在特定条件下利用执行不安全的反序列化操作的Java应用程序。ysoserial项目最初在2015年AppSecCali会议上提出,包含针对Apache Commons Collections(3.x和4.x版本)、Spring Beans/Core(4.x版本)和Groovy(2.3.x版本)的利用链

    zigbee CC2530无线自组网协议栈系统代码实现协调器与终端的TI Sensor实验和Monitor使用.zip

    1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。

    YOLO算法-自卸卡车-挖掘机-轮式装载机数据集-2644张图像带标签-自卸卡车-挖掘机-轮式装载机.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    Oracle10gDBA学习手册中文PDF清晰版最新版本

    **Oracle 10g DBA学习手册:安装Oracle和构建数据库** **目的:** 本章节旨在指导您完成Oracle数据库软件的安装和数据库的创建。您将通过Oracle Universal Installer (OUI)了解软件安装过程,并学习如何利用Database Configuration Assistant (DBCA)创建附加数据库。 **主题概览:** 1. 利用Oracle Universal Installer (OUI)安装软件 2. 利用Database Configuration Assistant (DBCA)创建数据库 **第2章:Oracle软件的安装与数据库构建** **Oracle Universal Installer (OUI)的运用:** Oracle Universal Installer (OUI)是一个图形用户界面(GUI)工具,它允许您查看、安装和卸载机器上的Oracle软件。通过OUI,您可以轻松地管理Oracle软件的安装和维护。 **安装步骤:** 以下是使用OUI安装Oracle软件并创建数据库的具体步骤:

    消防验收过程服务--现场记录表.doc

    消防验收过程服务--现场记录表.doc

    (4655036)数据库 管理与应用 期末考试题 数据库试题

    数据库管理\09-10年第1学期数据库期末考试试卷A(改卷参考).doc。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    YOLO算法-瓶纸盒合并数据集-3161张图像带标签-纸张-纸箱-瓶子.zip

    YOLO系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中,文件名末尾是部分类别名称; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值; 【注】可以下拉页面,在资源详情处查看标签具体内容;

    职业暴露后的处理流程.docx

    职业暴露后的处理流程.docx

    Java Web开发短消息系统

    Java Web开发短消息系统

    java毕设项目之ssm基于java和mysql的多角色学生管理系统+jsp(完整前后端+说明文档+mysql+lw).zip

    项目包含完整前后端源码和数据库文件 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 服务器:tomcat7

    批量导出多项目核心目录工具

    这是一款可以配置过滤目录及过滤的文件后缀的工具,并且支持多个项目同时输出导出,并过滤指定不需要导出的目录及文件后缀。 导出后将会保留原有的路径,并在新的文件夹中体现。

    【图像压缩】基于matlab GUI DCT图像压缩(含MAX MED MIN NONE)【含Matlab源码 9946期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    YOLO算法-挖掘机与火焰数据集-7735张图像带标签-挖掘机.zip

    YOLO算法-挖掘机与火焰数据集-7735张图像带标签-挖掘机.zip

    操作系统实验 Ucore lab5

    操作系统实验 Ucore lab5

    IMG_5950.jpg

    IMG_5950.jpg

    竞选报价评分表.docx

    竞选报价评分表.docx

    java系统,mysql、springboot等框架

    java系统,mysql、springboot等框架

    zigbee CC2530网关+4节点无线通讯实现温湿度、光敏、LED、继电器等传感节点数据的采集上传,网关通过ESP8266上传远程服务器及下发控制.zip

    1、嵌入式物联网单片机项目开发例程,简单、方便、好用,节省开发时间。 2、代码使用IAR软件开发,当前在CC2530上运行,如果是其他型号芯片,请自行移植。 3、软件下载时,请注意接上硬件,并确认烧录器连接正常。 4、有偿指导v:wulianjishu666; 5、如果接入其他传感器,请查看账号发布的其他资料。 6、单片机与模块的接线,在代码当中均有定义,请自行对照。 7、若硬件有差异,请根据自身情况调整代码,程序仅供参考学习。 8、代码有注释说明,请耐心阅读。 9、例程具有一定专业性,非专业人士请谨慎操作。

Global site tag (gtag.js) - Google Analytics