py3devil1tex.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import ctypes
  2. import os, sys
  3. sys.path.append(
  4. os.path.abspath(
  5. os.path.join(
  6. os.path.dirname(__file__), "../../")))
  7. from lib3ddevil1.bindings import libc
  8. del os, sys
  9. #--------------------------------------+
  10. # Basic Struct
  11. #--------------------------------------+
  12. class TexturePack(ctypes.Structure):
  13. _pack_ = 1
  14. _fields_ = [
  15. ("id", ctypes.c_char * 4), # fixed length 4, reverse order
  16. ("batchNumber", ctypes.c_int),
  17. ("firstBatchOffset", ctypes.c_int),
  18. ("unknownA", ctypes.c_int)
  19. ]
  20. class TextureBatchDescriptor(ctypes.Structure):
  21. _pack_ = 1
  22. _fields_ = [
  23. ("batchIdx", ctypes.c_int),
  24. ("hash", ctypes.c_int),
  25. ("texNumber", ctypes.c_int),
  26. ("unknownA", ctypes.c_int * 8),
  27. ("textureSize", ctypes.c_int),
  28. ("unknownB", ctypes.c_int * 30)
  29. ]
  30. class Texture(ctypes.Structure):
  31. _pack_ = 1
  32. _fields_ = [
  33. ("data", ctypes.POINTER(ctypes.c_ubyte))
  34. ]
  35. class TextureBatch(ctypes.Structure):
  36. _pack_ = 1
  37. _fields_ = [
  38. ("batch", ctypes.POINTER(Texture))
  39. ]
  40. class Devil1TEX_FN(ctypes.Structure):
  41. _fields_ = [
  42. ("printheader", ctypes.CFUNCTYPE(
  43. None,
  44. ctypes.POINTER(TexturePack))),
  45. ("printbatchdesc", ctypes.CFUNCTYPE(
  46. None,
  47. ctypes.POINTER(TextureBatchDescriptor))),
  48. ("getheader", ctypes.CFUNCTYPE(
  49. ctypes.c_bool,
  50. ctypes.POINTER(
  51. ctypes.POINTER(TexturePack)),
  52. ctypes.c_char_p)),
  53. ("getbatchdesc", ctypes.CFUNCTYPE(
  54. ctypes.c_bool,
  55. ctypes.POINTER(
  56. ctypes.POINTER(TextureBatchDescriptor)),
  57. ctypes.c_uint,
  58. ctypes.c_char_p,
  59. ctypes.c_uint)),
  60. ("getbatch", ctypes.CFUNCTYPE(
  61. ctypes.c_bool,
  62. ctypes.POINTER(
  63. ctypes.POINTER(TextureBatch)),
  64. ctypes.c_uint,
  65. ctypes.c_char_p,
  66. ctypes.c_uint)),
  67. ("gettextures", ctypes.CFUNCTYPE(
  68. ctypes.c_bool,
  69. ctypes.POINTER(Texture),
  70. ctypes.c_uint,
  71. ctypes.c_char_p,
  72. ctypes.c_uint))
  73. ]
  74. devil1tex = Devil1TEX_FN.in_dll(libc, "DEVIL1TEX")
  75. del libc
  76. #--------------------------------------+
  77. # Pythonic Object
  78. #--------------------------------------+
  79. class pyTexturePack:
  80. def __init__(self, filedata):
  81. self.cstruct = ctypes.pointer(TexturePack())
  82. if not devil1tex.getheader(ctypes.byref(self.cstruct), filedata):
  83. raise RuntimeError("failed to get texture pack header")
  84. return
  85. def show(self):
  86. devil1tex.printheader(self.cstruct)
  87. def getbatchnumber(self):
  88. return self.cstruct.contents.batchNumber
  89. def getfirstbatchoffset(self):
  90. return self.cstruct.contents.firstBatchOffset
  91. class pyTextureBatchDescriptor:
  92. def __init__(self, i, filedata):
  93. self.cstruct = ctypes.pointer(TextureBatchDescriptor())
  94. ptrofptr = ctypes.byref(self.cstruct)
  95. if filedata:
  96. if not devil1tex.getbatchdesc(
  97. ptrofptr,
  98. i,
  99. filedata,
  100. len(filedata)):
  101. raise RuntimeError("failed to get texturebatchdescriptor #" + str(i))
  102. return
  103. def show(self):
  104. devil1tex.printbatchdesc(self.cstruct)
  105. def getbatchidx(self):
  106. return self.cstruct.contents.batchIdx
  107. def gethash(self):
  108. return self.cstruct.contents.hash
  109. def gettexnumber(self):
  110. return self.cstruct.contents.texNumber
  111. def gettexturesize(self):
  112. return self.cstruct.contents.textureSize
  113. class pyTextureBatch:
  114. def __init__(self, i, filedata):
  115. self.cstruct = TextureBatch()
  116. if filedata:
  117. self.cstruct.batch = None
  118. tbd = pyTextureBatchDescriptor(i, filedata)
  119. self.amount = tbd.gettexnumber()
  120. self.size = tbd.gettexturesize()
  121. memsize = self.amount * self.size
  122. self.cstruct.batch = ctypes.cast(
  123. ctypes.create_string_buffer(memsize),
  124. ctypes.POINTER(Texture))
  125. if not devil1tex.gettextures(
  126. self.cstruct.batch,
  127. i,
  128. filedata,
  129. len(filedata)):
  130. raise RuntimeError("failed to get textures of batch #" + str(i))
  131. return
  132. def gettextures(self):
  133. ptrs = self.cstruct.batch[:self.amount]
  134. textures = []
  135. for ptr in ptrs:
  136. texture = ctypes.cast(ptr.data,
  137. ctypes.POINTER(
  138. ctypes.c_ubyte * self.size))[0]
  139. textures.append(texture)
  140. return textures