Advertisement
Guest User

Untitled

a guest
May 27th, 2021
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. "use strict";
  2.  
  3. // Imports
  4.  
  5. const fs = require('fs')
  6. const PNG = require("pngjs").PNG;
  7.  
  8. // Declare Paths
  9.  
  10. const DAT_PATH = '/home/pi/Documents/mml2data/DAT';
  11. const COMMON_PATH = '/home/pi/Documents/mml2data/COMMON';
  12. const OUT_PATH = '/home/pi/Documents/out';
  13.  
  14. // Constants
  15.  
  16. const PAL_TYPE = 0x02;
  17. const TIM_TYPE = 0x03;
  18. const EBD_TYPE = 0x0A;
  19.  
  20. // Characters (EBD)
  21.  
  22. fs.readdirSync(DAT_PATH).forEach(name => {
  23.  
  24. let file = fs.readFileSync(`${DAT_PATH}/${name}`);
  25. let type = file.readUInt32LE(0x00);
  26. if(type !== EBD_TYPE) {
  27. return;
  28. }
  29.  
  30. let len = file.readUInt32LE(0x04);
  31. let ebd = file.subarray(0x30, len + 0x30);
  32. let stub = name.substr(0, 4);
  33.  
  34. let dir = `${OUT_PATH}/${stub}`;
  35. if(!fs.existsSync(dir)) {
  36. fs.mkdirSync(dir);
  37. }
  38.  
  39. fs.writeFileSync(`${dir}/entities.ebd`, ebd);
  40.  
  41. });
  42.  
  43. // Textures (TIM)
  44.  
  45. console.log('Scanning for textures');
  46.  
  47. fs.readdirSync(DAT_PATH).forEach(name => {
  48.  
  49. let file = fs.readFileSync(`${DAT_PATH}/${name}`);
  50.  
  51. for(let ofs = 0; ofs < file.length; ofs += 0x400) {
  52. let type = file.readUInt32LE(ofs);
  53. if(type !== TIM_TYPE) {
  54. continue;
  55. }
  56.  
  57. let str = ofs.toString(16);
  58. while(str.length < 6) {
  59. str = '0' + str;
  60. }
  61.  
  62.  
  63. const header = {
  64. name : '0x' + str,
  65. stub : name.substr(0, 4),
  66. decompressed_size : file.readUInt16LE(ofs + 0x04),
  67. palette_x : file.readUInt16LE(ofs + 0x0c),
  68. palette_y : file.readUInt16LE(ofs + 0x0e),
  69. palette_size : file.readUInt16LE(ofs + 0x10),
  70. palette_count : file.readUInt16LE(ofs + 0x12),
  71. image_x : file.readUInt16LE(ofs + 0x14),
  72. image_y : file.readUInt16LE(ofs + 0x16),
  73. width : file.readUInt16LE(ofs + 0x18) * 2,
  74. height : file.readUInt16LE(ofs + 0x1a),
  75. bitfield_size : file.readUInt16LE(ofs + 0x24),
  76. bits_per_pixel : 8
  77. }
  78.  
  79. if(header.width > 256) {
  80. continue;
  81. }
  82.  
  83. if(header.height > 256) {
  84. continue;
  85. }
  86.  
  87. if(header.palette_size > 256) {
  88. continue;
  89. }
  90.  
  91. console.log();
  92. console.log('Reading File: %s', name);
  93. console.log('Found TIM file at offset: 0x%s', str);
  94. console.log(header);
  95.  
  96. if(header.palette_size < 256) {
  97. let count = header.palette_size / 16;
  98. header.palette_size = 16;
  99. header.palette_count = count;
  100. }
  101.  
  102. if(header.palette_size === 16) {
  103. header.width *= 2;
  104. header.bits_per_pixel = 4;
  105. }
  106.  
  107. // Copy the bitfield
  108.  
  109. let tmp = ofs + 0x30;
  110. const bitfield = file.subarray(tmp, tmp + header.bitfield_size);
  111. tmp += header.bitfield_size;
  112.  
  113. // Decompress
  114.  
  115. let bits = readBits(bitfield);
  116. let payload = decompress(file, tmp, bits, header)
  117.  
  118. // Render the texture
  119.  
  120. renderImage(header, payload);
  121.  
  122. }
  123.  
  124. });
  125.  
  126. function readBits(buffer) {
  127.  
  128. let bits = [];
  129. for(let ofs = 0; ofs < buffer.length; ofs += 4) {
  130. let val = buffer.readUInt32LE(ofs);
  131. for(let i = 31; i >= 0; i--) {
  132. let bit = 1 << i;
  133. bits.push(val & bit ? 1 : 0);
  134. }
  135. }
  136. return bits;
  137.  
  138. }
  139.  
  140.  
  141. function decompress(file, ofs, bits, header) {
  142.  
  143. let out_ofs = 0;
  144. let window_ofs = 0;
  145. let buffer = Buffer.alloc(header.decompressed_size);
  146.  
  147. for(let i = 0; i < bits.length; i++) {
  148.  
  149. let bit = bits[i];
  150. let word = file.readUInt16LE(ofs);
  151. ofs += 2;
  152.  
  153. if(bit === 0) {
  154. buffer.writeUInt16LE(word, out_ofs);
  155. out_ofs += 2;
  156. } else if(word === 0xffff) {
  157. window_ofs += 0x2000;
  158. } else {
  159. let val = ((word >> 3) & 0x1fff);
  160. let copy_from = window_ofs + val;
  161. let copy_len = (word & 0x07) + 2;
  162. while(copy_len--) {
  163. let w = buffer.readUInt16LE(copy_from);
  164. copy_from += 2;
  165. buffer.writeUInt16LE(w, out_ofs);
  166. out_ofs += 2;
  167. }
  168. }
  169.  
  170. if(out_ofs >= buffer.length) {
  171. break;
  172. }
  173.  
  174. if(window_ofs > buffer.length) {
  175. break;
  176. }
  177.  
  178. }
  179.  
  180. return buffer;
  181. }
  182.  
  183. function renderImage(header, payload) {
  184.  
  185. let png = new PNG({
  186. width : header.width,
  187. height : header.height
  188. });
  189.  
  190. // First we read the palette
  191.  
  192. let palette = [];
  193.  
  194. let ofs = 0;
  195.  
  196. for(let p = 0; p < header.palette_count; p++) {
  197.  
  198. let pal = [];
  199. let bits = 0;
  200.  
  201. for(let i = 0; i < header.palette_size; i++) {
  202. let color = payload.readUInt16LE(ofs);
  203. ofs += 2;
  204. bits |= color;
  205.  
  206. pal[i] = {
  207. r : ((color >> 0x00) & 0x1f) << 3,
  208. g : ((color >> 0x05) & 0x1f) << 3,
  209. b : ((color >> 0x0a) & 0x1f) << 3,
  210. a : color > 0 ? 255 : 0
  211. };
  212.  
  213. }
  214.  
  215. if(!bits) {
  216. continue;
  217. }
  218.  
  219. palette.push(pal);
  220.  
  221. }
  222.  
  223. let image_body = [];
  224. while(ofs < payload.length) {
  225. let byte = payload.readUInt8(ofs++);
  226.  
  227. switch(header.bits_per_pixel) {
  228. case 4:
  229. image_body.push(byte & 0xf);
  230. image_body.push(byte >> 4);
  231. break;
  232. case 8:
  233. image_body.push(byte);
  234. break;
  235. }
  236. }
  237.  
  238. console.log(header);
  239. console.log(palette);
  240.  
  241. for(let p = 0; p < palette.length; p++) {
  242.  
  243. let pal = palette[p];
  244.  
  245. for(let y = 0; y < header.height; y++) {
  246. for(let x = 0; x < header.width; x++) {
  247.  
  248. let i = header.width * y + x;
  249. let color = pal[image_body[i]]
  250.  
  251. if(!color) {
  252. console.log("Error, stopping");
  253. console.log(i);
  254. console.log(color);
  255. console.log(pal);
  256. console.log(image_body);
  257. process.exit();
  258. }
  259.  
  260. let idx = i * 4;
  261.  
  262. png.data[idx + 0] = color.r;
  263. png.data[idx + 1] = color.g;
  264. png.data[idx + 2] = color.b;
  265. png.data[idx + 3] = color.a;
  266. }
  267. }
  268.  
  269. let dir = `${OUT_PATH}/${header.stub}`;
  270. if(!fs.existsSync(dir)) {
  271. fs.mkdirSync(dir);
  272. }
  273.  
  274. let buffer = PNG.sync.write(png);
  275. fs.writeFileSync(`${dir}/${header.name}_${p}.png`, buffer);
  276.  
  277. }
  278.  
  279.  
  280. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement