Skip to content

Commit

Permalink
NeXAS(针对BALDR HEART)完成
Browse files Browse the repository at this point in the history
  • Loading branch information
Darkness-TX committed Jan 21, 2020
1 parent 2f6c7cc commit 467f098
Show file tree
Hide file tree
Showing 17 changed files with 997 additions and 3 deletions.
Binary file added NeXAS/BALDR_HEART/NeXAS_fnt_Shift-JIS.txt
Binary file not shown.
37 changes: 37 additions & 0 deletions NeXAS/BALDR_HEART/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Niflheim-BALDR HEART
用于处理NeXAS引擎,针对BALDR HEART
## [Base on]
giga_text_dump.py:https://github.com/Inori/FuckGalEngine/blob/master/GIGA/giga_text_out.py

dat_dump.py:https://github.com/regomne/chinesize/blob/master/NeXAs/exTxtFromDat.py

pac_unpack、pac_pack:crass源码
## [Note]
#### [字库]
将fnt_make_bold_ft.exe、fnt_make_ft.exe、fnt_make.ini、libpng16.dll、tbl_chs.txt和三个makefnt的bat放在同一个文件夹,新建fnt、UpdateCHS文件夹。

将fnt_build.exe、fnt_dec.exe、libpng16.dll、zlib1.dll和全部原始fnt文件放入fnt文件夹里,双击makefnt_all.bat即可。

如果不想封包,可以去掉makefnt_all.bat的最后一行“pac_pack.exe UpdateCHS”,不然自行添加pac_pack.exe相关exe和dll。

字体用的思源黑体和宋体(tutorial用的宋体),也可以自行更改fnt_make.ini用自己喜欢的字体,我个人觉得思源的字体效果不完美......。

tutorial如果想还原原字体效果,需要在fnt_make_bold_ft.exe生成png后再用ps录制一层描边再批处理,效果为RGB(255,255,255),透明度50%,1像素。

字体对应.txt为找到的fnt在游戏中使用到的地方,并非所有fnt都会使用,NeXAS_fnt_Shift-JIS.txt为所有fnt的编码对应,tbl_chs.txt用于生成中文字库使用的码表,可自行更改,本项目中使用的tbl.txt和tbl_chs.txt都为针对BALDR HEART制作。

最好都用freetype2版的程序(有ft标志),非freetype2的程序后续并没有开发,因为用Windows API生成的效果巨 屎 无 比,所有抛弃了,仅供参考。
#### [游戏主程序]
用的Themida壳,脱壳就顺带也破解了.....,根据dump的方法不同,可能需要自行修复一下IAT表,一般会少了D3DXAssembleShader、D3DXQuaternionMultiply,exe中有非常多文本,想完美汉化不得不脱壳。
#### [文本]
bin中除了导出程序导出的外还会有点文本,一般就一两句话会用到,测试的时候就知道了。

dat为系统文本,mek为机体文本,grp有一些文本,看会不会用到,除了bin和dat外,mek和grp都需要具体文件具体分析。

但是都没有文本长度标识,所有其实可以暴力导出然后按原地址塞回去,再进行超长或缩短后的处理。

tbl.txt为BALDR HEART的汉化码表,更改文本会影响到游戏读取图片文件的文件名,所以使用在GetGlyphOutline中进行编码转换的方式实现汉化,即可保证汉化和原版存档共存,又能保持更改文本对文件读取影响不大,也不会出现乱码。
## [New]
ver 1.0

可解决BALDR HEART汉化
54 changes: 54 additions & 0 deletions NeXAS/BALDR_HEART/dat_dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# -*- coding:utf-8 -*-

import struct
import os
import sys
import io

def byte2int(byte):
long_tuple=struct.unpack('L',byte)
long = long_tuple[0]
return long

def int2byte(num):
return struct.pack('L',num)

def FormatString(string, count):
res = "○%08d○\n%s\n●%08d●\n%s\n\n"%(count, string, count, string)
return res

def dumpstr(src):
bstr = b''
c = src.read(1)
while c != b'\x00':
bstr += c
c = src.read(1)
return bstr.decode('932')

