Advertisement
Zoinkity

PoC Mario Kart Texture Replacement

Aug 16th, 2015
619
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.29 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. # order is:
  4. #  offset to 0x50 resource virtual addresses
  5. #  offset to resource entry tables
  6. #  offset to uncompressed root files
  7. #  offset to compressed root files
  8. #  pairs for start of first file
  9. #  pairs for start of second file (and end of first)
  10. #  pairs for start of third file (and end of second)
  11. #  pairs for start of fourth file (and end of third)
  12. #  pairs for root table
  13. #  pairs for resource table
  14. #  pairs for whatever the float table is
  15. #  pairs for bank 0A
  16. #  pairs for bank 0B (TKMK)
  17. #  pairs for ???
  18. #  pairs for ???
  19. #  pairs for end of ??? / start of first offsets in res. tbl. entries
  20. #  pairs for start of res. tbl. entry 4's first offset
  21. #  pairs for end of res. tbl. entry 4's first offset
  22. #  pairs for sound.ctl
  23. #  pairs for sound.tbl
  24. #  pairs of hardcoded resource virtual addresses
  25. NKTE = (0xE60D0,
  26.      0x2AE80,
  27.      0xDE7F4,
  28.      0xDEAC0,
  29.     ((0x1CF0, 0x1CF8),),
  30.     ((0x1C78, 0x1C80),
  31.      (0x1CF4, 0x1CFC),),
  32.     ((0x1C7C, 0x1C84),
  33.      (0x1F10, 0x1F20),),
  34.     ((0x1F14, 0x1F18),
  35.      (0x1F30, 0x1F3C),),
  36.     ((0x1F34, 0x1F38),
  37.      (0x5B2C, 0x5B28),
  38.      (0x27DB8, 0x27DBC),
  39.      (0x27EC4, 0x27EC8),
  40.      (0x27FDC, 0x27FE0),
  41.      (0x28100, 0x28104),
  42.      (0x282D8, 0x282DC),
  43.      (0x283CC, 0x283D0),
  44.      (0x284CC, 0x284D0),
  45.      (0x285D8, 0x285DC),
  46.      (0x286C0, 0x286D8),
  47.      (0x28768, 0x28780),
  48.      (0x28814, 0x28820),
  49.      (0x288AC, 0x288B8),),
  50.     ((0x6F9D4, 0x6F9E0),
  51.      (0x75190, 0x7519C),
  52.      (0x1119A8, 0x1119B4),
  53.      (0x111A80, 0x111A8C),
  54.      (0x111B58, 0x111B64),
  55.      (0x111C34, 0x111C40),),
  56.     ((0x1ED0, 0x1EDC),),
  57.     ((0x99C30, 0x99C3C),
  58.      (0x9A7C4, 0x9A7CC),
  59.      (0x9AB78, 0x9AB80),),
  60.     ((0x99CB8, 0x99CC4),),
  61.     ((0x123B20, 0x123B2C),
  62.      (0x125080, 0x12508C),),
  63.     ((0x9280C, 0x92818),
  64.      (0x123B24, 0x123B28),
  65.      (0x125084, 0x125088),),
  66.     ((0x92810, 0x92814),),
  67.     ((0x1250A4, 0x1250B4),),
  68.     ((0x1250A8, 0x1250AC),),
  69.     ((0xBCFE0, 0xBCFEC),),
  70.     ((0xBD0D4, 0xBD0D8),),
  71.     ((0xBCF64, 0xBCF68),),
  72.     ((0xBD150, 0xBD158),),
  73.     ((0x107970, 0x107974),
  74.      (0x107984, 0x107988),
  75.      (0x107780, 0x107784),
  76.      (0x107798, 0x1077A0),
  77.      (0x1077B0, 0x1077B4),
  78.      (0x1077C4, 0x1077C8),
  79.      (0x1077D8, 0x1077DC),
  80.      (0x1077EC, 0x1077F0),
  81.      (0x107800, 0x107804),
  82.      (0x107814, 0x107818),
  83.      (0x107828, 0x10782C),
  84.      (0x107840, 0x107848),
  85.      (0x107858, 0x10785C),
  86.      (0x10786C, 0x107870),
  87.      (0x107880, 0x107884),
  88.      (0x107894, 0x107898),
  89.      (0x1078A8, 0x1078AC),
  90.      (0x1078BC, 0x1078C0),
  91.      (0x3D10, 0x3D14),
  92.      (0x1079C0, 0x1079C4),
  93.      (0x107AB4, 0x107AB8),
  94.      (0x107B00, 0x107B04),
  95.      (0x3DCC, 0x3DD0),
  96.      (0x107C1C, 0x107C20),
  97.      (0x3DE0, 0x3DE4),
  98.      (0x107C30, 0x107C34),
  99.      (0x107BEC, 0x107BF0),
  100.      (0x107C00, 0x107C04),
  101.      (0x107B14, 0x107B18),
  102.      (0x107A98, 0x107A9C),
  103.      (0x107AD0, 0x107AD4),
  104.      (0x107AE4, 0x107AE8),
  105.      (0x3DF4, 0x3DF8),
  106.      (0x107C44, 0x107C48),
  107.      (0x3E08, 0x3E0C),
  108.      (0x107C58, 0x107C5C),
  109.      (0x3E1C, 0x3E20),
  110.      (0x107C6C, 0x107C70),
  111.      (0x3E30, 0x3E34),
  112.      (0x107C80, 0x107C84),
  113.      (0x3E44, 0x3E48),
  114.      (0x107C94, 0x107C98),
  115.      (0x3E58, 0x3E5C),
  116.      (0x107CA8, 0x107CAC),
  117.      (0x3E6C, 0x3E70),
  118.      (0x107CBC, 0x107CC0),
  119.      (0x3E80, 0x3E84),
  120.      (0x107CD0, 0x107CD4),
  121.      (0x3E94, 0x3E98),
  122.      (0x107CE4, 0x107CE8),
  123.      (0x3EA8, 0x3EAC),
  124.      (0x107CF8, 0x107CFC),
  125.      (0x107D14, 0x107D18),
  126.      (0x107D28, 0x107D2C),
  127.      (0x107D3C, 0x107D40),
  128.      (0x107D50, 0x107D54),
  129.      (0x107D64, 0x107D68),
  130.      (0x1078D0, 0x1078D4),
  131.      (0x1078E4, 0x1078E8),
  132.      (0x1078F8, 0x1078FC),
  133.      (0x10790C, 0x107910),
  134.      (0x107920, 0x107924),
  135.      (0x107934, 0x107938),
  136.      (0x107948, 0x10794C),
  137.      (0x10795C, 0x107960),
  138.      (0x1079D4, 0x1079D8),
  139.      (0x107B28, 0x107B2C),
  140.      (0x1079EC, 0x1079F4),
  141.      (0x107B40, 0x107B48),
  142.      (0x107A04, 0x107A08),
  143.      (0x107B58, 0x107B5C),
  144.      (0x107A18, 0x107A1C),
  145.      (0x107B6C, 0x107B70),
  146.      (0x107A2C, 0x107A30),
  147.      (0x107B80, 0x107B84),
  148.      (0x107A40, 0x107A44),
  149.      (0x107B94, 0x107B98),
  150.      (0x107A54, 0x107A58),
  151.      (0x107BA8, 0x107BAC),
  152.      (0x107A68, 0x107A6C),
  153.      (0x107BBC, 0x107BC0),
  154.      (0x107A7C, 0x107A80),
  155.      (0x107BD0, 0x107BD4),
  156.      (0x107D80, 0x107D84),
  157.      (0x107D94, 0x107D98),
  158.      (0x107DA8, 0x107DAC),
  159.      (0x5DEB0, 0x5DEB8),
  160.      (0x5DECC, 0x5DED4),
  161.      (0x5DEE8, 0x5DEF0),
  162.      (0x5DFA0, 0x5DFA4),
  163.      (0x5DF3C, 0x5DF44),
  164.      (0x5DF20, 0x5DF28),
  165.      (0x5E010, 0x5E018),
  166.      (0x5DF04, 0x5DF0C),
  167.      (0x5DF58, 0x5DF60),
  168.      (0x5DF74, 0x5DF7C),
  169.      (0x5DE98, 0x5DE9C),
  170.      (0x5DFF4, 0x5DFFC),
  171.      (0x5E0D4, 0x5E0DC),
  172.      (0x5E0F0, 0x5E0F8),
  173.      (0x5E10C, 0x5E114),
  174.      (0x5E128, 0x5E130),
  175.      (0x5E144, 0x5E14C),
  176.      (0x5E160, 0x5E168),
  177.      (0x5E17C, 0x5E184),
  178.      (0x5E198, 0x5E1A0),
  179.      (0x5E1B4, 0x5E1BC),
  180.      (0x5E1D0, 0x5E1D8),
  181.      (0x5E1EC, 0x5E1F4),
  182.      (0x5E208, 0x5E210),
  183.      (0x5E224, 0x5E22C),
  184.      (0x5E240, 0x5E248),
  185.      (0x5E25C, 0x5E264),
  186.      (0x5E09C, 0x5E0A4),
  187.      (0x5E0B8, 0x5E0C0),
  188.      (0x5E064, 0x5E06C),
  189.      (0x5E080, 0x5E088),
  190.      (0x5E02C, 0x5E034),
  191.      (0x5E048, 0x5E050),
  192.      (0x5DFBC, 0x5DFC4),
  193.      (0x5DFD8, 0x5DFE0),
  194.      (0x5E278, 0x5E280),
  195.      (0x5E294, 0x5E29C),
  196.      (0x79EFC, 0x79F08),
  197.      (0x7A254, 0x7A260),
  198.      (0x7AC78, 0x7AC84),
  199.      (0x7AE40, 0x7AE4C),
  200.      (0x7B00C, 0x7B018),
  201.      (0x7A5C4, 0x7A5D0),
  202.      (0x6FDE4, 0x6FDE8),
  203.      (0x7DA1C, 0x7DA30),
  204.      (0x6FE48, 0x6FE4C),
  205.      (0x70070, 0x70074),
  206.      (0x70178, 0x7017C),
  207.      (0x6FFE8, 0x6FFEC),
  208.      (0x6FEFC, 0x6FF00),
  209.      (0x6FF60, 0x6FF64),
  210.      (0x6FCE4, 0x6FCE8),
  211.      (0x70114, 0x70120),
  212.      (0x6FA4C, 0x6FA58),)
  213.     )
  214.  
  215. # Format: filename, old entry, size replaced.
  216. edits = (("-hi1.NKTJ.mio", (0xF04B420, 0x4A1, 0x1000, 0), 0x4A4),
  217.     ("Yos-.NKTJ.mio", (0xF04AF40, 0x4DF, 0x1000, 0), 0x4E0),
  218.     ("-endo.NKTJ.mio", (0xF02C3A0, 0x2F7, 0x1000, 0), 0x2F8),
  219.     ("Ninte-.NKTJ.mio", (0xF02C0F8, 0x2A6, 0x1000, 0), 0x2A8),
  220.     ("-oro.NKTJ.mio", (0xF02A584, 0x2B1, 0x1000, 0), 0x2B4),
  221.     ("Mario-.NKTJ.mio", (0xF02A2B0, 0x2D2, 0x1000, 0), 0x2D4),
  222.     ("-igip.NKTJ.mio", (0xF02A000, 0x2AF, 0x1000, 0), 0x2B0),
  223.     ("Lu-.NKTJ.mio", (0xF029D78, 0x287, 0x1000, 0), 0x288),
  224.     ("-a_Air.NKTJ.mio", (0xF022D40, 0x304, 0x1000, 0), 0x304),
  225.     ("Koop-.NKTJ.mio", (0xF0229E0, 0x360, 0x1000, 0), 0x360),
  226.     ("64.NKTJ.mio", (0xF000B18, 0x567, 0x1000, 0), 0x568),
  227.      )
  228.  
  229. def main():
  230.     """This is buggered to just do the file insertion and fix the offsets."""
  231.     import N64
  232.     from struct import Struct
  233.     resentry = Struct(">12L")
  234.     helpo = Struct(">4L")
  235.     statictbl = Struct(">20L")
  236.  
  237.     with open(r"Mario Kart 64 (U) [!].z64", 'rb') as f:
  238.         cart = N64.Cart(f.read())
  239.     # Get a list of the original locations.
  240.     i = cart.ID
  241.     name = "{}{}{}{}".format(i.frmt, i.name, i.region, '' if not i.version else str(i.version))
  242.     ##tbl = MK64.get(name, None)
  243.     tbl = NKTE
  244.     if not tbl:
  245.         raise NotImplementedError("%s is not supported!" % name)
  246.     # Use any entry in tbl[9] to pull offset to resource table in order to calculate correction.
  247.     for i in edits:
  248.         with open(i[0], 'rb') as f:
  249.             data = f.read()
  250.         orgv = i[1][0]
  251.         orgp = (orgv & 0xFFFFFF) + cart.getASMvalue(tbl[9][0][0], tbl[9][0][1])
  252.         sz = i[1][1]
  253.         sz += 3
  254.         sz &= ~3
  255.         l = len(data)
  256.         padding = (4 - (l&3)) & 3
  257.         correct = l + padding - sz
  258.         new = (orgv, l, int.from_bytes(data[4:8], 'big') if data[0:4] == b'MIO0' else l+padding, 0)
  259.         # walk through and update resource entries.
  260.         # Use tbl[1] to pull the resource entries from first file.
  261.         p = tbl[1] + cart.getASMvalue(tbl[4][0][0], tbl[4][0][1])
  262.         while True:
  263.             v = list(resentry.unpack_from(cart.rom, p))
  264.             if not v[0]:
  265.                 break
  266.             for k in range(v[4], v[5], 16):
  267.                 e = helpo.unpack_from(cart.rom, k)
  268.                 if not e[0]:
  269.                     break
  270.                 if e == i[1]:
  271.                     helpo.pack_into(cart.rom, k, *new)
  272.                 elif e[0] > orgv:
  273.                     helpo.pack_into(cart.rom, k, e[0]+correct, e[1], e[2], e[3])
  274.             # After fiddling with tables, update the entry and write it back.
  275.             for k in range(6):
  276.                 if v[k] > orgp:
  277.                     v[k] += correct
  278.             resentry.pack_into(cart.rom, p, *v)
  279.             p += 48
  280.         # tbls 9, 10, 11, 12, 13, 14, 15 get pushed around
  281.         for k in range(4, len(tbl)-1):
  282.             for j in tbl[k]:
  283.                 v = cart.getASMvalue(j[0], j[1])
  284.                 if v <= orgp:
  285.                     break
  286.                 v += correct
  287.                 cart.setASMvalue(v, j[0], j[1])
  288.         for j in tbl[-1]:
  289.             v = cart.getASMvalue(j[0], j[1])
  290.             if v > orgv:
  291.                 v += correct
  292.                 cart.setASMvalue(v, j[0], j[1])
  293.         v = list(statictbl.unpack_from(cart.rom, tbl[0]))
  294.         for j in range(len(v)):
  295.             if v[j] > orgv:
  296.                 v[j] += correct
  297.         statictbl.pack_into(cart.rom, tbl[0], *v)
  298.         # Now replace the file.
  299.         cart.rom[orgp:orgp+i[2]] = data + bytes(padding)
  300.     cart.calccrc(fix=True)
  301.     with open("hacked.n64", 'wb') as f:
  302.         f.write(cart.rom)
  303.  
  304. if __name__ == '__main__':
  305.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement