[Hướng dẫn] Tiếng Việt trong Visual Novel

Death

Đét
Messages
1,773
Reaction score
538
Points
113
Credits
179

Nhân dịp fanpage đổi tên miền, đồng thời dạo này thấy có nhiều dự án nổi lên nên tiện thể viết thêm bài hướng dẫn này, coi như bổ sung một số chỗ chưa được đề cập chi tiết trong http://hako.re/forum/16-huong-dan/974-guide-nhung-dieu-can-biet-khi-lap-pj-dich-vn.html, cụ thể là về phần Tech.

I. Những điều cơ bản
1. Tool
Như được đề cập trong bài hướng dẫn cũ, tool là thứ không thể thiếu trong việc dịch một bộ VN. Tool có nhiều loại và có thể được tìm ở nhiều nguồn khác nhau, mình xin nhắc lại một số nguồn cơ bản:
  • TLWiki (ExtractData, Crass, arc_unpacker,...)
  • asmodean (Nơi tổng hợp tool của một số engine cụ thể)
Hiện tại đã có rất nhiều tool để extract data nhưng tool đóng gói (compiler) thì lại rất ít. Rất may là nhiều engine có hỗ trợ đọc data ngay trong folder game mà không phải qua khâu đóng gói nên nếu bạn không quan tâm đến việc tỏ ra "chuyên nghiệp" thì có thể bỏ qua công đoạn này.
2. Encoding
Khái niệm Encoding có thể được tìm ở nhiều nơi, có thể hiểu đơn giản là bảng mã mà engine dùng để hiển thị các kí tự.


Unikey.

Với các engine Nhật, encoding thường được sử dụng là Shift-JIS, rất đáng tiếc là nó không hỗ trợ tiếng Việt nên làm việc trên các engine này rất khó khăn. Vậy nên nếu bạn muốn solo một dự án nào đó mà không cần động nhiều đến phần tech thì tốt nhất là nên tìm một engine hỗ trợ Unicode hay UTF-8 như KiriKiri hay (O)NScripter để làm.

II. Kỹ thuật nâng cao
Như đã nói ở trên, có một số engine phức tạp cần phải qua xử lý mới hoạt động được như ý, đây sẽ là phần để giải quyết chúng và các vấn đề thường gặp khác.
1. Sửa font
a. TCVN3
Trước khi vào việc chính, mình xin nói thêm về bảng mã TCVN3 (Tiêu Chuẩn Việt Nam 3). Đã bao giờ bạn thắc mắc vì sao lại sinh ra thêm một bảng mã riêng cho tiếng Việt mà không dùng các bảng mã khác như Unicode hay UTF-8 chưa? Lí do chính là vận dụng việc sửa font để hiện thị tiếng Việt trên các nền tảng không hỗ trợ.


Font .VnArial trong FontForge.

Có thể thấy, những kí tự đặc biệt đã được thay bằng các chữ cái tiếng Việt. Nhưng cũng có một điều khác đáng chú ý đó là... không gồm các chữ in hoa. Đúng vậy, trong bảng mã TCVN3, muốn hiển thị các chữ in hoa có dấu như Ắ Ớ thì phải... dùng font khác, cụ thể là thêm chữ H sau tên font (.VnArial -> .VnArialH). Lí do của việc này là số kí tự có thể thay đổi bị giới hạn.

"Tiếng Nhật có cả nghìn chữ sao mà không đủ?", để trả lời cho câu hỏi này, xin mời đọc tiếp phần dưới.
b. Half-width và Full-width
Half-width và Full-width là thuộc tính chỉ độ rộng của một kí tự, có thể xem qua video bên dưới để thấy rõ hơn:


Trong bản demo trên, những chữ cái tiếng Việt sau khi được sửa trông rất lệch lạc, đây là kết quả của việc sửa font trên các kí tự Full-width mà không chỉnh lại độ rộng (Chỉnh lại được không thì mình không rõ, nhưng nếu engine đã hard code độ rộng rồi thì khá là khó). Những chữ cái không dấu khác vẫn hiển thị bình thường vì chúng là các kí tự Half-width.

Vậy chúng ta cần bao nhiêu kí tự Half-width để có thể nhét vừa bảng chữ cái tiếng Việt vào? Bỏ qua 48 chữ cái aA -> zZ cơ bản (mình tính cả vài chữ tiếng Anh nữa), tiếng Việt còn có thêm 134 chữ cái nữa, tính riêng chữ cái không hoa là 67. Vậy nhiệm vụ đầu tiên cần phải làm là tìm chỗ để nhét 67 chữ cái kia vào.


