gbp-decode
Advanced tools
| export declare const completeFrame: (images: string[][]) => string[][]; |
| const fourtyLines = (new Array(40)).fill('00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00'); | ||
| export const completeFrame = (images) => (images.map((image) => { | ||
| if (image.length !== 280) { | ||
| return image; | ||
| } | ||
| return [ | ||
| ...fourtyLines, | ||
| ...image, | ||
| ...fourtyLines, | ||
| ]; | ||
| })); |
| import { Packet } from "./Types"; | ||
| export declare enum COMMAND { | ||
| INIT = 1, | ||
| PRINT = 2, | ||
| DATA = 4, | ||
| STATUS = 15, | ||
| TRANSFER = 16 | ||
| } | ||
| export declare enum STATE { | ||
| AWAIT_MAGIC_BYTES = 0, | ||
| AWAIT_COMMAND = 1, | ||
| AWAIT_COMPRESSION_INFO = 2, | ||
| AWAIT_PACKET_DATA_LENGTH = 3, | ||
| AWAIT_DATA = 4, | ||
| AWAIT_CHECKSUM = 5, | ||
| AWAIT_KEEPALIVE = 6, | ||
| AWAIT_STATUS_QUERY = 7 | ||
| } | ||
| export declare const EMPTY_PACKET: Packet; | ||
| export declare enum DECOMP_MODE { | ||
| DETECT_LENGTH = 0, | ||
| COMPRESSED = 1, | ||
| UNCOMPRESSED = 2 | ||
| } |
| export var COMMAND; | ||
| (function (COMMAND) { | ||
| COMMAND[COMMAND["INIT"] = 1] = "INIT"; | ||
| COMMAND[COMMAND["PRINT"] = 2] = "PRINT"; | ||
| COMMAND[COMMAND["DATA"] = 4] = "DATA"; | ||
| COMMAND[COMMAND["STATUS"] = 15] = "STATUS"; | ||
| COMMAND[COMMAND["TRANSFER"] = 16] = "TRANSFER"; | ||
| })(COMMAND || (COMMAND = {})); | ||
| export var STATE; | ||
| (function (STATE) { | ||
| STATE[STATE["AWAIT_MAGIC_BYTES"] = 0] = "AWAIT_MAGIC_BYTES"; | ||
| STATE[STATE["AWAIT_COMMAND"] = 1] = "AWAIT_COMMAND"; | ||
| STATE[STATE["AWAIT_COMPRESSION_INFO"] = 2] = "AWAIT_COMPRESSION_INFO"; | ||
| STATE[STATE["AWAIT_PACKET_DATA_LENGTH"] = 3] = "AWAIT_PACKET_DATA_LENGTH"; | ||
| STATE[STATE["AWAIT_DATA"] = 4] = "AWAIT_DATA"; | ||
| STATE[STATE["AWAIT_CHECKSUM"] = 5] = "AWAIT_CHECKSUM"; | ||
| STATE[STATE["AWAIT_KEEPALIVE"] = 6] = "AWAIT_KEEPALIVE"; | ||
| STATE[STATE["AWAIT_STATUS_QUERY"] = 7] = "AWAIT_STATUS_QUERY"; | ||
| })(STATE || (STATE = {})); | ||
| export const EMPTY_PACKET = { | ||
| command: null, | ||
| buffer: [], | ||
| data: [], | ||
| hasCompression: 0, | ||
| dataLength: 0, | ||
| checksum: 0, | ||
| }; | ||
| export var DECOMP_MODE; | ||
| (function (DECOMP_MODE) { | ||
| DECOMP_MODE[DECOMP_MODE["DETECT_LENGTH"] = 0] = "DETECT_LENGTH"; | ||
| DECOMP_MODE[DECOMP_MODE["COMPRESSED"] = 1] = "COMPRESSED"; | ||
| DECOMP_MODE[DECOMP_MODE["UNCOMPRESSED"] = 2] = "UNCOMPRESSED"; | ||
| })(DECOMP_MODE || (DECOMP_MODE = {})); |
| import { ParsedPacket, PrintPacket } from "./Types"; | ||
| export declare const decodePrintCommands: (packets: ParsedPacket[]) => (PrintPacket | ParsedPacket)[]; |
| import { COMMAND } from "./constants"; | ||
| import { parsePaletteByte } from "./parsePaletteByte"; | ||
| export const decodePrintCommands = (packets) => { | ||
| return packets | ||
| .map((packet) => { | ||
| if (packet.command === COMMAND.PRINT) { | ||
| const printData = { | ||
| margins: packet.data[1], | ||
| marginUpper: packet.data[1] >> 4, | ||
| marginLower: packet.data[1] & 0xf, | ||
| palette: packet.data[2], | ||
| paletteData: parsePaletteByte(packet.data[2]), | ||
| }; | ||
| return { | ||
| ...packet, | ||
| data: printData, | ||
| }; | ||
| } | ||
| return packet; | ||
| }); | ||
| }; |
| import { ParsedPacket } from "./Types"; | ||
| export declare const decompressDataStream: (packets: ParsedPacket[]) => ParsedPacket[]; |
| import { COMMAND } from "./constants"; | ||
| import { unpack } from "./unpack"; | ||
| export const decompressDataStream = (packets) => { | ||
| return packets | ||
| .map((packet) => { | ||
| if (packet.command === COMMAND.DATA) { | ||
| return { | ||
| ...packet, | ||
| hasCompression: 0, | ||
| data: packet.hasCompression ? unpack(packet.data) : packet.data | ||
| }; | ||
| } | ||
| return packet; | ||
| }); | ||
| }; |
| import { ParsedPacket } from "./Types"; | ||
| export declare const getImageDataStream: (packets: ParsedPacket[]) => ParsedPacket[]; |
| import { COMMAND } from "./constants"; | ||
| export const getImageDataStream = (packets) => { | ||
| return packets.filter(({ command }) => (command === COMMAND.DATA || | ||
| command === COMMAND.PRINT)); | ||
| }; |
| import { HarmonisedPalette, PaletteData } from "./Types"; | ||
| export declare const harmonizePalette: (charA: number, charB: number, paletteDefinition?: PaletteData) => HarmonisedPalette; |
| export const harmonizePalette = (charA, charB, paletteDefinition = [3, 2, 1, 0]) => { | ||
| const bits = [...Array(8)].map((_, index) => ({ | ||
| a: (charB >> 7 - index) % 2, | ||
| b: (charA >> 7 - index) % 2, | ||
| })); | ||
| const res = bits | ||
| .map(({ a, b, }) => ((a << 1) + b)) | ||
| .map((val) => (paletteDefinition[3 - val])) | ||
| .map((mapped) => ({ | ||
| a: (mapped >> 1) % 2, | ||
| b: mapped % 2, | ||
| })) | ||
| .reduce((acc, current, index) => ({ | ||
| a: acc.a + (current.a << 7 - index), | ||
| b: acc.b + (current.b << 7 - index), | ||
| }), { | ||
| a: 0, | ||
| b: 0, | ||
| }); | ||
| return [ | ||
| res.b & 0xff, | ||
| res.a & 0xff, | ||
| ]; | ||
| }; |
| import { ParsedPacket, PrintPacket } from "./Types"; | ||
| export declare const harmonizePalettes: (packets: (PrintPacket | ParsedPacket)[]) => (PrintPacket | ParsedPacket)[]; |
| import { COMMAND } from "./constants"; | ||
| import { harmonizePalette } from "./harmonizePalette"; | ||
| export const harmonizePalettes = (packets) => { | ||
| let unharmonizedPackets = []; | ||
| return packets | ||
| .map((packet) => { | ||
| switch (packet.command) { | ||
| case COMMAND.DATA: | ||
| unharmonizedPackets.push(packet); | ||
| break; | ||
| case COMMAND.PRINT: | ||
| if (packet.data.palette === 0) { | ||
| unharmonizedPackets = []; | ||
| break; | ||
| } | ||
| while (unharmonizedPackets.length) { | ||
| let unharmonizedPacket = unharmonizedPackets.shift(); | ||
| const data = []; | ||
| if (!unharmonizedPacket) { | ||
| throw Error('error harmonizing'); | ||
| } | ||
| for (let i = 0; i < unharmonizedPacket.data.length; i += 2) { | ||
| data.push(...harmonizePalette(unharmonizedPacket.data[i], unharmonizedPacket.data[i + 1], packet.data.paletteData)); | ||
| } | ||
| Object.assign(unharmonizedPacket, { data }); | ||
| } | ||
| break; | ||
| } | ||
| return packet; | ||
| }); | ||
| }; |
| export {}; |
| import fs from "node:fs/promises"; | ||
| import path from "node:path"; | ||
| import { toByteArray } from "./toByteArray"; | ||
| import { parsePackets } from "./parsePackets"; | ||
| import { getImageDataStream } from "./getImageDataStream"; | ||
| import { decompressDataStream } from "./decompressDataStream"; | ||
| import { decodePrintCommands } from "./decodePrintCommands"; | ||
| import { harmonizePalettes } from "./harmonizePalettes"; | ||
| import { transformToClassic } from "./transformToClassic"; | ||
| import { parseReducedPackets } from "./parseReducedPackets"; | ||
| import { inflateTransferPackages } from "./inflateTransferPackages"; | ||
| import { completeFrame } from "./completeFrame"; | ||
| const outDir = path.join(process.cwd(), 'out'); | ||
| const runStandard = async (fileName, outKey) => { | ||
| const filePath = path.join(process.cwd(), 'in', fileName); | ||
| let fileContents; | ||
| let rawPackets; | ||
| let parsedPackets; | ||
| let dataPackets; | ||
| let decompPackets; | ||
| let printInfoPackets; | ||
| let harmonizedPackets; | ||
| let classicPrintStreamImages; | ||
| try { | ||
| fileContents = await fs.readFile(filePath, { encoding: 'utf8' }); | ||
| } | ||
| catch (error) { | ||
| console.error(error.message); | ||
| process.exit(-1); | ||
| } | ||
| rawPackets = toByteArray(fileContents); | ||
| parsedPackets = parsePackets(rawPackets); | ||
| dataPackets = getImageDataStream(parsedPackets); | ||
| decompPackets = decompressDataStream(dataPackets); | ||
| printInfoPackets = decodePrintCommands(decompPackets); | ||
| harmonizedPackets = harmonizePalettes(printInfoPackets); | ||
| classicPrintStreamImages = transformToClassic(harmonizedPackets); | ||
| try { | ||
| await Promise.all(classicPrintStreamImages.map(async (image, index) => { | ||
| image.unshift('!{"command":"INIT"}'); | ||
| await fs.writeFile(path.join(outDir, `out_${outKey}_${index}.txt`), image.join('\n'), { encoding: 'utf8' }); | ||
| })); | ||
| } | ||
| catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
| const runReduced = async (fileName, outKey) => { | ||
| const filePath = path.join(process.cwd(), 'in', fileName); | ||
| let fileContents; | ||
| let reducedPackages; | ||
| let rawPackets; | ||
| let parsedPackets; | ||
| let dataPackets; | ||
| let decompPackets; | ||
| let printInfoPackets; | ||
| let harmonizedPackets; | ||
| let reducedClassicPrintStreamImages; | ||
| let classicPrintStreamImages; | ||
| try { | ||
| fileContents = await fs.readFile(filePath, { encoding: 'utf8' }); | ||
| } | ||
| catch (error) { | ||
| console.error(error.message); | ||
| process.exit(-1); | ||
| } | ||
| reducedPackages = toByteArray(fileContents); | ||
| rawPackets = parseReducedPackets(reducedPackages); | ||
| parsedPackets = inflateTransferPackages(rawPackets); | ||
| dataPackets = getImageDataStream(parsedPackets); | ||
| decompPackets = decompressDataStream(dataPackets); | ||
| printInfoPackets = decodePrintCommands(decompPackets); | ||
| harmonizedPackets = harmonizePalettes(printInfoPackets); | ||
| reducedClassicPrintStreamImages = transformToClassic(harmonizedPackets); | ||
| classicPrintStreamImages = completeFrame(reducedClassicPrintStreamImages); | ||
| try { | ||
| await Promise.all(classicPrintStreamImages.map(async (image, index) => { | ||
| image.unshift('!{"command":"INIT"}'); | ||
| await fs.writeFile(path.join(outDir, `out_${outKey}_${index}.txt`), image.join('\n'), { encoding: 'utf8' }); | ||
| })); | ||
| } | ||
| catch (error) { | ||
| console.error(error); | ||
| } | ||
| }; | ||
| fs.mkdir(outDir, { | ||
| recursive: true, | ||
| }).then(() => { | ||
| runStandard('alice.txt', 'alice'); | ||
| runStandard('all.txt', 'all'); | ||
| runStandard('comp.txt', 'comp'); | ||
| runStandard('gradient.txt', 'gradient'); | ||
| runStandard('uncomp.txt', 'uncomp'); | ||
| runStandard('white.txt', 'white'); | ||
| runReduced('pico.txt', 'pico'); | ||
| }); |
| import { ParsedPacket } from "./Types"; | ||
| export declare const inflateTransferPackages: (packets: ParsedPacket[]) => ParsedPacket[]; |
| import { COMMAND } from "./constants"; | ||
| const twoTiles = (new Array(2 * 16)).fill(0x00); | ||
| const inflate = (arr) => { | ||
| const chunks = []; | ||
| let i = 0; | ||
| const n = arr.length; | ||
| while (i < n) { | ||
| chunks.push(...twoTiles, ...arr.slice(i, i += 256), ...twoTiles); | ||
| } | ||
| return chunks; | ||
| }; | ||
| export const inflateTransferPackages = (packets) => (packets.map((packet) => { | ||
| if (packet.command !== COMMAND.TRANSFER) { | ||
| return packet; | ||
| } | ||
| return { | ||
| ...packet, | ||
| command: COMMAND.DATA, | ||
| data: inflate(packet.data), | ||
| }; | ||
| })); |
| import { ParsedPacket } from "./Types"; | ||
| export declare const logPackets: (packets: ParsedPacket[]) => ParsedPacket[]; |
| import { COMMAND } from "./constants"; | ||
| const commandName = (command) => { | ||
| switch (command) { | ||
| case COMMAND.INIT: | ||
| return 'INIT'; | ||
| case COMMAND.PRINT: | ||
| return 'PRINT'; | ||
| case COMMAND.DATA: | ||
| return 'DATA'; | ||
| case COMMAND.STATUS: | ||
| return 'STATUS'; | ||
| default: | ||
| return '-'; | ||
| } | ||
| }; | ||
| export const logPackets = (packets) => { | ||
| console.log(packets.map(({ command, data, hasCompression, dataLength }) => ({ | ||
| command: commandName(command), | ||
| hasCompression: hasCompression ? 'yes' : 'no', | ||
| dataLength, | ||
| data: data.margins ? `marginUpper: ${data.marginUpper} - marginLower: ${data.marginLower}` : data.slice(0, 20).join(','), | ||
| }))); | ||
| return packets; | ||
| }; |
| import { ParsedPacket } from "./Types"; | ||
| export declare const parsePackets: (bytes: number[]) => ParsedPacket[]; |
| import { STATE, EMPTY_PACKET } from "./constants"; | ||
| export const parsePackets = (bytes) => { | ||
| let state = STATE.AWAIT_MAGIC_BYTES; | ||
| let packet = { ...EMPTY_PACKET }; | ||
| const packets = []; | ||
| bytes.forEach((byte) => { | ||
| switch (state) { | ||
| case STATE.AWAIT_MAGIC_BYTES: | ||
| if (packet.buffer.length === 0 && byte === 0x88) { | ||
| packet.buffer.push(byte); | ||
| return; | ||
| } | ||
| else if (packet.buffer.length === 1 && byte === 0x33) { | ||
| packet.buffer = []; | ||
| state = STATE.AWAIT_COMMAND; | ||
| return; | ||
| } | ||
| else { | ||
| packet = { ...EMPTY_PACKET }; | ||
| return; | ||
| } | ||
| case STATE.AWAIT_COMMAND: | ||
| packet.command = byte; | ||
| state = STATE.AWAIT_COMPRESSION_INFO; | ||
| return; | ||
| case STATE.AWAIT_COMPRESSION_INFO: | ||
| packet.hasCompression = byte; | ||
| state = STATE.AWAIT_PACKET_DATA_LENGTH; | ||
| return; | ||
| case STATE.AWAIT_PACKET_DATA_LENGTH: | ||
| if (packet.buffer.length === 0) { | ||
| packet.buffer.push(byte); | ||
| return; | ||
| } | ||
| packet.dataLength = packet.buffer[0] + (byte << 8); | ||
| packet.buffer = []; | ||
| if (packet.dataLength === 0) { | ||
| state = STATE.AWAIT_CHECKSUM; | ||
| } | ||
| else { | ||
| state = STATE.AWAIT_DATA; | ||
| } | ||
| return; | ||
| case STATE.AWAIT_DATA: | ||
| if (packet.buffer.length < packet.dataLength) { | ||
| packet.buffer.push(byte); | ||
| return; | ||
| } | ||
| packet.data = packet.buffer; | ||
| packet.buffer = []; | ||
| state = STATE.AWAIT_CHECKSUM; | ||
| return; | ||
| case STATE.AWAIT_CHECKSUM: | ||
| if (packet.buffer.length === 0) { | ||
| packet.buffer.push(byte); | ||
| return; | ||
| } | ||
| packet.checksum = packet.buffer[0] + (byte << 8); | ||
| packet.buffer = []; | ||
| state = STATE.AWAIT_KEEPALIVE; | ||
| return; | ||
| case STATE.AWAIT_KEEPALIVE: | ||
| state = STATE.AWAIT_STATUS_QUERY; | ||
| return; | ||
| case STATE.AWAIT_STATUS_QUERY: | ||
| state = STATE.AWAIT_MAGIC_BYTES; | ||
| packets.push({ | ||
| checksum: packet.checksum, | ||
| command: packet.command, | ||
| data: packet.data, | ||
| dataLength: packet.dataLength, | ||
| hasCompression: packet.hasCompression, | ||
| }); | ||
| packet = { ...EMPTY_PACKET }; | ||
| return; | ||
| } | ||
| }); | ||
| return packets; | ||
| }; |
| import { PaletteData } from "./Types"; | ||
| export declare const parsePaletteByte: (paletteRaw: number) => PaletteData; |
| export const parsePaletteByte = (paletteRaw) => { | ||
| return [ | ||
| (paletteRaw >> 6) & 0x3, | ||
| (paletteRaw >> 4) & 0x3, | ||
| (paletteRaw >> 2) & 0x3, | ||
| (paletteRaw >> 0) & 0x3, | ||
| ]; | ||
| }; |
| import { ParsedPacket } from "./Types"; | ||
| export declare const parseReducedPackets: (bytes: number[]) => ParsedPacket[]; |
| import { COMMAND, STATE } from "./constants"; | ||
| export const parseReducedPackets = (bytes) => { | ||
| let state = STATE.AWAIT_COMMAND; | ||
| let packet = { | ||
| command: null, | ||
| buffer: [], | ||
| data: [], | ||
| hasCompression: 0, | ||
| dataLength: 0, | ||
| }; | ||
| const packets = []; | ||
| const nextPacket = () => { | ||
| packets.push({ | ||
| command: packet.command, | ||
| data: packet.data, | ||
| dataLength: packet.dataLength, | ||
| hasCompression: packet.hasCompression, | ||
| }); | ||
| packet = { | ||
| command: null, | ||
| buffer: [], | ||
| data: [], | ||
| hasCompression: 0, | ||
| dataLength: 0, | ||
| }; | ||
| state = STATE.AWAIT_COMMAND; | ||
| }; | ||
| bytes.forEach((byte, index) => { | ||
| switch (state) { | ||
| case STATE.AWAIT_COMMAND: | ||
| packet.command = byte; | ||
| switch (packet.command) { | ||
| case COMMAND.INIT: | ||
| nextPacket(); | ||
| return; | ||
| case COMMAND.DATA: | ||
| state = STATE.AWAIT_COMPRESSION_INFO; | ||
| return; | ||
| case COMMAND.PRINT: | ||
| state = STATE.AWAIT_PACKET_DATA_LENGTH; | ||
| return; | ||
| case COMMAND.TRANSFER: | ||
| state = STATE.AWAIT_PACKET_DATA_LENGTH; | ||
| return; | ||
| default: | ||
| throw new Error(`Unknown packet command: 0x${packet.command.toString(16)} at index ${index}`); | ||
| } | ||
| case STATE.AWAIT_COMPRESSION_INFO: | ||
| packet.hasCompression = byte; | ||
| state = STATE.AWAIT_PACKET_DATA_LENGTH; | ||
| return; | ||
| case STATE.AWAIT_PACKET_DATA_LENGTH: | ||
| if (packet.buffer.length === 0) { | ||
| packet.buffer.push(byte); | ||
| return; | ||
| } | ||
| packet.dataLength = packet.buffer[0] + (byte << 8); | ||
| packet.buffer = []; | ||
| if (packet.dataLength === 0) { | ||
| state = STATE.AWAIT_COMMAND; | ||
| nextPacket(); | ||
| return; | ||
| } | ||
| state = STATE.AWAIT_DATA; | ||
| return; | ||
| case STATE.AWAIT_DATA: | ||
| packet.buffer.push(byte); | ||
| if (packet.buffer.length === packet.dataLength) { | ||
| packet.data = packet.buffer; | ||
| state = STATE.AWAIT_COMMAND; | ||
| if (packet.command === COMMAND.TRANSFER) { | ||
| nextPacket(); | ||
| packet = { | ||
| buffer: [], | ||
| command: COMMAND.PRINT, | ||
| data: [1, 3, 228, 127], | ||
| hasCompression: 0, | ||
| dataLength: 4, | ||
| }; | ||
| } | ||
| nextPacket(); | ||
| } | ||
| break; | ||
| default: | ||
| } | ||
| }); | ||
| return packets; | ||
| }; |
| export declare const toByteArray: (fileContents: string) => number[]; |
| export const toByteArray = (fileContents) => (fileContents | ||
| .split('\n') | ||
| .filter((line) => !line.startsWith('//')) | ||
| .map(line => line.trim()) | ||
| .map(line => line | ||
| .split(' ') | ||
| .filter(Boolean) | ||
| .map((cc) => parseInt(cc, 16))) | ||
| .flat()); |
| import { ParsedPacket, PrintPacket } from "./Types"; | ||
| export declare const transformToClassic: (packets: (PrintPacket | ParsedPacket)[]) => string[][]; |
| import { COMMAND } from "./constants"; | ||
| export const transformToClassic = (packets) => { | ||
| let image = { | ||
| transformed: [], | ||
| }; | ||
| let currentLine = []; | ||
| const images = []; | ||
| packets.forEach((packet) => { | ||
| switch (packet.command) { | ||
| case COMMAND.DATA: | ||
| for (let i = 0; i < packet.data.length; i += 1) { | ||
| currentLine.push(packet.data[i].toString(16).padStart(2, '0')); | ||
| if (i % 16 === 15) { | ||
| image.transformed.push(currentLine.join(' ')); | ||
| currentLine = []; | ||
| } | ||
| } | ||
| break; | ||
| case COMMAND.PRINT: | ||
| image.palette = packet.data.paletteData || image.palette; | ||
| if (packet.data.marginLower !== 0) { | ||
| images.push(image.transformed); | ||
| image = { | ||
| transformed: [], | ||
| }; | ||
| currentLine = []; | ||
| } | ||
| break; | ||
| default: | ||
| break; | ||
| } | ||
| }); | ||
| if (image.transformed.length) { | ||
| images.push(image.transformed); | ||
| } | ||
| return images; | ||
| }; |
| import { COMMAND } from "./constants"; | ||
| export type PaletteData = [number, number, number, number]; | ||
| export type HarmonisedPalette = [number, number]; | ||
| export interface PrintData { | ||
| margins: number; | ||
| marginUpper: number; | ||
| marginLower: number; | ||
| palette: number; | ||
| paletteData: PaletteData; | ||
| } | ||
| export interface Packet { | ||
| command: null | COMMAND; | ||
| buffer: number[]; | ||
| data: number[]; | ||
| hasCompression: number; | ||
| dataLength: number; | ||
| checksum?: number; | ||
| } | ||
| export type ParsedPacket = Omit<Packet, 'buffer'>; | ||
| export interface PrintPacket extends Omit<Packet, 'data'> { | ||
| command: COMMAND.PRINT; | ||
| data: PrintData; | ||
| } | ||
| export interface TransformedImage { | ||
| transformed: string[]; | ||
| palette?: PaletteData; | ||
| } |
| export {}; |
| export declare const unpack: (data: number[]) => number[]; |
| import { DECOMP_MODE } from "./constants"; | ||
| export const unpack = (data) => { | ||
| const dataOut = []; | ||
| let mode = DECOMP_MODE.DETECT_LENGTH; | ||
| let length = 0; | ||
| data.forEach((byte) => { | ||
| switch (mode) { | ||
| case DECOMP_MODE.DETECT_LENGTH: | ||
| if (byte & 0x80) { | ||
| mode = DECOMP_MODE.COMPRESSED; | ||
| length = (byte & 0x7f) + 2; | ||
| } | ||
| else { | ||
| mode = DECOMP_MODE.UNCOMPRESSED; | ||
| length = byte + 1; | ||
| } | ||
| return; | ||
| case DECOMP_MODE.UNCOMPRESSED: | ||
| length -= 1; | ||
| if (length === 0) { | ||
| mode = DECOMP_MODE.DETECT_LENGTH; | ||
| } | ||
| dataOut.push(byte); | ||
| return; | ||
| case DECOMP_MODE.COMPRESSED: | ||
| dataOut.push(...[...Array(length)].map(() => byte)); | ||
| mode = DECOMP_MODE.DETECT_LENGTH; | ||
| length = 0; | ||
| return; | ||
| } | ||
| }); | ||
| return dataOut; | ||
| }; |
+2
-3
| { | ||
| "name": "gbp-decode", | ||
| "version": "1.3.14", | ||
| "version": "1.3.15", | ||
| "description": "A set of functions to decode gameboy printer code", | ||
@@ -19,4 +19,3 @@ "scripts": { | ||
| "files": [ | ||
| "dist/shared/*", | ||
| "dist/main.*" | ||
| "dist" | ||
| ], | ||
@@ -23,0 +22,0 @@ "repository": { |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
29713
264.09%38
850%643
2043.33%1
Infinity%