Công khai mã nguồn bản dịch Tear Ring Saga

Thảo luận trong 'Turn Based Strategy' bắt đầu bởi SPC700, 7/1/24.

  1. SPC700

    SPC700 Legend of Zelda

    Tham gia ngày:
    1/10/20
    Bài viết:
    1,062


    Tear Ring Saga, tên ban đầu là Emblem Saga, được rất nhiều tay chơi game Việt Nam biết đến với tên gọi "Mộc đế 6" hoặc "Mộc đế PS1".
    Đơn giản là do game này có cùng cốt cách với dòng game "Mộc đế" (Fire Emblem) do hãng Ninh Tiền Đô phát hành.

    Emblem Saga là sản phẩm của Kaga Shōzō sau khi ông này rời khỏi Intelligent Systems, công ty phát triển game cho Ninh Tiền Đô, và nổi tiếng nhất qua series Fire Emblem. Kaga Shōzō cũng là người sáng tạo nên dòng game Fire Emblem, nhưng Ninh Tiền Đô lại là bên chi tiền để phát triển cả dòng game này.
    Vì thế, ngay sau khi Kaga Shōzō thành lập công ty riêng, tạo nên Emblem Saga thì giữa Ninh Tiền Đô và ông này đã diễn ra vụ kiện tụng kéo dài đến năm 2005, xoay quanh vấn đề tác quyền.
    Cũng vì lẽ đó mà Emblem Saga được đổi tên thành Tear Ring Saga.
    Bản dịch tiếng Việt này được hoàn thành (mức độ 100%) vào năm 2014. Sau 10 năm, tác giả bản dịch quyết định công khai code và script của bản dịch này để cộng đồng có thể chỉnh sửa lời thoại, xây dựng nên những câu chuyện mới.

    Link:
    https://www.mediafire.com/file/6f9wafsvd5r91jl/Emblem_Saga.rar

    Cũng giống như các phiên bản Fire Emblem khác, đây là game có khối lượng thoại đồ sộ, không thua kém bất cứ trường thiên tiểu thuyết nào.
    Ngoài ra, tác giả bản dịch này còn công khai mã nguồn + script bản dịch tiếng Việt cho nhiều game khác.
    Xem chi tiết ở link bên dưới.

    https://sites.google.com/view/sfc65816
     
    Sephir0th and namff like this.
  2. SPC700

    SPC700 Legend of Zelda

    Tham gia ngày:
    1/10/20
    Bài viết:
    1,062
    Một số bạn hỏi sao bản dịch Tear Ring Saga không chơi được trên PS Vita.
    Câu trả lời là: PS Vita không thể chơi được game PS1.
    Tuy nhiên, nó có thể chơi được game của PSP, còn máy PSP thì lại chơi được game PS1.
    Do đó, để chơi bản dịch Tear Ring Saga trên máy PS Vita thì cần phải:
    1) Convert Rom Tear Ring Saga thành dạng Eboot để máy PSP có thể đọc được.
    2) Chạy giả lập PSP trên máy PS Vita (giả lập Andreline)
    Một số hệ máy cầm tay của Ninh Tiền Đô cũng có thể chạy được bản dịch này với giả lập PS1, nhưng không khuyến khích.
    Bởi vì CPU của hệ PS nhà Sony là MIPS, trong khi CPU của các hệ máy cầm tay của nhà Ninh Tiền Đô thường là ARM, và thường yếu hơn nên độ tương thích không cao.
    Mà bây giờ nhìn lại thì thấy bản dịch này (năm 2014) chỉ mới dừng ở mức thủ thuật chứ chưa phải kỹ thuật.
    Còn link bên dưới bao gồm Rom tiếng Việt cho cả PS1 lẫn Eboot cho PSP, nhưng có thêm một số chỗ nghịch ngợm của năm 2024.

    Link:
    Super Easy Tear Ring Saga (mediafire.com)

    a) Di chuyển không tốn lượt
    b) Mua đồ không tốn tiền, nhưng bán thì tăng tiền
    c) Level up với 1 EXP
    d) Độ bền của vũ khí chỉ có tăng chứ không có giảm
    Bản vọc này thích hợp cho người chỉ muốn thưởng thức nội dung của game, hoặc người lúc nào cũng muốn tiền vào mà không thích tiền ra....

     
    Sephir0th, namff and T0977999482 like this.
  3. SPC700

    SPC700 Legend of Zelda

    Tham gia ngày:
    1/10/20
    Bài viết:
    1,062
    Hack những điều chưa ai từng làm trong TRS.

    STONE BOAT - Tear Ring Saga (google.com)

    Đánh bại Erunsth ở MAP 10

    Hầu hết người chơi kỹ Tear Ring Saga (TRS) đều có ấn tượng với kỵ sĩ Hoàng kim Erunsth ở MAP 10. Đây là một trong những nhân vật mạnh nhất game, các chỉ số cao ngất ngưởng cùng với bộ skill khủng và mấy cái khiên giảm sát thương đáng kể. May thay là trong lần đụng độ ở MAP 10, nhân vật này không chủ động tấn công người chơi, và cũng chủ động rút lui sau một số lượt đi.

    [​IMG]

    [​IMG]
    Trang bị của Erunsth: khiên giảm 20 sát thương vật lý và 2 khiên giảm sát thương ma thuật

    Tuy nhiên, nếu muốn thì người chơi cũng có thể giao chiến với Erunsth nếu đủ tự tin vào sức mạnh của mình. Chỉ có điều nhân vật này được thiết kế để không thể bị đánh bại ở MAP 10 nếu giao đấu trực tiếp. Cụ thể là trước mỗi trận đấu, CPU luôn kiểm tra xem lượng sát thương mà Erunsth sẽ nhận được trong trận ngay sau đó có vượt quá số HP còn lại của nhân vật này hay không. Nếu lượng sát thương vượt quá số lượng HP còn lại thì CPU sẽ rẻ nhánh sang hướng xử lý khác thông thường, là khiến nhân vật luôn tránh được mọi đòn đánh của người chơi. Trận đánh trong TRS và nhiều phiên bản Fire Emblem khác đều diễn ra theo kịch bản đã được tính toán sẵn từ trước. Trước mỗi trận đấu, CPU luôn tính toán tỷ lệ trúng đòn, lượng sát thương hay tỷ lệ đánh tất sát của mỗi bên, có nhân vật nào chết hay không. Mọi hình ảnh chiến đấu diễn ra sau đó chỉ là phần diễn kịch lại những kịch bản đã được định đoạn ở bước tính toán trước đó.

    Ta có thể kiểm chứng điều này bằng cách dùng phần mềm giả lập kiêm Debugger cho máy PlayStation, từ đó chỉnh sửa code để game bỏ qua bước kiểm tra này. Khi đó thì Erunsth sẽ không còn tự động né đòn khi HP xuống thấp nữa.

    Ý tưởng ở đây là đặt break point tại địa chỉ Ram quản lý giá trị HP hiện tại của nhân vật này để xem CPU làm gì với giá trị này. Đầu tiên là cần phải tìm được địa chỉ Ram quản lý HP hiện tại của Erunsth. Các Debugger thường có chức năng scan memory để tìm ra những địa chỉ nào có giá trị biến đổi theo thời gian. Chẳng hạn, nếu HP hiện tại của Erunsth đang là 49, và ta scan giá trị 49 trong memory; rồi sau một trận đánh, HP của nhân vật này giảm còn 40 thì ta tiếp tục dò tìm giá trị nào từng là 49 nhưng ngay thời điểm này là 40; và cứ tiếp tục như thế sau vài lần lọc thì sẽ tìm được địa chỉ Ram quản lý giá trị HP hiện tại của nhân vật này.

    Không chỉ các Debugger mới có chức năng này, mà một số phần mềm độc lập như Art Money hay Cheat Engine cũng có chức năng tương tự. Bằng cách này thì ta dễ dàng tìm được địa chỉ Ram này là $801925E8.

    [​IMG]

    [​IMG]
    Lưu ý là địa chỉ này chỉ quản lý HP hiện tại của nhân vật trong trận đấu, không phải là địa chỉ thể hiện giá trị HP hiện tại "thật" của nhân vật. Trước mỗi trận đấu, giá trị HP hiện tại "thật" từ địa chỉ Ram khác được copy vào $801925E8, để rồi khi trận đấu diễn ra thì CPU luôn đọc địa chỉ $801925E8 ở mỗi frame để vẽ các vạch tương ứng với số HP còn lại.

    [​IMG]

    [​IMG]
    Bằng cách thay đổi giá trị tại $801925E8 thì lượng HP được hiển thị cũng thay đổi theo.

    Nếu đặt write break point tại địa chỉ $801925E8 thì sẽ thấy giá trị HP được copy sang địa chỉ này từ Register $v0 trước khi trận đấu diễn ra.

    800f9c2c ae420020: sw $v0(00000031), 0x0020(s2)([801925e8] = 00000031)

    Đoạn log trên thể hiện giá trị 0x31 (tương đương số thập phân 49), tức giá trị HP hiện tại của Erunsth, được copy từ Register $v0 sang địa chỉ Ram $801925E8. Nếu truy ngược về trước một chút của đoạn log thì sẽ thấy có đoạn xử lý như bên dưới.

    8010d278 3042003f: andi $v0(007bc031), 0x003f

    8010d27c 0262102a: slt $v0(00000031), $s3(00000009), $v0(00000031)

    8010d280 144000d0: bne $v0(00000001), $r0(00000000), 0x8010d5c4

    8010d284 2402004a: li $v0(00000001), 0x004a

    8010d5c4 8fa30020: lw $v1(00000065), 0x0020(sp)([801ffd60] = 00000001)

    8010d5c8 00000000: nop

    Điều này có nghĩa là tại Register $v0, giá trị HP là 1 byte (0x31) nằm chung với 3 byte khác (0x00, 0x7B, 0xC0), sau đó được AND với 0x3F để giữ lại byte cuối là 0x31. Sau đó, CPU sẽ kiểm tra xem giá trị tại $s3 (đang là 0x09) có nhỏ hơn giá trị tại Register $v0 (đang là 0x31) hay không. Giá trị tại $s3 lúc này chính là lượng sát thương mà nhân vật sẽ nhận được trong trận đấu sắp tới. Nếu lượng sát thương sẽ nhận được (0x09) nhỏ hơn lượng HP hiện tại (0x31) thì $v0 sẽ được set giá trị thành 0x01.

    [​IMG]

    [​IMG]
    Lệnh SLT trong ngôn ngữ MIPS R3000A mà máy PlayStation sử dụng mang nghĩa là set giá trị 1 cho Register đích nếu giá trị của Register được so sánh nhỏ hơn giá trị của Register là đối tượng so sánh

    Sau đó, giá trị của Register $v0 được so với 0x0000 (tại Register $r0), nếu giá trị này khác 0x00 thì CPU sẽ rẻ nhánh sang địa chỉ thực thi ở $8010D5C4. Điều này có nghĩa là nếu kết quả của phép so sánh trước đó là 1 (trường hợp lượng sát thương nhỏ hơn lượng HP còn lại) thì CPU sẽ xử lý ở phần cho phép nhân vật nhận sát thương bình thường. Còn nếu kết quả của phép so sánh trước đó là 0 (trường hợp lượng sát thương lớn hơn lượng HP còn lại) thì CPU sẽ không phân nhánh mà xử lý theo hướng khiến nhân vật tự động né đòn.

    Do vậy, nếu tại địa chỉ thực hiện phép so sánh mà ta sửa lại lệnh thi hành, khiến CPU luôn phân nhánh (jump) tới địa chỉ $8010D5C4 thì nhân vật không còn né đòn được khi lượng HP xuống thấp.

    8010d278: andi $v0, 0x003f

    8010d27c: j 0x043571

    Hằng số theo sau lệnh J (jump) trong ngôn ngữ MIPS không phải là địa chỉ tuyệt đối mà CPU sẽ nhảy tới, mà là số lượng câu lệnh mà nó sẽ bỏ qua để tới địa chỉ thực thi tiếp theo. Do mỗi câu lệnh của MIPS là 32 bit (tức 4 byte) nên chỉ cần lấy địa chỉ cần nhảy tới chia cho 4 là được giá trị tham số cho lệnh J. Cụ thể ở đây là: 10D5C4/4 = 43571.

    Và kết quả sau khi chỉnh sửa câu lệnh trên thì Erunsth không còn né đòn khi HP xuống thấp nữa, cho nên nhân vật này vẫn trúng đòn, và HP xuống còn zero. Tuy nhiên, game không có phần xử lý cho nhân vật này biến mất khi HP là zero nên dẫn tới hiện tượng như bên dưới.

    [​IMG]

    [​IMG]
    Mặc dù HP là zero nhưng CPU vẫn coi nhân vật này đang tồn tại, vẫn xảy ra hội thoại của nhân vật này sau đó. Bởi mặc định CPU luôn coi nhân vật này không thể chết ở map này. Nếu muốn CPU coi nhân vật này đã chết, xóa hội thoại sau đó thì cần phải can thiệp thêm nhiều vị trí khác. Và dĩ nhiên là việc này sẽ tác động tới các flag liên quan tới event của nhân vật này ở những map sau.

    Và phần can thiệp bên trên chỉ là can thiệp vào memory mang tính nhất thời. Nếu muốn phần code này có hiệu lực vĩnh viễn (hard code) thì cần phải tìm đoạn code trên trong Rom rồi sửa như trên. Phần xử lý HP của nhân vật này nằm ở file B.bin trong CD-ROM, có địa chỉ như bên dưới.

    0001C270 ANDI v0, v0, 0x003F

    0001C274 SLT v0, v0, 0x00

    Đầu tiên là trích xuất file B.bin từ CD-ROM thông qua những phần mềm xử lý CD như CDmage, rồi chỉnh sửa đoạn code trên, compile thành mã máy rồi chèn lại B.bin đã chỉnh sửa vào CD cũng bằng CDmage.

     
    Chỉnh sửa cuối: 29/1/24
    namff thích bài này.
  4. SPC700

    SPC700 Legend of Zelda

    Tham gia ngày:
    1/10/20
    Bài viết:
    1,062
    Thử demake Tear Ring Saga.

     

Chia sẻ trang này