Lưu ý là bình thường chỉ dùng được Half-width kana thôi chứ không dùng được Half-width hira nhé. Những chữ hiragana nhỏ thường dùng trông vậy thôi nhưng đều tính là Full-width, vì vậy độ rộng của chúng là như nhau khi hiển thị trong game (つっ). Sau khi tính toán lấp đầy bảng Half-width kana thì còn thiếu hơn chục chữ nữa, hi sinh dàn chữ số và một số kí tự đặc biệt nữa (tùy ý) là coi như đủ.

Tiếp đến là những chữ in hoa có dấu, cái này thì đơn giản hơn. Dấu cách + Half-width = Full-width. Và đầu câu mới phải viết hoa nên sẽ không gặp nhiều trở ngại, chỉ cần đẩy chữ sang bên phải là được. (Nhớ thêm lại chữ số và kí tự đặc biệt đã hi sinh bên trên)
c. Code replace
Phần này cũng quan trọng chẳng kém, một khi đã sửa font thì tức là đã có một bảng mã riêng. Với số lượng chữ cái cần thay trên 134 thì chắc chẳng ai muốn replace thủ công cả. (Nếu ai biết tool nào phục vụ việc này thì tốt quá)

*Code thì mạnh ai nấy làm, phần này và cả những phần sau nữa chỉ mang tính chất tham khảo.

  • Tool tham khảo: Chưa có.
  • Tool thực tế: Cập nhật sau.
2. Word wrap
Từ trước đến nay word wrap luôn là vấn đề đau đầu của nhiều dự án, thậm chí đến nỗi drop luôn vì không tìm được tool. Một số khác thì tuyển cả một chức vụ đặc biệt là... line breaker, người chuyên ngắt dòng. Word wrap có nhiều loại khác nhau, tùy thuộc vào engine sử dụng, nhưng thường là không hỗ trợ tiếng Việt. Đối với những engine có hỗ trợ code như Kirikiri thì việc tìm cách để word wrap tự động có thể sẽ dễ dàng hơn, nhưng đối với những engine hard code như BGI hay Leaf thì việc này thường rất khó. Nhưng khó không có nghĩa là bất khả thi, ít ra thì vẫn có thể tìm cách này hay cách khác. Ở phần này, mình xin giới thiệu một cách word wrap cũng rất hiệu quả, đó là dùng Windows API để đo độ dài thực của câu.

+ Độ chính xác cao.
+ Có thể sử dụng với nhiều engine khác nhau.
- Khá khó nếu không biết code.
- Rắc rối với các engine có code đi kèm text. (Kirikiri)
- Người chơi không được đổi font nếu dùng cách này.

*Nên tham khảo các thuật toán word wrap khác nhau.


3. ?

III. Hướng dẫn chi tiết
Ngoài hướng dẫn chung như bên trên ra thì sẽ còn hướng dẫn với các engine cụ thể nữa. Hiện tại mình chỉ định viết cho 2 engine thôi, mọi ý kiến đóng gạch đều được hoan nghênh :57:

  • Tiếng Việt trong Ethornell Engine (BGI).
  • Tiếng Việt trong Leaf Engine.
[/CENTER]
 

Hako-chan

Staff member
Administrator
Super Members
Uploader
Translator
Messages
4,789
Reaction score
2,895
Points
113
Credits
116
Ko thấy hướng dẫn làm sao để chèn text vào game. 1/10 :185:
 

Anikawa

Trap Cadet
Messages
197
Reaction score
41
Points
28
Credits
0
Edit font thì nên dùng gì tốt nhất nhỉ? Fontlab chăng?
 

Death

Đét
Messages
1,773
Reaction score
538
Points
113
Credits
179
Mình thì cứ google kết quả đầu tiên thôi =))
Nếu quen dùng phần mềm khác thì cứ dùng, miễn thấy ổn là được.
 

[K]hoaSin

Erogeneration
Super Members
Uploader
Messages
1,466
Reaction score
1,097
Points
113
Credits
100
Ko thấy hướng dẫn làm sao để chèn text vào game. 1/10 :185:
Thỉnh thoảng sếp nhà ta chấm điểm chuẩn quá mức cần thiết :sheep:
 

Death

Đét
Messages
1,773
Reaction score
538
Points
113
Credits
179
Chưa được share tool vạn năng dùng được với mọi engine nên việc đưa nó vào hướng dẫn chung là quá sức với mình :122:
Có phần hướng dẫn chi tiết cũng là có cái cớ của nó :53:
 

bestfriends_0705

