Added gbc script I'm never using again
This commit is contained in:
247
scripts/gbc_old.js
Normal file
247
scripts/gbc_old.js
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const { PNG } = require('pngjs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const TRANSPARENT = { r: 0, g: 0, b: 0, a: 0 };
|
||||||
|
const WHITE = { r: 255, g: 255, b : 255, a: 255 };
|
||||||
|
const RED = { r: 255, g: 0, b: 0, a: 255 };
|
||||||
|
|
||||||
|
const TILE_WIDTH = 8;
|
||||||
|
const TILE_HEIGHT = 8;
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
const pixelIsSame = (left, right, alpha) => {
|
||||||
|
if(left.r !== right.r) return false;
|
||||||
|
if(left.g !== right.g) return false;
|
||||||
|
if(left.b !== right.b) return false;
|
||||||
|
if(!alpha) return true;
|
||||||
|
return left.a === right.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageOut = (pixels, width, fileName) => {
|
||||||
|
const png = new PNG({
|
||||||
|
width,
|
||||||
|
height: pixels.length / width
|
||||||
|
});
|
||||||
|
|
||||||
|
pixels.forEach((pixel, i) => {
|
||||||
|
const x = i % width;
|
||||||
|
const y = (i - x) / width;
|
||||||
|
const idx = (width * y + x) << 2;
|
||||||
|
png.data[idx] = pixel.r;
|
||||||
|
png.data[idx+1] = pixel.g;
|
||||||
|
png.data[idx+2] = pixel.b;
|
||||||
|
png.data[idx+3] = pixel.a;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!fs.existsSync('out')) fs.mkdirSync('out');
|
||||||
|
|
||||||
|
const out = PNG.sync.write(png);
|
||||||
|
fs.writeFileSync(path.join('out', fileName), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageIn = fileName => {
|
||||||
|
const data = fs.readFileSync(fileName);
|
||||||
|
const png = PNG.sync.read(data);
|
||||||
|
const pixels = [];
|
||||||
|
|
||||||
|
for(let y = 0; y < png.height; y++) {
|
||||||
|
for (let x = 0; x < png.width; x++) {
|
||||||
|
let idx = (png.width * y + x) << 2;
|
||||||
|
const r = png.data[idx];
|
||||||
|
const g = png.data[idx+1];
|
||||||
|
const b = png.data[idx+2];
|
||||||
|
const a = png.data[idx+3];
|
||||||
|
|
||||||
|
let pixel = { r, g, b, a };
|
||||||
|
if(a === 0) {
|
||||||
|
pixel = { ...WHITE };
|
||||||
|
} else {
|
||||||
|
pixel.a = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.push(pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { pixels, width: png.width, height: png.height };
|
||||||
|
}
|
||||||
|
|
||||||
|
const tileFromPixel = (x, y, original) => {
|
||||||
|
const byEightX = Math.floor(x / 8);
|
||||||
|
const byEightY = Math.floor(y / 8);
|
||||||
|
const byEightWidth = Math.floor(original.width / 8);
|
||||||
|
const byEightId = byEightX + (byEightY * byEightWidth);
|
||||||
|
|
||||||
|
return { x: byEightX, y: byEightY, columns: byEightWidth, id: byEightId };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Input File
|
||||||
|
const original = imageIn('bruh.png');
|
||||||
|
|
||||||
|
const columns = (original.width / TILE_WIDTH);
|
||||||
|
const rows = (original.height / TILE_HEIGHT);
|
||||||
|
|
||||||
|
// Foreach pixel
|
||||||
|
const palette = [];
|
||||||
|
const paletteByEight = [];
|
||||||
|
const withPaletteOverflows = [];
|
||||||
|
|
||||||
|
for(let y = 0; y < original.height; y++) {
|
||||||
|
for(let x = 0; x < original.width; x++) {
|
||||||
|
const id = x + (y * original.width);
|
||||||
|
const pixel = original.pixels[id];
|
||||||
|
let errorPixel = { ...pixel };
|
||||||
|
const tile = tileFromPixel(x, y, original);
|
||||||
|
|
||||||
|
// Handle palettes
|
||||||
|
if(pixel.a != 0) {
|
||||||
|
const pb8 = (paletteByEight[tile.id] = paletteByEight[tile.id] || []);
|
||||||
|
|
||||||
|
if(!pb8.some(p => pixelIsSame(pixel, p))) {
|
||||||
|
pb8.push(pixel);
|
||||||
|
}
|
||||||
|
// Handle palette overflow
|
||||||
|
if(pb8.length > 4) errorPixel = { ...RED };
|
||||||
|
|
||||||
|
// Append to palette
|
||||||
|
if(!palette.some(p => pixelIsSame(pixel, p))) palette.push(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
withPaletteOverflows.push(errorPixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the palette set image
|
||||||
|
const outPaletteByEight = [];
|
||||||
|
let outByEightWidth = 1;
|
||||||
|
paletteByEight.forEach((pal,y) => {
|
||||||
|
pal.forEach((p,x) => {
|
||||||
|
outByEightWidth = Math.max(outByEightWidth, x+1);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
paletteByEight.forEach((pal,y) => {
|
||||||
|
for(let x = 0; x < outByEightWidth; x++) {
|
||||||
|
outPaletteByEight.push(x >= pal.length ? TRANSPARENT : pal[x]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now determine for each TILE what palette to use.
|
||||||
|
const paletteGroups = [];
|
||||||
|
const gbVersion = [];
|
||||||
|
const paletteImage = [];
|
||||||
|
|
||||||
|
for(let y = 0; y < original.height; y++) {
|
||||||
|
for(let x = 0; x < original.width; x++) {
|
||||||
|
const id = x + (y * original.width);
|
||||||
|
const pixel = original.pixels[id];
|
||||||
|
const tile = tileFromPixel(x, y, original);
|
||||||
|
|
||||||
|
// Get the palette
|
||||||
|
const paletteSet = paletteByEight[tile.id];
|
||||||
|
|
||||||
|
// Check for matching
|
||||||
|
let palId = paletteGroups.findIndex(pg => {
|
||||||
|
// Check for cases where one of the pallet group palettes may have
|
||||||
|
// less pixels than the current set we're checking, e.g. we do a tile that
|
||||||
|
// has only two colors, then we iterate over a tile with 4 colors that has
|
||||||
|
// two colors shared with that other tile. In that case we just add our
|
||||||
|
// two extra colors.
|
||||||
|
if(paletteSet.length > pg.length) {
|
||||||
|
return pg.every(p => paletteSet.some(pss => pixelIsSame(pss, p)));
|
||||||
|
} else {
|
||||||
|
return paletteSet.every(p => pg.some(pgs => pixelIsSame(pgs, p)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(palId === -1) {
|
||||||
|
palId = paletteGroups.length;
|
||||||
|
paletteGroups.push(paletteSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
const paletteGroupSet = paletteGroups[palId];
|
||||||
|
|
||||||
|
// This is where we correct the missing pixels if we share that tileset from
|
||||||
|
// earlier
|
||||||
|
paletteSet.forEach(ps => {
|
||||||
|
const existing = paletteGroupSet.some(pgs => pixelIsSame(pgs, ps));
|
||||||
|
if(existing) return;
|
||||||
|
paletteGroupSet.push(ps);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort the paletteGroupSet...
|
||||||
|
const pgsGetWeight = thing => {
|
||||||
|
return thing.r + thing.g + thing.b;
|
||||||
|
}
|
||||||
|
paletteGroupSet.sort((l,r) => {
|
||||||
|
return pgsGetWeight(l) - pgsGetWeight(r);
|
||||||
|
});
|
||||||
|
|
||||||
|
const examples = [
|
||||||
|
/* 0 */{ r: 0, g: 0, b: 0, a: 255 },
|
||||||
|
/* 1 */{ r: 255, g: 0, b: 0, a: 255 },
|
||||||
|
/* 2 */{ r: 0, g: 255, b: 0, a: 255 },
|
||||||
|
/* 3 */{ r: 0, g: 0, b: 255, a: 255 },
|
||||||
|
/* 4 */{ r: 255, g: 255, b: 0, a: 255 },
|
||||||
|
/* 5 */{ r: 255, g: 0, b: 255, a: 255 },
|
||||||
|
/* 6 */{ r: 0, g: 255, b: 255, a: 255 },
|
||||||
|
/* 7 */{ r: 255, g: 255, b: 255, a: 255 },
|
||||||
|
|
||||||
|
/* S */{ r: 100, g: 0, b: 0, a: 255 },
|
||||||
|
/* S */{ r: 0, g: 100, b: 0, a: 255 },
|
||||||
|
/* S */{ r: 0, g: 0, b: 100, a: 255 },
|
||||||
|
/* S */{ r: 100, g: 100, b: 0, a: 255 },
|
||||||
|
/* S */{ r: 0, g: 100, b: 100, a: 255 },
|
||||||
|
/* S */{ r: 100, g: 0, b: 100, a: 255 },
|
||||||
|
/* S */{ r: 100, g: 100, b: 100, a: 255 },
|
||||||
|
];
|
||||||
|
paletteImage.push(examples[palId]);
|
||||||
|
|
||||||
|
const pixelIndex = paletteGroupSet.findIndex(ps => pixelIsSame(ps, pixel));
|
||||||
|
const nonColor = [
|
||||||
|
{ r: 8, g: 24, b: 32, a: 255 },
|
||||||
|
{ r: 52, g: 104, b: 86, a: 255 },
|
||||||
|
{ r: 136, g: 192, b: 112, a: 255 },
|
||||||
|
{ r: 224, g: 248, b: 208, a: 255 }
|
||||||
|
];
|
||||||
|
gbVersion.push(nonColor[pixelIndex % nonColor.length]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('Found', paletteGroups.length, 'palettes');
|
||||||
|
|
||||||
|
imageOut(original.pixels, original.width, 'original.png');
|
||||||
|
imageOut(withPaletteOverflows, original.width, 'errors.png');
|
||||||
|
imageOut(palette, palette.length, 'palette.png');
|
||||||
|
imageOut(outPaletteByEight, outByEightWidth, 'paletteByEight.png');
|
||||||
|
imageOut(paletteImage, original.width, 'palettes.png');
|
||||||
|
imageOut(gbVersion, original.width, 'gameboy.png');
|
||||||
|
|
||||||
|
// Now generate the GB files
|
||||||
|
// let rearranged = [];
|
||||||
|
// let n = 0;
|
||||||
|
// for(let i = 0; i < columns * rows; i++) {
|
||||||
|
// const tileX = i % columns;
|
||||||
|
// const tileY = Math.floor(i / columns) % rows;
|
||||||
|
|
||||||
|
// for(let y = 0; y < TILE_HEIGHT; y++) {
|
||||||
|
// for(let x = 0; x < TILE_WIDTH; x++) {
|
||||||
|
// const px = (tileX * TILE_WIDTH) + x;
|
||||||
|
// const py = (tileY * TILE_HEIGHT) + y;
|
||||||
|
// const pi = (py * png.width) + px;
|
||||||
|
// rearranged[n++] = original.pixels[pi];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Now turn into a tileset
|
||||||
|
// const bits = [];
|
||||||
|
// for(let i = 0; i < rearranged.length; i += TILE_WIDTH) {
|
||||||
|
// let lowBits = 0x00;
|
||||||
|
// let highBits = 0x00;
|
||||||
|
// for(let j = 0; j < TILE_WIDTH; j++) {
|
||||||
|
// const pixel = rearranged[i + j];
|
||||||
|
// lowBits = lowBits | ((pixel & 0x01) << (7-j));
|
||||||
|
// highBits = highBits | ((pixel & 0x02) >> 1 << (7-j));
|
||||||
|
// }
|
||||||
|
// bits.push(lowBits, highBits);
|
||||||
|
// }
|
Reference in New Issue
Block a user