diff --git a/miku/title-smol.png b/miku/title-smol.png index 4590390..d50b578 100644 Binary files a/miku/title-smol.png and b/miku/title-smol.png differ diff --git a/out/.gitkeep b/out/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/GAME.ts b/src/GAME.ts index da87af5..c7559fe 100644 --- a/src/GAME.ts +++ b/src/GAME.ts @@ -20,52 +20,7 @@ **/ import { readFileSync, writeFileSync } from "fs"; -import { PNG } from "pngjs"; -import { - encodePalette, - encodeCutSceneTexture, - encodeTexel, - compressNewSegment, - encodeBitfield, - readPixel, -} from "./EncodeTexture"; - -type Pixel = { - r: number; - g: number; - b: number; - a: number; -}; - -const wordToColor = (word: number): Pixel => { - const r = ((word >> 0x00) & 0x1f) << 3; - const g = ((word >> 0x05) & 0x1f) << 3; - const b = ((word >> 0x0a) & 0x1f) << 3; - const a = word > 0 ? 255 : 0; - return { r, g, b, a }; -}; - -const compressData = (decompressed: Buffer) => { - const SEGMENT_LENGTH = 0x2000; - const segmentCount = Math.ceil(decompressed.length / SEGMENT_LENGTH); - const segments: Buffer[] = []; - for (let i = 0; i < segmentCount; i++) { - segments.push( - decompressed.subarray(i * SEGMENT_LENGTH, (i + 1) * SEGMENT_LENGTH), - ); - } - - const bucket: boolean[] = []; - const loads: Buffer[] = []; - segments.forEach((segment, index) => { - const { bits, outBuffer } = compressNewSegment(segment, 0); - bits.forEach((bit) => bucket.push(bit)); - loads.push(outBuffer); - }); - - const bitfied = encodeBitfield(bucket); - return [bitfied, Buffer.concat(loads)]; -}; +import { encodeCutSceneTexture, compressNewTexture } from "./EncodeTexture"; const decompress = (src: Buffer) => { const tim = { @@ -155,44 +110,18 @@ const decompress = (src: Buffer) => { } } - const imageData: number[] = new Array(); - for (ofs = 0; ofs < target.length; ofs++) { - const byte = target.readUInt8(ofs); - imageData.push(byte & 0xf); - imageData.push(byte >> 4); - } - - return imageData; -}; - -const encodeImage = (src: Buffer) => { - const face = PNG.sync.read(src); - const { data, width, height } = face; - - let inOfs = 0; - const pal: number[] = []; - const img: number[] = []; - - for (let y = 0; y < height; y++) { - for (let x = 0; x < width; x += 2) { - const lowByte = readPixel(data, inOfs, pal); - img.push(lowByte); - inOfs += 4; - const highByte = readPixel(data, inOfs, pal); - img.push(highByte); - inOfs += 4; - } - } - - return { pal, img }; + return target; }; const updateDemoLogo = (pngPath: string) => { const bin = readFileSync("bin/GAME.BIN"); const pngData = readFileSync(pngPath); - // Encode Image - const { pal, img } = encodeImage(pngData); + const imgOfs = 0x041800; + const pal: number[] = []; + + const encodedLogo = encodeCutSceneTexture(pal, pngData); + const encodedTexture = decompress(Buffer.from(bin.subarray(imgOfs))); // Update Palette const palOfs = 0x44800; @@ -200,66 +129,26 @@ const updateDemoLogo = (pngPath: string) => { bin.writeUInt16LE(pal[i], palOfs + 0x30 + i * 2); } - // Update Image - const imgOfs = 0x041800; - // First thing we want to do is get the decompressed texture - const buffer = Buffer.from(bin.subarray(imgOfs)); - const imgData = decompress(buffer); - - // Then we splice in our updated encoded texture - const height = 128; - const width = 256; - let inOfs = 0; - let outOfs = 0; - for (let y = 0; y < height; y++) { - for (var x = 0; x < width; x++) { - if (y >= 64 && y < 104) { - if (x >= 48 && x < 144) { - imgData[outOfs] = img[inOfs]; - inOfs++; - } - } - outOfs++; - } - } + console.log("Encoded Logo: 0x%s", encodedLogo.length.toString(16)); + console.log("Encoded Texture: 0x%s", encodedTexture.length.toString(16)); - // Write the texture to png to confirm it's working' - const png = new PNG({ width, height }); - - let index = 0; - let dst = 0; - for (let y = 0; y < height; y++) { - for (var x = 0; x < width; x++) { - const colorIndex = imgData[index++]; - const { r, g, b, a } = wordToColor(pal[colorIndex!]); - png.data[dst++] = r; - png.data[dst++] = g; - png.data[dst++] = b; - png.data[dst++] = a; + let texOfs = 0x2000; + let logoOfs = 0; + for (let y = 0; y < 40; y++) { + texOfs += 24; + for (let x = 0; x < 48; x++) { + encodedTexture[texOfs++] = encodedLogo[logoOfs++]; } + texOfs += 56; } - // Export file - const dat = PNG.sync.write(png); - writeFileSync(`out/smol.png`, dat); - - // Convert the image data back to a 4bit encoded buffer - const decompressed = Buffer.alloc((width * height) / 2, 0); - - index = 0; - outOfs = 0; - for (let y = 0; y < height; y++) { - for (let x = 0; x < width; x += 2) { - const lowByte = imgData[index++]; - const highByte = imgData[index++]; - const byte = ((highByte << 4) | lowByte) & 0xff; - decompressed[outOfs] = byte; - outOfs++; - } - } + console.log("Logo Pos: 0x%s", logoOfs.toString(16)); - // And then we compress and put it back in - const [bodyBitField, compressedBody] = compressData(decompressed); + const [bodyBitField, compressedBody] = compressNewTexture( + Buffer.alloc(0), + encodedTexture, + 0, + ); const len = bodyBitField.length + compressedBody.length; console.log("Segment 2: 0x%s", len.toString(16)); diff --git a/test/logo.test.ts b/test/logo.test.ts index 6c9501a..61bff42 100644 --- a/test/logo.test.ts +++ b/test/logo.test.ts @@ -159,7 +159,7 @@ const renderImage = (src: Buffer, pos: number, palette: Pixel[]) => { // Export file const buffer = PNG.sync.write(png); - writeFileSync(`out/logos_${pos.toString(16)}.png`, buffer); + writeFileSync(`out/miku_${pos.toString(16)}.png`, buffer); }; test("it should search for textures in the file", () => {