Trap Cadet
Messages
289
Reaction score
46
Points
28
Credits
0
Còn một cách khác để hiện Tiếng Việt trong game mà chẳng cần sửa font hay cần engine gì cả, đó chính là memory-patching (inject DLL và hook code để thao túng hoạt động của game, trò này rất lợi hại), script của game có thể dùng mã gì để thể hiện Tiếng Việt cũng được, nhưng ta hook vào 1 API hiện kí tự (TextOut chẳng hạn) để convert ngay qua Unicode, rồi cho hiển thị bằng font có sẵn đã support Tiếng Việt Unicode :D . Tuy nhiên cách này đòi hỏi phải biết cách chọc ngoáy vào file exe (đọc asm các kiểu), và biết code C++.
Minh chứng thực tế: https://thpatch.net/wiki/Touhou_Patch_Center
 

Death

Đét
Messages
1,773
Reaction score
538
Points
113
Credits
179
^ Thì y như hook của VNR thôi, nhưng VNR cũng không hook hết được engine nên kèo này khó :mohoi:

rồi cho hiển thị bằng font có sẵn đã support Tiếng Việt Unicode :D
Và một số engine không nhét được unicode vào text, vậy nên cách này fail ngay từ công đoạn đầu. (Tức là chưa xong đầu vào đã lo đầu ra)
 
Last edited:

bestfriends_0705

Trap Cadet
Messages
289
Reaction score
46
Points
28
Credits
0
Và một số engine không nhét được unicode vào text, vậy nên cách này fail ngay từ công đoạn đầu. (Tức là chưa xong đầu vào đã lo đầu ra)
Mình làm được đấy bạn, ví dụ có con game sử dụng lệnh TextOutA (chỉ support ANSI, không support Unicode và phụ thuộc vào system locale) để xuất text, thì mình sửa script như thế này chẳng hạn:

Thể hiện câu "Đây là Tiếng Vit"
thành "(0x80)(0x81)y l(0x82) Ti(0x83)ng Vi(0x84)t"
từng byte một như vậy (tận dụng mã ANSI 0x80 đến 0xFF để mã hóa kí tự có dấu, còn từ 0x00 đến 0x7F thì theo ASCII), thực tế là lưu thành"
(0x80)(0x81)(0x79)(0x20) (0x6C)(0x82)(0x20) (0x54)(0x69)(0x83)(0x6E)(0x67)(0x20) (0x56)(0x69)(0x84)(0x74)

Xong rồi mình dùng kĩ thuật hook WinAPI TextOutA và đổi hướng nó sang TextOutW (API Unicode)
rồi trong hook đó, viết thuật toán đổi chuỗi byte trên sang Unicode tương ứng rồi đưa cho TextOutW.
(0x80) => "Đ" , (0x81) => â , (0x82) => à, (0x83) => ế , (0x84) => ệ

Toàn bộ các kí tự dựng sẵn đều có thể nhét hết vào 0x80 đến 0xFF , thêm với kĩ thuật hook, memory-patching thì ngay trong lúc chạy có thể đổi font thoải mái :D
 
Last edited:

Death

Đét
Messages
1,773
Reaction score
538
Points
113
Credits
179
Mình làm được đấy bạn, ví dụ có con game sử dụng lệnh TextOutA (chỉ support ANSI, không support Unicode và phụ thuộc vào system locale) để xuất text, thì mình sửa script như thế này chẳng hạn:

Thể hiện câu "Đây là Tiếng Vit"
thành "(0x80)(0x81)y l(0x82) Ti(0x83)ng Vi(0x84)t"
từng byte một như vậy (tận dụng mã ANSI 0x80 đến 0xFF để mã hóa kí tự có dấu, còn từ 0x00 đến 0x7F thì theo ASCII), thực tế là lưu thành"
(0x80)(0x81)(0x79)(0x20) (0x6C)(0x82)(0x20) (0x54)(0x69)(0x83)(0x6E)(0x67)(0x20) (0x56)(0x69)(0x84)(0x74)

Xong rồi mình dùng kĩ thuật hook WinAPI TextOutA và đổi hướng nó sang TextOutW (API Unicode)
rồi trong hook đó, viết thuật toán đổi chuỗi byte trên sang Unicode tương ứng rồi đưa cho TextOutW.
(0x80) => "Đ" , (0x81) => â , (0x82) => à, (0x83) => ế , (0x84) => ệ

Toàn bộ các kí tự dựng sẵn đều có thể nhét hết vào 0x80 đến 0xFF , thêm với kĩ thuật hook, memory-patching thì ngay trong lúc chạy có thể đổi font thoải mái :D
Trước có thử vụ A -> W rồi nhưng không được trên BGI.
Cho hỏi bạn làm trên engine nào với font nào luôn :148:
 
Top