pkhex吧 关注:33,358贴子:99,854

简单科普下Gen3的宝可梦数据结构

只看楼主收藏回复

缓更,谢米镇


IP属地:四川来自iPhone客户端1楼2022-09-17 15:11回复
    在所有的宝可梦游戏中,宝可梦都是 “一块块” 的存储在内存中的。了解宝可梦的具体数据构成有助于对宝可梦的合法性和本质的了解。


    IP属地:四川2楼2022-09-17 15:15
    回复
      而 Gen3 作为能把宝可梦传入后代的游戏的开始,很多东西虽然很简单、基础,但是也具备后世代的雏形。后时代的宝可梦数据结构就是在此基础上衍生的。


      IP属地:四川3楼2022-09-17 15:18
      回复
        本片会分为 5 个部分讲解(大概)。
        第一部分:概述
        第二部分:未加密数据的讲解
        第三部分:加密数据的加密与解密
        第四部分:加密数据的讲解
        第五部分:实例(暂定)


        IP属地:四川4楼2022-09-17 15:22
        回复
          概述篇


          IP属地:四川5楼2022-09-17 15:24
          回复
            首先我们先来看一下一个典型的宝可梦在内存中是怎样存放的。(按加密数据按ABCD排序)


            IP属地:四川来自iPhone客户端6楼2022-09-17 15:28
            回复
              在第三世代即红蓝绿宝石和火红叶绿中,所有的宝可梦都是以这样的方式存放在内存当中的。只要我们修改某一个内存单元的数据,就能达到我们想要的结果。而每个数据块的修改方式我会在下面进行讲解。


              IP属地:四川7楼2022-09-17 15:33
              回复
                未加密数据的讲解篇(0x0000-0x001F)


                IP属地:四川8楼2022-09-17 15:34
                回复
                  加油


                  IP属地:安徽来自Android客户端9楼2022-09-17 15:48
                  收起回复
                    PID、TID 和 SID 我们放在一起讲。
                    PID:众所周知,PID 是一串 8 位的十六进制数,他在内存中占用了 4 个字节,并以大小端的形式存放的,即 PID 的低位在低内存地址,PID 的高位在高内存地址。举个例子:我们有一串 PID 是 0x1A2B3C4D,那么在 0x0000 这个地址存放的是 4D,在 0x0001 这个地址存放的是 3C,在 0x0002 这个地址存放的是 2B,在0x0003 这个地址存放的是 1A。
                    TID、SID:我们在 PKHeX 中的看到的 TID 与 SID 是十进制数,而二进制文本编辑器是默认以十六进制显示的(内存中实际上是以二进制存放的),所以我们需要先把 TID 和 SID 转换成十六进制的格式然后以大小端的方式写入(如 PID 那样,后面不在解释大小端)。

                    大伙可以把 PID、TID 和 SID 的实际样子打出来。


                    IP属地:四川10楼2022-09-17 15:50
                    回复
                      昵称,也就是显示宝可梦的名字,如果我们玩家没有取昵称,则昵称默认是种类名。
                      宝可梦的昵称是以 0xFF 结尾的,剩余未用到的字节以 0x00 填充。每个字节的值由专有字符编码确定,对照表(JPN)如下:

                      其中有个需要注意下:
                      0x00 这个是空格。
                      0xFA-0xFF 都是一些控制字符,除了 0xFF 外,其余的我们不会用到。
                      0xB7-0xB9、0xEF 和 0xF0-0xF9 在昵称中是不可用的。


                      IP属地:四川11楼2022-09-17 16:00
                      回复

                        这便是昵称实际在内存中存储的样子。
                        大伙可以把这个昵称在下面打出来。


                        IP属地:四川12楼2022-09-17 16:06
                        回复
                          语言,这个是获得宝可梦时的游戏版本确定的,比如你在日版绿宝石抓了一只盖欧卡,那么这只盖欧卡的语言便是 JPN。
                          需要注意的是在第三世代里,蛋的语言总是设置为日语。在孵化时,蛋的语言会重置为当前所在的游戏语言。
                          该字节的值决定了宝可梦的语言:

                          其中 0x06 对应的 KOR 也就是韩语,在第三世代是未使用的,最好别设置为 0x06。
                          在内存中长这样:


                          IP属地:四川13楼2022-09-17 16:17
                          回复
                            牛哇,谢米大佬,来顶一下


                            IP属地:山东来自Android客户端14楼2022-09-17 16:34
                            收起回复
                              蛋名,设置此字节的时候和上面相比有所不同了,上面讲的那些都是通过直接修改成整个值来达成效果,而蛋名我们必须按位来修改,我会详细讲解下,后面再次出现便不会赘述。
                              首先我前面说过所有的数据在内存中都是以二进制形式存储的,即 11101010 这种形式,这个数字一共有 8 位,从右往左看,我们规定最低位为 “第 0 位” ,最高位为 “第 7 位” 。
                              而蛋名就需要我们按位修改,我们用 1 来表示开启,用 0 来表示关闭,把每一位都改成我们想要的结果(0 或 1)后再转换成十六进制写入。其中的每一位都有特殊的含义,不能乱改。如下图所示:
                              下面我来解释下每一位的含义:
                              位 0:设置此标志后,宝可梦会被视为坏蛋。如果宝可梦的校验和错误,则会自动设置此标志,标记为坏蛋的宝可梦不可用。
                              位 1:宝可梦种类不为 0 时,就会自动设置此标志,任何宝可梦此标志位都为 1。任何没有此标志的宝可梦都无法繁殖,并且在选择时将消失。
                              位 2:设置此标志后,游戏将忽略宝可梦的昵称并显示对应游戏语言的“蛋”。只有蛋才应该有这个标志。
                              位 3-7:未使用,请设置为 0。
                              蛋名(内存中的样子):

                              我来解释下,首先把 0x02 这个值换算成二进制位 00000010:
                              位 0 设置成 0,因为是个合法的宝可梦。
                              位 1 设置成 1,因为所有的宝可梦这个位必须为 1。
                              位 2 设置成 0,因为这个宝可梦不是个蛋。
                              位 3-7 设置成 0,因为这些位未使用。


                              IP属地:四川15楼2022-09-17 16:55
                              回复