for f in os.listdir('Config'):
if not f.endswith('._dat'):
continue
fs = open('Config/'+f,'rb')
fs.seek(0, os.SEEK_END)
filesize=fs.tell()
fs.seek(0, os.SEEK_SET)
count = byte2int(fs.read(4))
types = [byte2int(fs.read(4)) for i in range(count)]
str_list = []
while fs.tell() < filesize:
for t in types:
if t == 2:
fs.read(4)
elif t == 1:
l=dumpstr(fs)
if len(l) != 0:
str_list.append(l)
if len(str_list)!=0:
dstname = 'Config/' + f[:-5] + '.txt'
dst = open(dstname, 'w', encoding='utf16')
i = 0
for string in str_list:
dst.write(FormatString(string, i))
i += 1
dst.close()
fs.close()
85 changes: 85 additions & 0 deletions NeXAS/BALDR_HEART/dat_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# -*- coding:utf-8 -*-

import struct
import os
import sys
import io

def walk(adr):
mylist=[]
for root,dirs,files in os.walk(adr):
for name in files:
if name[-5:] != '._dat':
continue
adrlist=os.path.join(root, name)
mylist.append(adrlist)
return mylist

def byte2int(byte):
long_tuple=struct.unpack('L',byte)
long = long_tuple[0]
return long

def dumpstr(src):
bstr = b''
c = src.read(1)
while c != b'\x00':
bstr += c
c = src.read(1)
return bstr.decode('932')

def int2byte(num):
return struct.pack('L',num)

def main():
f_lst = walk('Config')
tbl = open('tbl.txt','r',encoding='utf16')
dicts = {}
for rows in tbl:
row = rows.rstrip('\r\n').split('=')
if len(row) == 3:
row[1] = '='
dicts[row[1]]=int(row[0],16)
for fn in f_lst:
fs = open(fn, 'rb')
dstname = fn[:-5] + '.txt'
txt = open(dstname, 'r', encoding='utf16')
filesize=os.path.getsize(fn)
dst = open(fn[:-5]+'.dat','wb')
count = byte2int(fs.read(4))
types=[byte2int(fs.read(4)) for i in range(count)]
dst.write(int2byte(count))
for t in types:
dst.write(int2byte(t))
str_list = []
for rows in txt:
if rows[0] != '●':
continue
row = txt.readline().rstrip('\r\n').replace('\\n','\n')
str_list.append(row)
i = 0
while fs.tell() < filesize:
for t in types:
if t == 2:
dst.write(fs.read(4))
elif t == 1:
l = dumpstr(fs)
if len(l) != 0:
try:
for ch in str_list[i]:
if ch == '\n':
dst.write(b'\x0A')
elif dicts[ch] > 0xFF:
dst.write(struct.pack('>H',dicts[ch]))
else:
dst.write(struct.pack('B',dicts[ch]))
except Exception as inst:
print(str_list[i])
dst.write(struct.pack('B',0))
i += 1
else:
dst.write(struct.pack('B',0))
fs.close()
dst.close()
txt.close()
main()
21 changes: 18 additions & 3 deletions NeXAS/BALDR_HEART/fnt_make.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ Y_fix=-1
[10]
;完成,非103
Font=SourceHanSansCN-Bold.otf
Height=10
X_mod=0
Height=9
X_mod=1
Y_fix=0

[10b]
Expand All @@ -40,6 +40,13 @@ Height=10
X_mod=-1
Y_fix=0

[11e]
;完成,描边
Font=SourceHanSansCN-Bold.otf
Height=10
X_mod=-1
Y_fix=-2

[11s]
;完成,非103,描边
Font=SourceHanSansCN-Bold.otf
Expand Down Expand Up @@ -126,6 +133,14 @@ Height=20
X_mod=0
Y_fix=-2

[20_16]
;完成
Font=SourceHanSansCN-Bold.otf
Width=20
Height=16
X_mod=0
Y_fix=-2

[20b]
;完成,描边
Font=SourceHanSansCN-Bold.otf
Expand Down Expand Up @@ -161,7 +176,7 @@ Font=SourceHanSansCN-Bold.otf
Width=22
Height=28
X_mod=0
Y_fix=1
Y_fix=-2
Gradient=3

