魔法少女小圆吧 关注:338,502贴子:8,061,413
  • 41回复贴,共1

魔圆携带版立绘分享

只看楼主收藏回复

总有预感会被吞,只发一遍,建议自行存档收录,如果被和谐了不太打算重发。
因为提取方法不够自动化嫌麻烦加上要忙别的事情所以暂时没有CG等,毕竟我用不到就不愿意费周章了,不过CG是512×307而不是按照屏幕大小定做这点倒是刷新了我的认知……


IP属地:上海1楼2021-06-06 21:17回复
    链接:度盘前面省略,/s/1kzP1etc1qedv3wJDPc9cTw
    提取码:7q4t
    pac.zip。直接提取的所有pac文件。
    extracted_raw.zip。原始解包结果。适用于追求原始数据的人群。
    extracted_png.zip。将gim转换为png的结果,并为便于自行拼接附上了原POS文件。适用于需要自己拼接眨眼动嘴表情的人群。
    assembled_png.zip。直接拼接结果。适用于需要即开即用的人群。
    因为以上提取拼接均由程序进行没有人工滤除无效图片。PNG按理说是无损的,如果觉得模糊是因为原图就是糊的,毕竟PSP屏幕才480×272不需要太清晰


    IP属地:上海2楼2021-06-06 21:18
    回复
      2025-08-29 23:54:41
      广告
      不感兴趣
      开通SVIP免广告
      关于文件名的补充信息:
      这部分基本上看文件就能找到规律了。
      已知问题
      1.部分表情没画(要么面无表情加上红字日文,要么全蓝有白字)……
      2.黑长直没有3和4。麻花焰没有4,但3也是蓝底白字的无意义图片。
      3.上条有一个多余的文件名不正确的全蓝嘴部资源,估计和携带版的大量bug一样是制作组失误。
      文件名格式
      pac文件名的格式是
      TALKCHARA<角色>_<姿态><装束>.GIM
      ,然后这些共用一个身体姿态图片,但是眼睛和嘴部分是透明的。如:
      示例图片
      <角色>是%02d的,麻花焰与黑长直视作不同角色,<姿态>是一位序号,<装束>是a(平常)或b(魔法少女),另外杏子有全套装束标为c的校服杏形态(但只有茶话会结局会出现其中几张吧?),圆则有一个7c是睡衣圆。
      同一姿态号不同装束的表情,存在与否似乎是完全对应的。(不算上条那个文件错误)
      姿态号没有规律,就是从0开始数而已。巧合的是只有杏子和黑长直有新房45°还都是5号。
      杏子有几个拿的食物不一样的单独姿态……
      然后眼睛和嘴是单独的图片,用于提供眨眼过程和不同开口程度的张嘴说话,如果拼接需要自己写程序(如果不想手工每个拼一遍的话),其中从pos那里可以读到眼睛部分和嘴部分的左上坐标(都是先横后竖)。
      格式是TALKCHARA<角色>_<姿态><装束>_<表情号>_E/M<帧号>.GIM
      <表情号>是%02d的格式,00代表平常的表情。
      1.同一表情号不同人物似乎是相似表情(比如01是微笑,但未确认)。
      2.同一个人可以有不同姿态同一表情。
      3.不是所有人所有表情的搭配都存在。
      4.同一姿态不同装束是对应的。
      E/M是眼睛和嘴,眼睛4帧嘴3帧,0是正常的睁眼闭嘴,往后依次是眨眼和张嘴。
      对QB和使魔这些不眨眼不张嘴的,图片没扣出去,眼睛和嘴都是2×2的空白图片,所以不拼也没关系,估计只是用于统一接口的。
      因为不同的姿态,眼睛和嘴附近主要是脸和头发的光影等不同,所以各个姿态间不能互相拼接。
      给出的已拼接图片只有正常的(毕竟眨眼和张嘴的没那么必要啊,到时候贴就好了)。
      GIMDATA和POSDATA这两个DAT似乎只是用于索引文件名的。


      IP属地:上海3楼2021-06-06 21:20
      回复
        复现方案:
        是一个土方法,明显有问题而且不够自动化,有违程序员身份(不是)。
        土法提取
        用PPSSPP模拟运行并调试,为控制堆栈区数据情况使用了某个临时存档从图鉴读取场景立绘。因为代码段地址可以认为不变,估计可以使用。
        名为CRI FS Data Decompression 0的线程会负责处理加载后的数据,从名字来看是解压。
        因为懒得研究汇编,也看不太懂复杂的,我大概跟踪了下执行过程和堆区数据变化,该线程执行位于0x088413EC的函数时会处理一些已加载数据段,该函数在0x8841524地址的jr $ra跳出前,会已经在地址0x09915E00解析出完整的文件。(这个似乎是堆上的地址,所以应该不完全是确定的。不过这个函数加载立绘pac运行后,$t0寄存器会指向其+0x100偏移的地址,如果不同可以做一个参考。其他文件是否也是这个偏移无法确定)
        (总之所以加密方式暂时不详。)
        因为魔圆携带版pac的前三个分别是文件数(uint16)未知(2字节)和文件大小(uint32)(依据是下面quickbms脚本)。从这里人工读出大小,把等大的内存dump成文件就行了。
        之所以说是土方法,是因为整理文章时突然意识到,看名字是criware提供的吧,或许用了他家压缩技术的解开方式应该都一样?那应该有现成工具在吧……以前没弄过所以不知道……
        感谢之前回复的 @caoyang131 吧友提到格式的问题。但所指的应该是正常解压后,文件最后部分是调色盘吧。我之前一直误会了,没意识到解压所以看到的大概是不同结构的文件。不过在此仍然需要表示感谢。
        至于控制加载过程,虽然不能确定是不是最后一次构造文件名,但可以看到在运行到0x088F96BC之前修改从0x08B71360开始的字符串(至少如果是立绘CharaBustup/talkchara??_??.pac,以及feelingdata之类的几个就从这读)就可以指定被加载的pac包。(记得之前存档,因为改过的话后面访问会发现找不到文件,然后模拟器发现被模拟的程序试图访问无效内存无法模拟而把游戏画面显示为蓝屏,但无伤大雅退出游戏重进就行)
        quickbms脚本如下
        get FILES short
        get UNK short
        get ASIZE long
        for i = 0 < FILES
        getdstring NAME 0x20
        get OFFSET long
        get SIZE long
        log NAME OFFSET SIZE
        next i
        其他说明:这个方法如果CG挨张提取太麻烦了,Bg/Event里的应该是,如果能解压就好了。反正我现在也不太需要CG,如果不能自动化执行我就懒得弄了……


        IP属地:上海4楼2021-06-06 21:26
        回复
          辛苦啦~


          IP属地:广东来自Android客户端5楼2021-06-07 04:23
          回复
            好像被吞了 求补档


            IP属地:江西来自iPhone客户端6楼2021-06-07 15:47
            收起回复
              还好我留了草稿……不知道有图会不会被吞……


              IP属地:上海9楼2021-06-08 09:58
              收起回复
                先mark


                IP属地:江西来自Android客户端11楼2021-06-09 00:02
                回复
                  2025-08-29 23:48:41
                  广告
                  不感兴趣
                  开通SVIP免广告
                  也不知道这次行不(来自纹理缓存区所以有未初始化内容,为啥重复就不知道了)


                  IP属地:上海12楼2021-06-09 12:18
                  收起回复
                    到底是哪一个呀?


                    IP属地:山东来自Android客户端13楼2025-08-08 17:42
                    回复
                      解压的密码是什么呀


                      IP属地:山东来自Android客户端14楼2025-08-09 17:14
                      收起回复