[J2V]Game 4D: God of War Ghost of Sparta Việt ngữ

Thảo luận trong 'Tin tức - Giới thiệu - Thảo luận chung về game' bắt đầu bởi asm65816, 25/12/16.

  1. asm65816

    asm65816 Mega Man

    Tham gia ngày:
    23/5/09
    Bài viết:
    3,320
    Nơi ở:
    El Sallia
    Hướng dẫn cụ thể hơn cho phần tìm Pointer.

    Tiền đề là đã xác định được text trong Ram cũng như trong Iso.
    Như trong hình, đoạn text mở đầu game nằm ở vị trí 0x9DE9183. Giờ tìm pointer của nó như sau:

    [​IMG]

    Giờ ta đặt Read break point tại 0x9DE9183. CPU sẽ dừng xử lý ngay trước khi nó đọc địa chỉ này.

    [​IMG]

    Và ta được:
    - Tại 0x8807804 thực hiện lệnh: LB t1, 0x0 (a3) với ý nghĩa: ghi giá trị của 01 byte tại địa chỉ chứa trong a3 vào t1. Lúc này a3 = 9DE9183, tức địa chỉ của câu thoại ta đang cần tìm pointer.

    [​IMG]

    Giờ ta truy ngược về trước để tìm ra giá trị 9DE9183 được ghi vào a3 từ lúc nào. Nhìn lên 5 dòng lệnh, ta thấy:

    - Tại 88077F0 thực hiện lệnh: Move a3, a1. Có nghĩa là giá trị 9DE9183 của a3 được chuyển từ a1 sang.
    - Giờ ta lại truy ngược, giá trị này từ đâu đưa vào a1.
    - Nhìn lên 4 dòng ta thấy: tại z_un_88077E4 thực hiện lệnh: Andi a3, a1, 0x3.
    - Như vậy có 2 khả năng xảy ra: dòng chảy của lệnh chảy từ 88077E0 đến 88077E4; hoặc từ một nơi khác nhảy đến 88077E4.
    - Thử đặt Execute break point tại 88077E0 (bằng cách double click địa chỉ này trong cửa sổ debug), load lại game thì thấy CPU không dừng. Điều này chứng tỏ dòng lệnh không chảy từ 88077E0 đến 88077E4.
    - Vậy làm sao xác định được dòng lệnh chảy từ đâu đến 88077E4? Hãy xem register RA, hoặc click vào tab RA.
    - Register RA chứa địa chỉ trở về sau khi dòng lệnh nhảy đến một nơi nào đó (ở đây là 88077E4).
    - Giá trị hiện tại của RA là 8A56304.

    [​IMG]

    Như vậy có thể thấy:

    - Tại 8A562F8 thực hiện lệnh: Move a1, s3: chuyển nội dung của s3 sang a1
    - Sau đó tại 8A562FC thực hiện lệnh: Jal z_un_08877e4: nhảy đến subroutine 8877E4 (trước khi nhảy thực hiện Move a2, aw). Sau khi hoàn thành mọi công việc ở subroutine này, dòng lệnh lại trở về 8A56308.
    - Điều này cho thấy giá trị 9DE9183, địa chỉ của text, bắt nguồn từ s3. Giờ ta tiếp tục truy từ đâu chuyển vào s3.


    [​IMG]

    - Nhìn lên trên để truy ngược dòng lệnh, ta thấy tại 8A56274 xử lý: Move s3, s1. Để ý thì thấy lúc này giá trị của s3 là 84001E0, và sau lệnh này thì nó sẽ mang giá trị 9DE9183 nhận được từ s1.
    - Tiếp theo ta truy tìm 9DE9183 được ghi vào s1 từ khi nào.
    - Lại tiếp tục dò ngược về trước, ta thấy tại 8A561F8 xử lý: Move s1, a2. Cho thấy giá trị 9DE9183 xuất phát từ a2. Giờ lại truy tìm từ đâu ghi vào a2.

    [​IMG]

    - Lại nhìn lên trên cách 4 dòng code, thấy: z_un_8A561E8. Làm tương tự như chỗ z_un lần trước, ta xác định được dòng chảy của code là từ 8A54834: Move a2, t0 rồi nhảy đến subroutine z_un_8A561E8. Trước khi nhảy đến đây thì CPU đã chuyển giá từ t0 sang a2. Vậy ta tiếp tục dò tìm từ đâu chuyển vào t0.
    - Tại 8A54820 ta thấy: Move t0, a1. Vậy giá trị 9DE9183 xuất phát từ a1.

    [​IMG]

    - Để ý mũi tên màu da cam chỉ vào 8A54820: Move t0, a1. Mũi tên này cho hay đã có sự phân nhánh từ trước đó, tại vị trí nào đó rẽ sang 8A54820.
    - Giờ kéo lên trên và ta thấy đầu mũi tên xuất phát từ 8A54774: BEQ t0, zero, 0x08A54820. Nếu t0 = 0 thì sẽ nhảy tới 8A54820. Thử đặt Execute break point tại 8A54774 thì sẽ thấy giá trị t0 lúc này là 4B, khác 0. Như vậy dòng chảy không nhảy cóc đến 8A54820 mà thực hiện từng lệnh một đến địa chỉ 8A54820. Và a1 lúc này vẫn là 9DE9183.

    [​IMG]

    - Nhìn lên thấy z_un_8A54758: Addiu sp, sp, -0x10. Giống như trước, xem giá trị RA, lúc này là: 8A5291C. Như vậy dòng chảy của lệnh xuất phát từ 8A52XYZ nhảy đến subroutine z_un_8A54758.
    - Đặt Execute break point tại 8A52914: Jal z_un_8A54758. CPU dừng ngay trước lệnh này, và nhìn lên 3 dòng ta thấy tại 8A52908: Move a1, a2.
    - Điều này cho thấy 9DE9183 được chuyển từ a2 sang a1. Ta tiếp tục tìm nó từ đâu chuyển vào a2.

    [​IMG]

    - Tiếp tục nhìn lên, tại z_un_8A528D8: Addiu, sp, sp, -0x60. Giống như trước, bằng cách xem RA ta dễ dàng xác định dòng chảy xuất phát từ 8ABBXYZ nhảy đến 8A528D8.
    - Tại 8ABBE9C: Move a2, s2. Lệnh này cho thấy giá trị 9DE9183 được chuyển từ s2 sang a2.

    [​IMG]

    - Chú ý tại 8ABBE88: Jal z_un_880CE3C. Có thể khi nhảy tới routine 880CE3C thì s2 nhận được giá trị 9DE9183 từ đâu đó. Nhưng khi đặt thử Execute break point tại 8ABBE88 thì ta thấy s2 vẫn đang giữ giá trị 9DE9183. Nghĩa là nó đã nhận từ trước đó và không liên quan đến subroutine z_un_880CE3C.
    - Từ 8ABBE88: Jal z_un_880CE3C truy ngược về trước 3 dòng, ta thấy tại 8ABBE7C: move s2, a1. Vậy giá trị của s2 đến từ a1.
    - Nhìn lên z_un_8ABBE64: Addiu, sp, sp, -0x20. Tương tự như trước, xem RA để xác định dòng code chảy từ đâu đến đây.

    [​IMG]

    - Giá trị Ra lúc này là 8ABBF40, cho thấy dòng code chảy từ 8ABBFXY đến z_un_8ABBE64.
    - Tìm đến 8ABBF40, nhìn lên trên, tại 8ABBF34: move a1, v0. Điều này cho thấy giá trị 9DE9183 đến từ v0.

    [​IMG]

    - Từ 8ABBF34: move a1, v0 nhìn lên 3 dòng: 8ABBF28: JAL z_un_8ABB4B0. Đặt Execute break point tại đây thì thấy v0 lúc này mang giá trị 9DE8E68, không phải giá trị ta cần tìm. Như vậy có thể kết luận 9DE9183 đến từ đâu đó trong subroutine z_un_8ABB4B0 này.

    [​IMG]

    - Sau khi nhảy đến z_un_8ABB4B0, quan sát routine này (hoặc click vào "Step Into" để bám theo từng lệnh một) ta thấy có đoạn:

    8ABB4E0: LW v0, 0x4 (t0) chứa giá trị tại địa chỉ (t0 + 4) vào v0.
    8ABB4E4: Addu v0, a0, v0: v0= a0 + v0.

    Như vậy đây là 2 dòng xử lý làm thay đổi giá trị của v0.

    [​IMG]

    Đi vào chi tiết từng dòng lệnh:

    8ABB4E0: LW v0, 0x4 (t0) chứa giá trị tại địa chỉ (t0 + 4) vào v0.

    Lúc này t0= 9DE8E10. Vậy ta được v0= giá trị tại (9DE8E10 + 4 = 9DE8E14). Nhảy tới địa chỉ 0x9DE8E14 trong Ram, ta được giá trị 02BB.

    (PSP kiểu Little Endian)

    [​IMG]




    Ở dòng tiếp theo:

    8ABB4E4: Addu v0, a0, v0: v0= a0 + v0. Lúc này a0= 9DE8EC8. Dễ dàng nhận thấy đây là địa chỉ bắt đầu của cả khối text.

    Như vậy v0= 9DE8EC8 + 02BB=9DE9183. Đây chính là địa chỉ bắt đầu câu text trong đoạn mở đầu mà ta cần tìm.

    [​IMG]

    Như vậy có thể kết luận: giá trị 02BB tại 9DE8E14 trong Ram chính là Pointer chỉ đến địa chỉ câu text tại 9DE9183. Từ đó dễ dàng tìm ra vị trí của Pointer này trong file R6_INTRODUCE.BIN bằng chức năng tìm kiếm của Hex editor.

    Và ta được công thức: địa chỉ bắt đầu text = địa chỉ bắt đầu cả khối text + giá trị Pointer.
     
    Hakbit thích bài này.
  2. asm65816

    asm65816 Mega Man

    Tham gia ngày:
    23/5/09
    Bài viết:
    3,320
    Nơi ở:
    El Sallia
    GOW GOS bản Việt ngữ được dịch thuật dựa trên nền tảng GOW Kōtan no kokuin. Phiên bản này hỗ trợ âm thanh 2 ngôn ngữ: Nhật và Anh. Vì vậy, người chơi có thể lựa chọn thay đổi ngôn ngữ (âm thanh) trong khi phần phụ đề, ngôn ngữ văn bản vẫn là tiếng Việt.

    Phần âm thanh sẽ là tiếng Nhật (00) hoặc tiếng Anh (01) tùy thuộc vào chế độ cài đặt ngôn ngữ của máy PSP hoặc giả lập PSP. Trường hợp sử dụng giả lập thì tham khảo phần bên dưới đây.

    [​IMG]
    [​IMG]

     
  3. Ky_Kjske

    Ky_Kjske Mr & Ms Pac-Man

    Tham gia ngày:
    8/2/08
    Bài viết:
    104
    Thôi xác định là có censored rồi =))
     
  4. asm65816

    asm65816 Mega Man

    Tham gia ngày:
    23/5/09
    Bài viết:
    3,320
    Nơi ở:
    El Sallia
    Bản JP có censored một cảnh duy nhất: nó cắt hẳn cảnh người lính Sparta bị chém đứt đôi thân, lòi ruột ra ngoài.
    Đến khi hack dữ liệu phục hồi lại cảnh đó thì thấy censored: đoạn ruột lòi ra ngoài biến đâu mất tiêu. Còn bản USA thì cảnh đó không bị cắt, và thể hiện ruột lòng thòng ra khỏi cái thân đứt lìa.

     
  5. Tiger Tank

    Tiger Tank C O N T R A GameOver

    Tham gia ngày:
    29/12/16
    Bài viết:
    1,683
    riêng mấy game có hở hang gái thì bản nhật uncen bản mĩ cen :2onion19: mấy game kinh dị của jap mấy cảnh kinh hơn god of war nhiều
     

Chia sẻ trang này