| Profil de lovefun童话PhotosBlogListes | Aide |
|
25 octobre 恶魔城的一些破解问题1) 有关编码
; 取高字节
0209385C E200CCFF and r12,r0,0FF00h ;1 70 02093860 E1A0C42C mov r12,r12,lsr 8h ;1 71 ;减掉0x81 02093864 E24CC081 sub r12,r12,81h ;1 72 ;乘以0x1318,加到字库首地址 02093868 E021139C mla r1,r12,r3,r1 ;4 76 ;取低字节 0209386C E20000FF and r0,r0,0FFh ;1 77 ;如果比0x7E大,就减掉1 02093870 E350007E cmp r0,7Eh ;1 78 02093874 82400001 subhi r0,r0,1h ;1 79 ;再减0x40 02093878 E2403040 sub r3,r0,40h ;1 80 ;乘以0x1A 0209387C E0201293 mla r0,r3,r2,r1 ;3 83 02093880 E12FFF1E bx r14 ;3 86 所以,游戏从rom中解密编码的过程可以写为(Python语言):
def L2S(l): sdata = l % 256 hdata = l / 256 if sdata > 0x7e: sdata -= 1 return sdata + (hdata-0x81)*0xbc - 0x40 另外编写一个逆运算,也就是加密过程(这里有不少细节疑问,我认为只要解密的结果一样,加密就是对的):
def S2L(s): s = s + 0x40 low_number = s % 0xbc hi_number = s / 0xbc if low_number > 0x7e: low_number += 1 if low_number < 0x40: low_number += 0xbd hi_number -= 1 return low_number + (hi_number + 0x81) * 256 2)关于字库的缩容
碰到字库大就会引起烧录卡死机的情形。为了尽量减小字库容量,要拼命缩容。本来一个字模26个字节,其中最初的两个字节是无用编码,有人(flyeyes?)提议去掉这两个字节,于是,首先参见游戏显示部分的代码,有一句很重要: 02095180 E59F31D8 ldr r3,=1318h ;注意0x1318=0x1A*0xBC
另外还有一句ldr r4,=1Ah之类的,一时找不到。将这两个分别改成0x18*0xBC和0x18即可。另外注意整个字库最前面还是需要有2字节的无用编码。
3)关于汉化编程
在快速处理方面,得益于Python的快速开发特性。强烈建议有VB等经验的破解员学习Python。附上文本解密导出的程序 # coding:utf8 import os,sys def Output(f, now_index, now_loc): # f.write ("========================\n") f.write ("index: " + str(now_index) + '\n') f.write ("loc: " + hex(now_loc) + '\n') f.write ("--------------------\n") def S2L(s): s = s + 0x40 low_number = s % 0xbc hi_number = s / 0xbc if low_number > 0x7e: low_number += 1 if low_number < 0x40: low_number += 0xbd hi_number -= 1 return low_number + (hi_number + 0x81) * 256 def L2S(l): sdata = l % 256 hdata = l / 256 if sdata > 0x7e: sdata -= 1 return sdata + (hdata-0x81)*0xbc - 0x40 # 换行 ChLine = int("F006",16) # 结束 ChEnd = int("F00A",16) # S-JIS码表 table = {} f = file("SJIS.txt",) for data in f: # data = f.readline() # find the "=" place for i in range(len(data)): if data[i] == "=": break # print data, i address = int(data[:i],16) value = data[i+1:-1] table[address] = value f.close() # 相对码表 xtable = {} f = file("ld937714.dat","rb") fo = file("newtable.txt","w") data = " " number = 0 while True: data = f.read(2) if len(data)<2: break address = ord(data[1]) + ord(data[0])*256 if address == 0: break value = table[address] xtable[number] = value s_number = number + 0x40 low_number = s_number % 0xbc hi_number = s_number / 0xbc if low_number > 0x7e: low_number += 1 if low_number < 0x40: low_number += 0xbd hi_number -= 1 s_number = low_number + (hi_number + 0x81) * 256 # fo.write(hex(number)+"="+hex(s_number)+"="+value+"\n") fo.write(hex(s_number)[2:]+"="+value+"\n") number += 1 data = f.read(24) fo.close() f.close() # 文本 f = file("overlay9_0000.bin","rb") fo = file("textout.txt","w") ft = file("old_index.txt","w") now_index = 0 now_loc = 0 pointer = 0 data = " " Output(fo, now_index, now_loc) sig = True while True: data = f.read(2) if len(data) < 2: break sdata = ord(data[0]) if sdata > 0x7e: sdata -= 1 address = ord(data[0]) + ord(data[1])*256 s_address = sdata + (ord(data[1])-0x81)*0xbc - 0x40 if address == ChLine: fo.write('\n') elif address == ChEnd: fo.write('\n') # fo.write ("--------------------\n\n") fo.write ("====================\n\n") now_index += 1 now_loc = pointer + 2 Output(fo, now_index, now_loc) ft.write (str(now_index) + " " + hex(now_loc)[2:] + "\n") elif address == 0: if sig == False: fo.write('{0}') elif xtable.has_key(s_address): fo.write(xtable[s_address]) # if xtable[s_address] == "遥": # print hex(address), hex(s_address), ord(data[0]), ord(data[1]) else: fo.write('{' + hex(address)[2:] + '}') # else: # print "Error\n" # print now_index, now_loc, data, hex(address) if address == ChEnd or address == 0: sig = True else: sig = False pointer += 2 ft.close() fo.close() f.close() 14 octobre 今天画的asymptote图 还在用metapost的linuxer们……该改用asympote了。 import solids; 13 octobre NDS OAM相关的内存解释OAM是精灵(sprite)映射表的储存位置。某些游戏中文本可能会以精灵的形式存在,所以也许需要跟踪精灵的内存变化。根据相关资料和我的分析,叙述如下: OAM分两块区域:下屏(main screen)从0x07000000起。上屏(sub screen)从0x07000400起。每个屏最多有128个精灵,每个精灵的映射表8个字节,其中前6个字节意义比较重要,举例说明: 0C 40 10 00 A8 04 (1)精灵在屏幕上的位置: X_Loc:0x0C (第一个字节) Y_Loc:0x10 (第三个字节) (2)精灵的大小: 精灵的大小由第二字节的最高两个Bit(Shape位)和第四字节的最高两个Bit(Size位)共同决定。可能还和其他的scale位有关,没有具体研究。最终对应的大小可能有12种(最后三种应该是一种放大): 8*8, 8*16, 8*32, 16*8, 16*16, 16*32, 32*8, 32*16, 32*32, 32*64, 64*32, 64*64 (3)精灵Tile在内存中的位置(这个对汉化比较重要): Tile_Index:A8 (第五个字节) 如为下屏,对应0x06400000+0x20*Tile_Index 如为上屏,对应0x06600000+0x20*Tile_Index 另外有个疑问:GBA的ROM在内存中整体有个映射区域,NDS的ROM则是怎么放入内存的,或者是游戏过程中动态读入,有没有人研究过这个问题?我没有找到相关资料。 1 octobre python中的部分专用类方法一部分在dive into python这本书里面已经有介绍了,更多的部分在Python Reference Manual中
这两个构造函数还是有所不同的,一般都用后者吧……
析构函数。好在python的内存管理很优秀,一般不用析构函数来释放内存,因而用的也少。注意del x这样的语句并不直接调用析构函数。
|
|
|