Advertisement
Guest User

Untitled

a guest
May 29th, 2021
20
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.64 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. console.log('Scanning for Actor Models');
  23.  
  24. fs.readdirSync(DAT_PATH).forEach(name => {
  25.  
  26. let file = fs.readFileSync(`${DAT_PATH}/${name}`);
  27. let type = file.readUInt32LE(0x00);
  28. if(type !== EBD_TYPE) {
  29. return;
  30. }
  31.  
  32. let len = file.readUInt32LE(0x04);
  33. let ebd = file.subarray(0x30, len + 0x30);
  34. let stub = name.substr(0, 4);
  35.  
  36. let dir = `${OUT_PATH}/${stub}`;
  37. if(!fs.existsSync(dir)) {
  38. fs.mkdirSync(dir);
  39. }
  40.  
  41. fs.writeFileSync(`${dir}/entities.ebd`, ebd);
  42.  
  43. });
  44.  
  45. /*
  46.  
  47. // Textures (TIM)
  48.  
  49. console.log('Scanning for Textures');
  50.  
  51. fs.readdirSync(DAT_PATH).forEach(name => {
  52.  
  53. let file = fs.readFileSync(`${DAT_PATH}/${name}`);
  54.  
  55. console.log();
  56. console.log(name);
  57.  
  58. for(let ofs = 0; ofs < file.length; ofs += 0x400) {
  59. let type = file.readUInt32LE(ofs);
  60. if(type !== TIM_TYPE) {
  61. continue;
  62. }
  63.  
  64. let str = ofs.toString(16);
  65. while(str.length < 6) {
  66. str = '0' + str;
  67. }
  68.  
  69. const header = {
  70. name : '0x' + str,
  71. stub : name.substr(0, 4),
  72. decompressed_size : file.readUInt16LE(ofs + 0x04),
  73. palette_x : file.readUInt16LE(ofs + 0x0c),
  74. palette_y : file.readUInt16LE(ofs + 0x0e),
  75. palette_size : file.readUInt16LE(ofs + 0x10),
  76. palette_count : file.readUInt16LE(ofs + 0x12),
  77. image_x : file.readUInt16LE(ofs + 0x14),
  78. image_y : file.readUInt16LE(ofs + 0x16),
  79. width : file.readUInt16LE(ofs + 0x18) * 2,
  80. height : file.readUInt16LE(ofs + 0x1a),
  81. bitfield_size : file.readUInt16LE(ofs + 0x24),
  82. bits_per_pixel : 8,
  83. skip : false
  84. }
  85.  
  86. if(header.width > 256 || !header.width) {
  87. continue;
  88. }
  89.  
  90. if(header.height > 256 || !header.height) {
  91. continue;
  92. }
  93.  
  94. if(header.palette_size > 256) {
  95. continue;
  96. }
  97.  
  98. console.log('Found TIM file at offset: 0x%s', str);
  99.  
  100. if(header.palette_size < 256 && header.palette_size > 16) {
  101. let count = header.palette_size / 16;
  102. header.palette_size = 16;
  103. header.palette_count = count;
  104. header.skip = true;
  105. }
  106.  
  107. if(header.palette_size === 16) {
  108. header.width *= 2;
  109. header.bits_per_pixel = 4;
  110. }
  111.  
  112. // Copy the bitfield
  113.  
  114. let tmp = ofs + 0x30;
  115. const bitfield = file.subarray(tmp, tmp + header.bitfield_size);
  116. tmp += header.bitfield_size;
  117.  
  118. // Decompress
  119.  
  120. let bits = readBits(bitfield);
  121. let payload = decompress(file, tmp, bits, header)
  122.  
  123. // Render the texture
  124.  
  125. renderImage(header, payload);
  126.  
  127. }
  128.  
  129. });
  130.  
  131.  
  132. // Scan for Palettes
  133.  
  134. console.log('Scanning for palettes');
  135.  
  136. fs.readdirSync(DAT_PATH).forEach(name => {
  137.  
  138. let file = fs.readFileSync(`${DAT_PATH}/${name}`);
  139.  
  140. console.log();
  141. console.log(name);
  142.  
  143. for(let ofs = 0; ofs < file.length; ofs += 0x400) {
  144. let type = file.readUInt32LE(ofs);
  145. if(type !== PAL_TYPE) {
  146. continue;
  147. }
  148.  
  149. let str = ofs.toString(16);
  150. while(str.length < 6) {
  151. str = '0' + str;
  152. }
  153.  
  154. console.log('Found PAL at: 0x%s', str);
  155.  
  156. const header = {
  157. name : '0x' + str,
  158. stub : name.substr(0, 4),
  159. palette_size : file.readUInt16LE(ofs + 0x04),
  160. palette_x : file.readUInt16LE(ofs + 0x0c),
  161. palette_y : file.readUInt16LE(ofs + 0x0e),
  162. palette_size : file.readUInt16LE(ofs + 0x10),
  163. palette_count : file.readUInt16LE(ofs + 0x12),
  164. image_x : file.readUInt16LE(ofs + 0x14),
  165. image_y : file.readUInt16LE(ofs + 0x16),
  166. width : file.readUInt16LE(ofs + 0x18) * 2,
  167. height : file.readUInt16LE(ofs + 0x1a),
  168. skip : false
  169. }
  170.  
  171. if(header.image_x) {
  172. continue;
  173. }
  174.  
  175. if(header.image_y) {
  176. continue;
  177. }
  178.  
  179. if(header.width) {
  180. continue;
  181. }
  182.  
  183. if(header.height) {
  184. continue;
  185. }
  186.  
  187. if(header.palette_size < 256 && header.palette_size > 16) {
  188. let count = header.palette_size / 16;
  189. header.palette_size = 16;
  190. header.palette_count = count;
  191. header.skip = true;
  192. }
  193.  
  194. let tmp = ofs + 0x30;
  195. for(let i = 0; i < header.palette_count; i++) {
  196.  
  197. let pal = [];
  198. let bits = 0;
  199.  
  200. for(let i = 0; i < header.palette_size; i++) {
  201. let color = file.readUInt16LE(tmp);
  202. tmp += 2;
  203. bits |= color;
  204.  
  205. pal[i] = {
  206. r : ((color >> 0x00) & 0x1f) << 3,
  207. g : ((color >> 0x05) & 0x1f) << 3,
  208. b : ((color >> 0x0a) & 0x1f) << 3,
  209. a : color > 0 ? 255 : 0
  210. };
  211.  
  212. }
  213.  
  214. if(!bits) {
  215. continue;
  216. }
  217.  
  218. if(i && header.skip) {
  219. continue;
  220. }
  221.  
  222. let png = new PNG({
  223. width : 256,
  224. height : 256
  225. });
  226.  
  227. for(let y = 0; y < 256; y++) {
  228. for(let x = 0; x < 256; x++) {
  229.  
  230. let a = Math.floor(y / 64);
  231. let b = Math.floor(x / 64);
  232.  
  233. let clr = a*4 + b;
  234. let color = pal[a*4 + b];
  235.  
  236. let i = 256 * y + x;
  237. let idx = i * 4;
  238.  
  239. png.data[idx + 0] = color.r;
  240. png.data[idx + 1] = color.g;
  241. png.data[idx + 2] = color.b;
  242. png.data[idx + 3] = color.a;
  243. }
  244. }
  245.  
  246. let dir = `${OUT_PATH}/${header.stub}`;
  247. if(!fs.existsSync(dir)) {
  248. fs.mkdirSync(dir);
  249. }
  250.  
  251. let buffer = PNG.sync.write(png);
  252. fs.writeFileSync(`${dir}/${header.name}_${i}.png`, buffer);
  253.  
  254. }
  255.  
  256. }
  257.  
  258. });
  259.  
  260. */
  261.  
  262. console.log('Looking for map stuff');
  263.  
  264. fs.readdirSync(DAT_PATH).forEach(name => {
  265.  
  266. if(name !== 'ST08.BIN') {
  267. return;
  268. }
  269.  
  270. let file = fs.readFileSync(`${DAT_PATH}/${name}`);
  271.  
  272. let type = file.readUInt32LE(0x00);
  273. if(type !== 0x0d) {
  274. return;
  275. }
  276.  
  277. let header = {
  278. decompressed_size : file.readUInt32LE(0x04)
  279. }
  280.  
  281. let count = file.readUInt32LE(0x08);
  282. let bitfield_size = file.readUInt32LE(0x10);
  283.  
  284. let tmp = 0x30;
  285. const bitfield = file.subarray(tmp, tmp + bitfield_size);
  286. tmp += bitfield_size;
  287.  
  288. // Decompress
  289.  
  290. let bits = readBits(bitfield);
  291. let payload = decompress(file, tmp, bits, header)
  292. fs.writeFileSync('mappy.bin', payload);
  293.  
  294. });
  295.  
  296. // Helper Functions
  297.  
  298. function readBits(buffer) {
  299.  
  300. let bits = [];
  301. for(let ofs = 0; ofs < buffer.length; ofs += 4) {
  302. let val = buffer.readUInt32LE(ofs);
  303. for(let i = 31; i >= 0; i--) {
  304. let bit = 1 << i;
  305. bits.push(val & bit ? 1 : 0);
  306. }
  307. }
  308. return bits;
  309.  
  310. }
  311.  
  312.  
  313. function decompress(file, ofs, bits, header) {
  314.  
  315. let out_ofs = 0;
  316. let window_ofs = 0;
  317. let buffer = Buffer.alloc(header.decompressed_size);
  318.  
  319. for(let i = 0; i < bits.length; i++) {
  320.  
  321. let bit = bits[i];
  322. let word = file.readUInt16LE(ofs);
  323. ofs += 2;
  324.  
  325. if(bit === 0) {
  326. buffer.writeUInt16LE(word, out_ofs);
  327. out_ofs += 2;
  328. } else if(word === 0xffff) {
  329. window_ofs += 0x2000;
  330. } else {
  331. let val = ((word >> 3) & 0x1fff);
  332. let copy_from = window_ofs + val;
  333. let copy_len = (word & 0x07) + 2;
  334. while(copy_len--) {
  335. let w = buffer.readUInt16LE(copy_from);
  336. copy_from += 2;
  337. buffer.writeUInt16LE(w, out_ofs);
  338. out_ofs += 2;
  339. }
  340. }
  341.  
  342. if(out_ofs >= buffer.length) {
  343. break;
  344. }
  345.  
  346. if(window_ofs > buffer.length) {
  347. break;
  348. }
  349.  
  350. }
  351.  
  352. return buffer;
  353. }
  354.  
  355. function renderImage(header, payload) {
  356.  
  357. let png = new PNG({
  358. width : header.width,
  359. height : header.height
  360. });
  361.  
  362. // First we read the palette
  363.  
  364. let palette = [];
  365.  
  366. let ofs = 0;
  367.  
  368. for(let p = 0; p < header.palette_count; p++) {
  369.  
  370. let pal = [];
  371. let bits = 0;
  372.  
  373. for(let i = 0; i < header.palette_size; i++) {
  374. let color = payload.readUInt16LE(ofs);
  375. ofs += 2;
  376. bits |= color;
  377.  
  378. pal[i] = {
  379. r : ((color >> 0x00) & 0x1f) << 3,
  380. g : ((color >> 0x05) & 0x1f) << 3,
  381. b : ((color >> 0x0a) & 0x1f) << 3,
  382. a : color > 0 ? 255 : 0
  383. };
  384.  
  385. }
  386.  
  387. if(!bits) {
  388. continue;
  389. }
  390.  
  391. if(p && header.skip) {
  392. continue;
  393. }
  394.  
  395. palette.push(pal);
  396.  
  397. }
  398.  
  399. let image_body = [];
  400. while(ofs < payload.length) {
  401. let byte = payload.readUInt8(ofs++);
  402.  
  403. switch(header.bits_per_pixel) {
  404. case 4:
  405. image_body.push(byte & 0xf);
  406. image_body.push(byte >> 4);
  407. break;
  408. case 8:
  409. image_body.push(byte);
  410. break;
  411. }
  412. }
  413.  
  414. for(let p = 0; p < palette.length; p++) {
  415.  
  416. let pal = palette[p];
  417.  
  418. for(let y = 0; y < header.height; y++) {
  419. for(let x = 0; x < header.width; x++) {
  420. let i = header.width * y + x;
  421. let color = pal[image_body[i]]
  422. let idx = i * 4;
  423.  
  424. png.data[idx + 0] = color.r;
  425. png.data[idx + 1] = color.g;
  426. png.data[idx + 2] = color.b;
  427. png.data[idx + 3] = color.a;
  428. }
  429. }
  430.  
  431. let dir = `${OUT_PATH}/${header.stub}`;
  432. if(!fs.existsSync(dir)) {
  433. fs.mkdirSync(dir);
  434. }
  435.  
  436. let buffer = PNG.sync.write(png);
  437. fs.writeFileSync(`${dir}/${header.name}_${p}.png`, buffer);
  438.  
  439. }
  440.  
  441.  
  442. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement