nds吧 关注:85,548贴子:1,557,320

【NDS汉化相关】关于NCER文件(精灵动画)的进一步研究

只看楼主收藏回复


这是对我之前的帖子:
https://tieba.baidu.com/p/6430520723
的补充&纠错
当时我的技术并不是太好,加上工具所限,所以有很多的错漏。
现在有NitroPaint来方便的编辑NCER了,所以一些只有几帧的简单的精灵位置修改完全可以交给软件解决了。
============================================
不过,近期在帮助汉化《节奏天国黄金版》的时候修改了LOGO,然而这个LOGO图层多(文字+黑底+白底+5个精灵拼接的蓝底,每个文字8层,共56层)帧数多(共52帧),所以用NitroPaint去修改感觉真的有心无力。于是我重新研究起了NCER文件,看能不能写程序解决问题。
【注意】
本贴只是为汉化人员写自动化处理程序的参考资料,并不是教程。因为不同的游戏遇到的问题不同,且考虑到上手门槛,我只会讲解获取某个属性的方法,不会涉及到程序实现的具体细节


IP属地:北京1楼2023-01-12 10:40回复
    NDS的精灵图通常由3部分组成:
    NCGR(tile格式存储的贴图)或NCBR(位图格式存储的贴图)
    NCLR(15bpp格式的调色板)
    NCER(精灵的属性)
    NCGR和NCLR的教程比较多了(并且CT2可以一键解析),所以这里对于这两种格式不再赘述,以下主要讲NCLR


    IP属地:北京2楼2023-01-12 10:47
    回复

      这里补充一下NCGR和NCBR的区别
      NCGR使用8x8tile分块的方式存储,会按照分块依次扫描存储
      而NCBR是位图方式存储,会直接扫完一整齐张图,不分块
      这只是两种不同的存储方式,对于NCER来说这两种贴图都是一样的


      IP属地:北京3楼2023-01-12 11:02
      回复
        接下来就看一下NCER文件,NCER由三部分组成:文件头,帧表,精灵表


        IP属地:北京4楼2023-01-12 11:06
        回复
          不明觉厉


          IP属地:广东5楼2023-01-12 11:06
          回复
            文件头中已知的两个参数是文件大小(32位无符号数)和帧数(32位无符号数)
            以节奏天国主LOGO为例子:

            可以很明显的看到NCER和CEBK的标识
            根据上述格式,可以得到:
            文件大小为0x70b2,即28850字节=28.17KB
            帧数为0x4f,即79帧


            IP属地:北京6楼2023-01-12 11:24
            回复

              帧表由两部分组成:长度(32位无符号数)和偏移量(32位无符号数)
              长度代表该帧有多少个精灵,偏移量代表该帧的第一个精灵在文件的哪里
              【注意偏移量是相对于整个精灵表的开头而不是NCER文件的开头】
              因为帧表后面就紧挨着精灵表,而帧数是79帧,很容易可以算出来第一帧的位置为
              32字节文件头+16字节全0+79帧*8字节=680=0x2a8
              所以实际的偏移量都得加上0x2a8才能对应到正确的位置
              以帧表前5项为例子:
              第一帧有0x25(37)个精灵,第一个精灵在0x2a8+0x0
              第二帧有0x17(23)个精灵,第一个精灵在0x2a8+0xde
              第三帧有0x13(19)个精灵,第一个精灵在0x2a8+0x168
              第四帧有没有精灵
              第五帧有0x13(19)个精灵,第一个精灵在0x2a8+0x1da
              ……


              IP属地:北京8楼2023-01-12 11:42
              回复
                如果涉及到精灵的增删,则除了要修改长度外,还要重新计算偏移量
                偏移量计算方法为:
                第1帧:0x0
                第n+1帧:第n帧偏移量+第n帧长度*6


                IP属地:北京9楼2023-01-12 11:44
                回复
                  在讲精灵表之前,我们需要知道精灵是怎么画出来的:
                  1:根据Tile编号选择需要精灵对应要绘制的贴图
                  2:根据Tile尺寸和调色板调整精灵使其正确显示
                  3:根据坐标在舞台中绘制精灵
                  4:处理特效和变换
                  5:截取窗口显示在屏幕上(一般在舞台中心)

                  舞台的大小为512x256,原点在中心,x轴朝右,y轴朝下,最终游戏会截取256x192的窗口用于显示

                  四边是相通的(超出舞台边界的部分会显示在舞台的另一边)


                  IP属地:北京10楼2023-01-12 12:14
                  回复
                    精灵表是一个6字节的数组,精灵的各种属性已经不再以字节为单位存储,而是以比特为单位存储了(老任黑科技压缩技术)。以下是oam数组的定义,其中每行代表一个字节,每个格子代表一个比特


                    IP属地:北京11楼2023-01-12 12:22
                    回复
                      以第14帧第27个精灵为例子(因为汉化过了所以可能与原本的数据不一样),代表了节奏天国主LOGO动画其中一帧“金”的属性
                      其数据如下:
                      E5 00 D7 C1 B7 B0
                      将其用比特表示如图:

                      我们可以获得的信息如下:


                      IP属地:北京12楼2023-01-12 12:42
                      回复
                        tile编号:0b0010110111=183
                        tile编号是10位无符号整数,其中每个编号代表128字节(4bpp下为4个tile,8bpp下为2个tile)
                        如果你想切换到下一个精灵,而当前精灵的尺寸为64x64,因为tile的尺寸为8x8,所以需要64个tile。因此,编号需要加上16(8bpp要加32)才能正常显示
                        修改tile编号后可以更改你想要显示的精灵(通常还需要改尺寸和调色板)才能正常显示
                        下图为更改tile编号的效果

                        编程时的建议:
                        读取:chara = oam[4] + ( oam[5] & 0b11 << 8 );
                        写入:oam[4] = (chara & 0b11111111); oam[5] = (oam[5] & 0b11111100) | (chara >> 8);


                        IP属地:北京13楼2023-01-12 13:02
                        收起回复
                          x轴坐标:0b111010111=-41
                          x轴坐标是9位有符号整数,用补码表示,范围为-256~255,其中坐标1个单位对应一个像素。
                          修改此值会更改精灵在水平方向的位置(因为节奏天国是竖屏游戏所以表现出垂直位置的变化)

                          编程时的建议:
                          读取:xPos = oam[2] + ( ( oam[3] & 0b1 ) << 8 ); xPos = xPos >= 256 ? xPos - 512 : xPos;
                          写入:xPos = xPos < 0 ? xPos + 512 : xPos; oam[2] = xPos & 0b11111111; oam[3] = (oam[3] & 0b11111110) | (xPos >> 8);
                          注意:用代码操作位移后可能会超出-256~255的范围,此时需要通过+512或-512将其调整到正确的范围


                          IP属地:北京14楼2023-01-12 13:20
                          回复
                            y轴坐标:0b11100101=-27
                            y轴坐标是8位有符号整数,用补码表示,范围为-128~127,其中坐标1个单位对应一个像素。
                            修改此值会更改精灵在垂直方向的位置(因为节奏天国是竖屏游戏所以表现出水平位置的变化)
                            注意:NitroPaint显示的y轴坐标是有问题的,主要是因为这个软件把y轴坐标错误的作为无符号整数表示

                            编程时的建议:
                            读取:yPos = oam[0]; yPos = yPos >= 128 ? yPos - 256 : yPos;
                            写入:yPos = yPos < 0 ? yPos + 256 : yPos; oam[0] = yPos;
                            注意:用代码操作位移后可能会超出-128~127的范围,此时需要通过+256或-256将其调整到正确的范围


                            IP属地:北京15楼2023-01-12 13:28
                            回复
                              以上的x坐标和y坐标的参考点均在精灵的左上角


                              IP属地:北京16楼2023-01-12 13:30
                              回复