diff --git a/PUZ File Format.md b/PUZ File Format.md index 68db459..6fc3e66 100644 --- a/PUZ File Format.md +++ b/PUZ File Format.md @@ -3,6 +3,8 @@ This document is copied from Google Code wikis, with some formatting cleanup. Source: https://code.google.com/archive/p/puz/wikis/FileFormat.wiki +Additional details: https://github.com/alexdej/puzpy + --- # Introduction @@ -42,7 +44,7 @@ The following checksums are described in more detail in a separate section below | Width | 0x2C | 0x2C | 0x1 | byte | The width of the board | | Height | 0x2D | 0x2D | 0x1 | byte | The height of the board | | # of Clues | 0x2E | 0x2F | 0x2 | short | The number of clues for this board | -| Unknown Bitmask | 0x30 | 0x31 | 0x2 | short | A bitmask. Operations unknown. | +| Puzzle Type | 0x30 | 0x31 | 0x2 | short | A bitmask. Crossword = 0x0001, Diagramless = 0x0401. | | Scrambled Tag | 0x32 | 0x33 | 0x2 | short | 0 for unscrambled puzzles. Nonzero (often 4) for scrambled puzzles. | ## Puzzle Layout and State diff --git a/package.json b/package.json index 8e48d4c..7fcfd7f 100644 --- a/package.json +++ b/package.json @@ -23,16 +23,16 @@ "devDependencies": { "@rollup/plugin-node-resolve": "13.0.2", "@rollup/plugin-typescript": "8.2.1", - "@types/jest": "26.0.23", - "jest": "27.0.4", + "@types/jest": "^26.0.23", + "jest": "^27.0.4", "np": "8.0.4", "prettier": "2.3.2", "rollup": "2.52.7", "rollup-plugin-dts": "3.0.2", "rollup-plugin-polyfill-node": "0.6.2", "rollup-plugin-terser": "7.0.2", - "ts-jest": "27.0.3", - "typescript": "4.3.4", + "ts-jest": "^27.0.3", + "typescript": "^4.3.4", "uglify-js": "3.13.10" }, "dependencies": { diff --git a/src/binary/parse.ts b/src/binary/parse.ts index deeaa6b..cde0bda 100644 --- a/src/binary/parse.ts +++ b/src/binary/parse.ts @@ -52,7 +52,7 @@ export function parseBinaryFile(data: Uint8Array): Puzzle { const width = buffer.readUInt8(HEADER_OFFSET.WIDTH_START); const height = buffer.readUInt8(HEADER_OFFSET.HEIGHT_START); const numberOfClues = buffer.readUInt16LE(HEADER_OFFSET.NUMBER_OF_CLUES_START); - const unknown3 = buffer.readUInt16LE(HEADER_OFFSET.UNKNOWN_BITMASK_START); + const puzzleFormat = buffer.readUInt16LE(HEADER_OFFSET.PUZZLE_FORMAT_START); const scrambledTag = buffer.readUInt16LE(HEADER_OFFSET.SCRAMBLED_START); // } catch (e) { // // throw error indicating corrupt header data @@ -176,7 +176,7 @@ export function parseBinaryFile(data: Uint8Array): Puzzle { misc: { unknown1, unknown2, - unknown3, + puzzleFormat, preamble, scrambledChecksum, }, diff --git a/src/index.ts b/src/index.ts index bde9d30..3edb704 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,7 +39,7 @@ export type Puzzle = { misc?: { unknown1?: number; unknown2?: Uint8Array; - unknown3?: number; + puzzleFormat?: number; preamble?: Uint8Array; scrambledChecksum?: number; }; diff --git a/src/util/constants.ts b/src/util/constants.ts index aa82b73..97f7953 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -23,7 +23,7 @@ export const enum HEADER_OFFSET { WIDTH_START = 0x2c, HEIGHT_START = 0x2d, NUMBER_OF_CLUES_START = 0x2e, - UNKNOWN_BITMASK_START = 0x30, + PUZZLE_FORMAT_START = 0x30, SCRAMBLED_START = 0x32, } diff --git a/src/util/misc.ts b/src/util/misc.ts index 0e69590..71f905d 100644 --- a/src/util/misc.ts +++ b/src/util/misc.ts @@ -138,7 +138,7 @@ export function encodeHeaderWithoutChecksums(puzzle: Puzzle): Buffer { header.writeUInt8(puzzle.width, HEADER_OFFSET.WIDTH_START); header.writeUInt8(puzzle.height, HEADER_OFFSET.HEIGHT_START); header.writeUInt16LE(puzzle.clues.length, HEADER_OFFSET.NUMBER_OF_CLUES_START); - header.writeUInt16LE(puzzle?.misc?.unknown3 ?? 0x00, HEADER_OFFSET.UNKNOWN_BITMASK_START); + header.writeUInt16LE(puzzle?.misc?.puzzleFormat ?? 0x0001, HEADER_OFFSET.PUZZLE_FORMAT_START); header.writeUInt16LE(puzzle.isScrambled ? 0x04 : 0x00, HEADER_OFFSET.SCRAMBLED_START); return header; diff --git a/test/__snapshots__/index.test.ts.snap b/test/__snapshots__/index.test.ts.snap index 7e697c3..22b4d10 100644 --- a/test/__snapshots__/index.test.ts.snap +++ b/test/__snapshots__/index.test.ts.snap @@ -1975,6 +1975,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 1213, "unknown1": 28009, "unknown2": Object { @@ -1994,7 +1995,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -2096,6 +2096,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 0, "unknown2": Object { @@ -2115,7 +2116,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -2217,6 +2217,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 0, "unknown2": Object { @@ -2236,7 +2237,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -2342,6 +2342,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1025, "scrambledChecksum": 16930, "unknown1": 0, "unknown2": Object { @@ -2361,7 +2362,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1025, }, "notepad": "This diagramless is 17 squares wide by 17 squares deep and has an asymmetrical pattern suggested by the puzzle’s theme. The first square across is the seventh square in the first row. ", @@ -2459,6 +2459,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 40861, "unknown1": 28009, "unknown2": Object { @@ -2478,7 +2479,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -2580,6 +2580,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 28009, "unknown2": Object { @@ -2599,7 +2600,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -2938,6 +2938,7 @@ Object { ], "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 16632, "unknown2": Object { @@ -2957,7 +2958,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": "TEEN PUZZLEMAKER WEEK All the daily crosswords this week, Monday through Saturday, have been contributed by puzzlemakers under the age of 20. Today's crossword is by Caleb Madison, 15, of New York City. He is a sophomore at Bard High School in Manhattan. This is his fourth puzzle for The Times. @@ -3357,6 +3357,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 23056, "unknown1": 60768, "unknown2": Object { @@ -3376,7 +3377,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": Object { @@ -4553,6 +4553,7 @@ Object { ], "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 0, "unknown2": Object { @@ -4572,7 +4573,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": "Drop one letter from each set of circled letters in the grid to name a major-league baseball team. The letters thus removed, in order from top to bottom, will spell an appropriate answer at 76-Down. ", @@ -5111,6 +5111,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 49648, "unknown1": 16032, "unknown2": Object { @@ -5130,7 +5131,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": "TEEN PUZZLEMAKER WEEK All the daily crosswords this week, Monday through Saturday, have been contributed by puzzlemakers under the age of 20. Today's crossword is by Natan Last, 17, of Brooklyn. He is a first-year student at Brown University. This is his sixth puzzle for The Times. @@ -5803,6 +5803,7 @@ Object { ], "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 63979, "unknown1": 8281, "unknown2": Object { @@ -5822,7 +5823,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": Object { @@ -6296,6 +6296,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 0, "unknown2": Object { @@ -6315,7 +6316,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -6377,6 +6377,7 @@ Object { ], "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 0, "unknown2": Object { @@ -6396,7 +6397,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": Object { @@ -6530,6 +6530,7 @@ Object { ], "type": "Buffer", }, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 61696, "unknown2": Object { @@ -6549,7 +6550,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined, @@ -6711,6 +6711,7 @@ Object { "markupGrid": undefined, "misc": Object { "preamble": undefined, + "puzzleFormat": 1, "scrambledChecksum": 0, "unknown1": 18664, "unknown2": Object { @@ -6730,7 +6731,6 @@ Object { ], "type": "Buffer", }, - "unknown3": 1, }, "notepad": undefined, "rebus": undefined,