iigs-game-engine/tools/tiled2iigs.js
2021-08-06 16:35:47 -05:00

92 lines
2.7 KiB
JavaScript

/**
* Read an exported Tiled project in JSON format and produce Merlin32 output files with
* GTE-compatible setup code wrapped around it.
*/
const fs = require('fs').promises;
const process = require('process');
const { Buffer } = require('buffer');
main(process.argv.slice(2)).then(
() => process.exit(0),
(e) => {
console.error(e);
process.exit(1);
}
);
function emitHeader() {
console.log('; Tiled Map Export');
console.log(';');
console.log('; This is a generated file. Do not modify.');
}
async function main(argv) {
// Read in the JSON data
const doc = JSON.parse(await fs.readFile(argv[0]));
// Make sure it's a map format we can handle
if (doc.infinite) {
throw new Error('Cannot import infinite maps.');
}
// Require 8x8 tiles
if (doc.tileheight !== 8 || doc.tilewidth !== 8) {
throw new Error('Only 8x8 tiles are supported');
}
// The total map size must be less than 32768 tiles because we limit the map to one data bank
// and the tiles are stored in GTE as 16-bit values.
if (doc.height * doc.width >= 32768) {
throw new Error('The tile map must have less than 32,768 tiles');
}
// Look at the tile layers. We support a maximum of two tile layers.
const tileLayers = doc.layers.filter(l => l.type === 'tilelayer');
if (tileLayers.length === 0) {
throw new Error('There must be at least one tile layer defined for the map');
}
if (tileLayers.length > 2) {
throw new Error('The map cannot have more than two tile layers');
}
// Sort the tile layers by ID. The lower ID is considered to be the "front" layer
tileLayers.sort((first, second) => first.id <= second.id);
// Ok, looks good. Write out the source code
emitHeader();
emitBG0Layer(tileLayers[0]);
if (tileLayers.length > 1) {
emigBG1Layer(tileLayers[1]);
}
}
function emitBG0Layer(layer) {
const label = layer.name.split(' ').join('_');
const initCode = `
BG0SetUp
lda #${layer.width}
sta TileMapWidth
lda #${layer.height}
sta TileMapHeight
lda #${label}
sta TileMapPtr
lda #^${label}
sta TileMapPtr+2
rts
`;
console.log(initCode);
console.log(`${label}`);
// Print out the data in groups of N
const N = 16;
const chunks = [];
const tileIDs = layer.data;
for (let i = 0; i < tileIDs.length; i += N) {
chunks.push(tileIDs.slice(i, i + N))
}
// Tiled starts numbering its tiles at 1, swtich to a more sane approach... :)
for (const chunk of chunks) {
console.log(' dw ' + chunk.map(t => t - 1).join(','));
}
}