[miniscenario]
Expand Down
73 changes: 73 additions & 0 deletions NeXAS/BALDR_HEART/giga_text_dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# -*- coding:utf-8 -*-
import struct,os,fnmatch,re

def walk(adr):
mylist=[]
for root,dirs,files in os.walk(adr):
for name in files:
if name[-5:] != '._bin':
continue
adrlist=os.path.join(root, name)
mylist.append(adrlist)
return mylist

def byte2int(byte):
long_tuple=struct.unpack('L',byte)
long = long_tuple[0]
return long

def int2byte(num):
return struct.pack('L',num)

def FormatString(string, count):
'''
res = "★%08d★\n%s\n"%(count, string+'\n')
res = "☆%08d☆\n%s★%08d★\n%s\n"%(count, string+'\n', count, string+'\n')
'''

#res = "○%08d○%s○\n%s●%08d●%s●\n%s\n"%(count, name, string, count, name, string)


res = "○%08d○\n%s\n●%08d●\n%s\n\n"%(count, string, count, string)

return res

def dumpstr(src):
bstr = b''
c = src.read(1)
while c != b'\x00':
bstr += c
c = src.read(1)
return bstr.decode('932')

def dumptxt(src, offset, count):
src.seek(offset)
str_list = []
for i in range(0, count):
str_list.append(dumpstr(src))
return str_list

def main():
f_lst = walk('Script')
for fn in f_lst:
src = open(fn, 'rb')
dstname = fn[:-5] + '.txt'
dst = open(dstname, 'w', encoding='utf16')

src.seek(4)
entry_count = byte2int(src.read(4))
str_offset = (entry_count << 1) * 4 + 8
src.seek(str_offset)
str_count = byte2int(src.read(4))

str_list = dumptxt(src, src.tell()+1, str_count-1) #最后一句不是文本
i = 0
for string in str_list:
dst.write(FormatString(string, i))
i += 1

src.close()
dst.close()
#print(fn[7:]+'--> done!')
main()
81 changes: 81 additions & 0 deletions NeXAS/BALDR_HEART/giga_text_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# -*- coding:utf-8 -*-

import struct
import os
import fnmatch

def walk(adr):
mylist=[]
for root,dirs,files in os.walk(adr):
for name in files:
if name[-5:] != '._bin':
continue
adrlist=os.path.join(root, name)
mylist.append(adrlist)
return mylist

def byte2int(byte):
long_tuple=struct.unpack('L',byte)
long = long_tuple[0]
return long

def dumpstr(src):
bstr = b''
c = src.read(1)
while c != b'\x00':
bstr += c
c = src.read(1)
return bstr.decode('932')

def dumptxt(src, offset, count):
src.seek(offset)
str_list = []
for i in range(0, count):
str_list.append(dumpstr(src))
return str_list

def main():
f_lst = walk('Update2')
tbl = open('tbl.txt','r',encoding='utf16')
dicts = {}
for rows in tbl:
row = rows.rstrip('\r\n').split('=')
if len(row) == 3:
row[1] = '='
dicts[row[1]]=int(row[0],16)
for fn in f_lst:
src = open(fn, 'rb')
dstname = fn[:-5] + '.txt'
txt = open(dstname, 'r', encoding='utf16')
filesize=os.path.getsize(fn)
src.seek(4)
entry_count = byte2int(src.read(4))
str_offset = (entry_count << 1) * 4 + 8
src.seek(0)
data=src.read(str_offset+5)
dst = open(fn[:-5]+'.bin','wb')
dst.write(data)
for rows in txt:
if rows[0] != '●':
continue
row = txt.readline().rstrip('\r\n')
for ch in row:
try:
if dicts[ch] > 0xFF:
dst.write(struct.pack('>H',dicts[ch]))
else:
dst.write(struct.pack('B',dicts[ch]))
except Exception as inst:
print(fn)
print(row)
dst.write(struct.pack('B',0))
src.seek(str_offset)
str_count = byte2int(src.read(4))
dumptxt(src, src.tell()+1, str_count-1)
data=src.read(filesize-src.tell())
dst.write(data)
src.close()
dst.close()
txt.close()

main()
Loading

0 comments on commit 467f098

Please sign in to comment.