From c35e17f04745ec4476a97d136b904ffae38d06fa Mon Sep 17 00:00:00 2001 From: edo999 Date: Thu, 2 May 2024 13:36:46 +0100 Subject: [PATCH] =?UTF-8?q?Add=20unit=20tests=20for=20room=20gfx=20nametab?= =?UTF-8?q?le=20and=20a=20serialiser=20=F0=9F=93=A1.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/parser/parseRooms.js | 50 ++----- src/lib/parser/room/parseRoomNametable.js | 70 +++++++++ .../serialiser/room/serialiseRoomNametable.js | 61 ++++++++ test/parseRoomNametable.test.js | 133 +++++++++++++++++ test/serialiseRoomNametable.test.js | 138 ++++++++++++++++++ 5 files changed, 411 insertions(+), 41 deletions(-) create mode 100644 src/lib/parser/room/parseRoomNametable.js create mode 100644 src/lib/serialiser/room/serialiseRoomNametable.js create mode 100644 test/parseRoomNametable.test.js create mode 100644 test/serialiseRoomNametable.test.js diff --git a/src/lib/parser/parseRooms.js b/src/lib/parser/parseRooms.js index 9db6650..455235e 100644 --- a/src/lib/parser/parseRooms.js +++ b/src/lib/parser/parseRooms.js @@ -1,5 +1,6 @@ import Parser from './parser.js'; import parseRoomHeader from './room/parseRoomHeader.js'; +import parseRoomNametable from './room/parseRoomNametable.js'; import parseRoomBoxes from './room/parseRoomBoxes.js'; import parseRoomMatrix from './room/parseRoomMatrix.js'; @@ -63,50 +64,17 @@ const parseRooms = (arrayBuffer, i = 0, offset = 0, characters = {}) => { } // Parse gfx nametable. - const nametableParser = new Parser(arrayBuffer.slice(nametableOffs)); - - const tileset = nametableParser.getUint8(); - - const palette = []; - const nametableObj = Array(16); - for (let i = 0; i < 16; i++) { - palette[i] = nametableParser.getUint8(); - } - for (let i = 0; i < 16; i++) { - nametableObj[i] = Array(64).fill(0); - nametableObj[i][0] = 0; - nametableObj[i][1] = 0; - let n = 0; - while (n < width) { - const loop = nametableParser.getUint8(); - if (loop & 0x80) { - for (let j = 0; j < (loop & 0x7f); j++) { - nametableObj[i][2 + n++] = nametableParser.getUint8(); - } - } else { - const data = nametableParser.getUint8(); - for (let j = 0; j < (loop & 0x7f); j++) { - nametableObj[i][2 + n++] = data; - } - } - } - } - - const nametable = { - tileset, - palette, - nametableObj, - }; + const { nametable, nametableMap } = parseRoomNametable( + arrayBuffer.slice(nametableOffs, attrOffs), + nametableOffs, + width, + ); - map.push({ - type: 'nametable', - from: nametableOffs, - to: nametableOffs + nametableParser.pointer - 1, - }); + map.push(nametableMap); assert( - nametableOffs + nametableParser.pointer === attrOffs, - 'name table overlaps on attributes table.', + nametableMap.to + 1 === attrOffs, + 'Gfx nametable overlaps on attributes table.', ); // Parse gfx attrtable. diff --git a/src/lib/parser/room/parseRoomNametable.js b/src/lib/parser/room/parseRoomNametable.js new file mode 100644 index 0000000..588a171 --- /dev/null +++ b/src/lib/parser/room/parseRoomNametable.js @@ -0,0 +1,70 @@ +import Parser from '../parser.js'; + +const assert = console.assert; + +const parseRoomNametable = (arrayBuffer, offset = 0, width = 0) => { + const parser = new Parser(arrayBuffer); + const tileset = parser.getUint8(); + + const palette = []; + for (let i = 0; i < 16; i++) { + palette[i] = parser.getUint8(); + } + + const nametableObj = Array(16); + for (let i = 0; i < 16; i++) { + nametableObj[i] = Array(64).fill(0); + nametableObj[i][0] = 0; + nametableObj[i][1] = 0; + + assert( + nametableObj[i][0] === 0, + 'Gfx nametable strip does not start with 0x00 0x00.', + ); + assert( + nametableObj[i][1] === 0, + 'Gfx nametable strip does not start with 0x00 0x00.', + ); + + let n = 0; + while (n < width) { + const loop = parser.getUint8(); + if (loop & 0x80) { + for (let j = 0; j < (loop & 0x7f); j++) { + nametableObj[i][2 + n++] = parser.getUint8(); + } + } else { + const data = parser.getUint8(); + for (let j = 0; j < (loop & 0x7f); j++) { + nametableObj[i][2 + n++] = data; + } + } + } + + assert( + nametableObj[i][62] === 0, + 'Gfx nametable strip does not end with 0x00 0x00.', + ); + assert( + nametableObj[i][63] === 0, + 'Gfx nametable strip does not end with 0x00 0x00.', + ); + } + + const nametableMap = { + type: 'nametable', + from: offset, + to: offset + parser.pointer - 1, + }; + + return { + nametable: { + tileset, + palette, + nametableObj, + }, + nametableMap, + }; +}; + +export default parseRoomNametable; diff --git a/src/lib/serialiser/room/serialiseRoomNametable.js b/src/lib/serialiser/room/serialiseRoomNametable.js new file mode 100644 index 0000000..6b2a90c --- /dev/null +++ b/src/lib/serialiser/room/serialiseRoomNametable.js @@ -0,0 +1,61 @@ +import Serialiser from '../serialiser.js'; + +const serialiseRoomNametable = (nametable = {}) => { + const serialiser = new Serialiser(); + const { tileset, palette, nametableObj } = nametable; + + serialiser.setUint8(tileset); + + for (let i = 0; i < 16; i++) { + serialiser.setUint8(palette[i]); + } + + for (let i = 0; i < 16; i++) { + serialiseOneStrip(nametableObj[i].slice(2, 62), serialiser); + } + + return serialiser.buffer; +}; + +// Serialise one strip using the compression algorithm. +const serialiseOneStrip = (nametableObj, serialiser) => { + let n = 0; + while (n < 60) { + let initialTile = nametableObj[n]; + let loop = 0; + + // Look 2 tiles ahead. + if ( + nametableObj[n] !== nametableObj[n + 1] || + nametableObj[n] !== nametableObj[n + 2] + ) { + // The next 3 tiles are different. Count how many unique tiles there are. + // It stops once it encounters 3 identical tiles in a row. + const initialN = n; + + do { + loop++; + initialTile = nametableObj[++n]; + } while ( + initialTile !== nametableObj[n + 1] || + initialTile !== nametableObj[n + 2] + ); + + serialiser.setUint8(loop | 0x80); // Set the type of loop. + for (let i = initialN; i < n; i++) { + serialiser.setUint8(nametableObj[i]); + } + } else { + // The next 3 tiles are identical. Count how many of them in a row. + // It stops when it finds a different tile. + do { + loop++; + } while (initialTile === nametableObj[++n]); + + serialiser.setUint8(loop); + serialiser.setUint8(initialTile); + } + } +}; + +export default serialiseRoomNametable; diff --git a/test/parseRoomNametable.test.js b/test/parseRoomNametable.test.js new file mode 100644 index 0000000..bb52116 --- /dev/null +++ b/test/parseRoomNametable.test.js @@ -0,0 +1,133 @@ +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import parseRoomNametable from '../src/lib/parser/room/parseRoomNametable.js'; +import serialiseRoomNametable from '../src/lib/serialiser/room/serialiseRoomNametable.js'; + +const roomNametableEmptyBuffer = (tileset) => { + const buffer = new ArrayBuffer(1 + 16 + 16 * 64); + const view = new DataView(buffer); + view.setUint8(0x00, tileset); // Set the value of tileset. + return buffer; +}; + +const roomNametableBuffer = () => { + const array = [ + 0x01, 0x0d, 0x07, 0x27, 0x3c, 0x0d, 0x17, 0x2a, 0x3a, 0x0d, 0x0d, 0x2a, + 0x28, 0x0d, 0x0d, 0x37, 0x20, 0x87, 0x01, 0x01, 0x62, 0x01, 0x63, 0x01, + 0x64, 0x03, 0x65, 0x82, 0x63, 0x64, 0x04, 0x65, 0x82, 0x63, 0x64, 0x09, + 0x65, 0x81, 0x63, 0x05, 0x65, 0x82, 0x63, 0x64, 0x03, 0x65, 0x83, 0x01, + 0x63, 0x74, 0x05, 0x01, 0x81, 0x62, 0x05, 0x01, 0x84, 0x74, 0x01, 0x01, + 0x74, 0x04, 0x01, 0x93, 0x01, 0x62, 0x62, 0x01, 0x63, 0x01, 0x64, 0x66, + 0x67, 0x68, 0x63, 0x66, 0x67, 0x68, 0x65, 0x66, 0x63, 0x68, 0x69, 0x06, + 0x6a, 0x8f, 0x6b, 0x66, 0x63, 0x68, 0x65, 0x66, 0x67, 0x68, 0x63, 0x66, + 0x67, 0x68, 0x65, 0x01, 0x63, 0x0c, 0x01, 0x88, 0x62, 0x01, 0x01, 0x62, + 0x01, 0x01, 0x62, 0x74, 0x04, 0x01, 0xa4, 0x63, 0x01, 0x64, 0x6c, 0x01, + 0x6d, 0x63, 0x6c, 0x01, 0x6d, 0x65, 0x6c, 0x63, 0x6d, 0x6e, 0x36, 0x39, + 0x37, 0x36, 0x39, 0x37, 0x6f, 0x6c, 0x63, 0x6d, 0x65, 0x6c, 0x01, 0x6d, + 0x63, 0x6c, 0x01, 0x6d, 0x65, 0x01, 0x63, 0x03, 0x01, 0x87, 0x74, 0x01, + 0x01, 0x62, 0x01, 0x01, 0x74, 0x04, 0x01, 0x86, 0x74, 0x01, 0x01, 0x74, + 0x01, 0x01, 0x81, 0x62, 0x03, 0x01, 0xa5, 0x63, 0x01, 0x64, 0x70, 0x71, + 0x72, 0x63, 0x70, 0x71, 0x72, 0x65, 0x70, 0x63, 0x72, 0x6e, 0x3e, 0x73, + 0x40, 0x3b, 0x73, 0x3c, 0x6f, 0x70, 0x63, 0xb4, 0x65, 0x70, 0xb5, 0xb4, + 0x63, 0x70, 0xb5, 0xb4, 0x65, 0x01, 0x63, 0x62, 0x13, 0x01, 0xa8, 0x01, + 0x62, 0x01, 0x74, 0x63, 0x01, 0x64, 0x6c, 0x01, 0x6d, 0x63, 0x6c, 0x01, + 0x6d, 0x65, 0x6c, 0x63, 0x6d, 0x6e, 0x3b, 0x3d, 0x40, 0x3b, 0x3d, 0x40, + 0x6f, 0x6c, 0x63, 0x6d, 0x65, 0x6c, 0x01, 0x6d, 0x63, 0x6c, 0x01, 0x6d, + 0x65, 0x01, 0x63, 0x03, 0x01, 0x83, 0x62, 0x01, 0x74, 0x03, 0x01, 0x81, + 0x62, 0x04, 0x01, 0x83, 0x62, 0x01, 0x74, 0x03, 0x01, 0x04, 0x01, 0xa4, + 0x63, 0x01, 0x64, 0x75, 0x76, 0x77, 0x63, 0x75, 0x76, 0x77, 0x65, 0x75, + 0x63, 0x77, 0x6e, 0x3b, 0x3d, 0x40, 0x3b, 0x3d, 0x40, 0x78, 0x75, 0x63, + 0x77, 0x65, 0x75, 0x76, 0x77, 0x63, 0x75, 0x76, 0x77, 0x65, 0x01, 0x63, + 0x0b, 0x01, 0x81, 0x74, 0x08, 0x01, 0x87, 0x62, 0x01, 0x01, 0x79, 0x7a, + 0x7b, 0x7c, 0x03, 0x7d, 0x82, 0x7a, 0x7c, 0x04, 0x7d, 0x8c, 0x7a, 0x64, + 0x6e, 0x3b, 0x3d, 0x49, 0x49, 0x3d, 0x40, 0x6f, 0x65, 0x7a, 0x05, 0x7d, + 0x81, 0x7a, 0x04, 0x7d, 0x83, 0x7b, 0x7a, 0xb6, 0x03, 0x01, 0x82, 0x74, + 0x62, 0x03, 0x01, 0x81, 0x62, 0x08, 0x01, 0x82, 0x62, 0x01, 0xab, 0x01, + 0x74, 0x01, 0x7e, 0x63, 0x01, 0x7f, 0x64, 0x7f, 0x64, 0x7f, 0x64, 0x7f, + 0x64, 0x7f, 0x64, 0x7f, 0x64, 0x6e, 0x3b, 0x3d, 0x40, 0x3b, 0x3d, 0x40, + 0x6f, 0x65, 0x7f, 0x64, 0x7f, 0x64, 0x7f, 0x64, 0x7f, 0x64, 0x7f, 0x64, + 0x7f, 0x01, 0x63, 0x7e, 0x01, 0x74, 0x03, 0x01, 0x84, 0x74, 0x01, 0xb7, + 0x62, 0x0a, 0xb7, 0x03, 0x01, 0xb4, 0x80, 0x63, 0x01, 0x81, 0x64, 0x81, + 0x64, 0x81, 0x64, 0x81, 0x64, 0x81, 0x64, 0x81, 0x64, 0x6e, 0x3e, 0x3d, + 0x40, 0x3b, 0x3d, 0x3c, 0x6f, 0x65, 0x81, 0x64, 0x81, 0x64, 0x81, 0x64, + 0x81, 0x64, 0x81, 0x64, 0x81, 0x01, 0x63, 0x80, 0x01, 0x62, 0x01, 0x01, + 0x62, 0x01, 0x01, 0xb8, 0xb9, 0xb8, 0xb8, 0xba, 0xb8, 0xb8, 0x05, 0xba, + 0xb7, 0x62, 0x01, 0x01, 0x82, 0x82, 0x83, 0x82, 0x84, 0x82, 0x84, 0x82, + 0x84, 0x82, 0x84, 0x82, 0x84, 0x82, 0x64, 0x6e, 0x41, 0x43, 0x44, 0x41, + 0x43, 0x44, 0x6f, 0x65, 0x82, 0x84, 0xbb, 0x84, 0xbb, 0x84, 0xbb, 0x84, + 0xbb, 0x84, 0xbb, 0x83, 0xbb, 0xbb, 0x01, 0xc4, 0xc5, 0x01, 0xc4, 0xc5, + 0x01, 0xc4, 0xc5, 0xbc, 0xbc, 0xbd, 0xbc, 0xbc, 0x05, 0xbd, 0x84, 0x85, + 0x86, 0x87, 0x01, 0x0d, 0x88, 0x82, 0x89, 0x84, 0x06, 0x8a, 0x83, 0x84, + 0x8b, 0x88, 0x0c, 0xbe, 0x8a, 0x01, 0x01, 0xc7, 0xc7, 0x01, 0xc7, 0xc7, + 0x01, 0xc7, 0xc7, 0x04, 0xbd, 0x82, 0xbf, 0xc0, 0x04, 0xbd, 0x84, 0x8c, + 0x8d, 0x8e, 0x01, 0x08, 0x8f, 0x04, 0x90, 0x82, 0x91, 0x92, 0x08, 0x93, + 0x82, 0x94, 0x91, 0x04, 0xce, 0x08, 0x8f, 0x8b, 0x01, 0x62, 0xbf, 0xc0, + 0x01, 0xbf, 0xc0, 0x01, 0xbf, 0xc0, 0xbc, 0x05, 0xbd, 0x81, 0xbc, 0x03, + 0xbd, 0x84, 0x01, 0x95, 0x01, 0x01, 0x06, 0x8f, 0x88, 0x96, 0x96, 0x97, + 0x98, 0x97, 0x98, 0x99, 0x9a, 0x08, 0x9b, 0x86, 0x9c, 0x9d, 0x97, 0xcf, + 0x97, 0xcf, 0x08, 0x8f, 0x14, 0xc1, 0x84, 0x9e, 0x9f, 0x9e, 0x9e, 0x08, + 0x90, 0x85, 0xa0, 0xa1, 0xa0, 0xa1, 0x82, 0x0a, 0x84, 0x85, 0x82, 0xa0, + 0xd1, 0xa0, 0xd1, 0x08, 0xc2, 0x14, 0x3d, 0x88, 0x3d, 0xa2, 0x3d, 0x3d, + 0xa3, 0xa4, 0xa4, 0xa5, 0x16, 0x3d, 0x81, 0xc6, 0x1d, 0x3d, 0x88, 0x3d, + 0xa2, 0x3d, 0x3d, 0xa6, 0xa7, 0xa8, 0xa7, 0x34, 0x3d, + // 0x82, 0x77, 0x01, 0x08, 0x00, 0x86, 0x40, 0xcd, 0x11, 0x00, 0xc0, 0xfc, + // 0x82, + ]; + const buffer = new ArrayBuffer(array.length); + const view = new DataView(buffer); + array.forEach((v, i) => view.setUint8(i, v)); + return buffer; +}; + +describe('parseRoomNametable', () => { + it('should return a non empty object.', () => { + const { nametable } = parseRoomNametable(roomNametableEmptyBuffer(0)); + + assert.equal(typeof nametable, 'object'); + assert.deepEqual(Object.keys(nametable), [ + 'tileset', + 'palette', + 'nametableObj', + ]); + assert.ok(Number.isInteger(nametable.tileset)); + assert.ok(Array.isArray(nametable.palette)); + assert.equal(nametable.palette.length, 16); + assert.ok(Array.isArray(nametable.nametableObj)); + assert.equal(nametable.nametableObj.length, 16); + assert.ok(Array.isArray(nametable.nametableObj[0])); + assert.equal(nametable.nametableObj[0].length, 64); + }); + + it('should parse the tileset.', () => { + const { nametable } = parseRoomNametable(roomNametableEmptyBuffer(5)); + + assert.equal(nametable.tileset, 5); + }); + + it('should return a map object.', () => { + const { nametableMap } = parseRoomNametable(roomNametableEmptyBuffer(0)); + + assert.equal(typeof nametableMap, 'object'); + assert.equal(nametableMap.from, 0); + assert.equal(nametableMap.to, 16); + }); + + it('should return a map object with a start offset.', () => { + const { nametableMap } = parseRoomNametable( + roomNametableEmptyBuffer(0), + 0xabc, + ); + + assert.equal(nametableMap.from, 0xabc); + assert.equal(nametableMap.to, 0xacc); + }); + + it('should be the inverse of serialiseRoomNametable.', () => { + const initialBuffer = roomNametableBuffer(); + const { nametable } = parseRoomNametable(initialBuffer, 0, 60); + + const buffer = serialiseRoomNametable(nametable); + + assert.deepEqual(initialBuffer, buffer); + }); +}); diff --git a/test/serialiseRoomNametable.test.js b/test/serialiseRoomNametable.test.js new file mode 100644 index 0000000..024f7fa --- /dev/null +++ b/test/serialiseRoomNametable.test.js @@ -0,0 +1,138 @@ +import { describe, it } from 'node:test'; +import assert from 'node:assert/strict'; +import serialiseRoomNametable from '../src/lib/serialiser/room/serialiseRoomNametable.js'; +import parseRoomNametable from '../src/lib/parser/room/parseRoomNametable.js'; + +const roomNametable = { + tileset: 187, + palette: [ + 114, 133, 23, 173, 185, 114, 141, 63, 109, 172, 188, 114, 230, 23, 230, 23, + ], + nametableObj: [ + [ + 0, 0, 1, 1, 98, 1, 99, 1, 100, 101, 101, 101, 99, 100, 101, 101, 101, 101, + 99, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 99, 101, 101, 101, + 101, 101, 99, 100, 101, 101, 101, 1, 99, 116, 1, 1, 1, 1, 1, 98, 1, 1, 1, + 1, 1, 116, 1, 1, 116, 1, 1, 1, 1, 0, 0, + ], + [ + 0, 0, 1, 98, 98, 1, 99, 1, 100, 102, 103, 104, 99, 102, 103, 104, 101, + 102, 99, 104, 105, 106, 106, 106, 106, 106, 106, 107, 102, 99, 104, 101, + 102, 103, 104, 99, 102, 103, 104, 101, 1, 99, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 98, 1, 1, 98, 1, 1, 98, 116, 0, 0, + ], + [ + 0, 0, 1, 1, 1, 1, 99, 1, 100, 108, 1, 109, 99, 108, 1, 109, 101, 108, 99, + 109, 110, 54, 57, 55, 54, 57, 55, 111, 108, 99, 109, 101, 108, 1, 109, 99, + 108, 1, 109, 101, 1, 99, 1, 1, 1, 116, 1, 1, 98, 1, 1, 116, 1, 1, 1, 1, + 116, 1, 1, 116, 1, 1, 0, 0, + ], + [ + 0, 0, 98, 1, 1, 1, 99, 1, 100, 112, 113, 114, 99, 112, 113, 114, 101, 112, + 99, 114, 110, 62, 115, 64, 59, 115, 60, 111, 112, 99, 180, 101, 112, 181, + 180, 99, 112, 181, 180, 101, 1, 99, 98, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + ], + [ + 0, 0, 1, 98, 1, 116, 99, 1, 100, 108, 1, 109, 99, 108, 1, 109, 101, 108, + 99, 109, 110, 59, 61, 64, 59, 61, 64, 111, 108, 99, 109, 101, 108, 1, 109, + 99, 108, 1, 109, 101, 1, 99, 1, 1, 1, 98, 1, 116, 1, 1, 1, 98, 1, 1, 1, 1, + 98, 1, 116, 1, 1, 1, 0, 0, + ], + [ + 0, 0, 1, 1, 1, 1, 99, 1, 100, 117, 118, 119, 99, 117, 118, 119, 101, 117, + 99, 119, 110, 59, 61, 64, 59, 61, 64, 120, 117, 99, 119, 101, 117, 118, + 119, 99, 117, 118, 119, 101, 1, 99, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 116, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, + ], + [ + 0, 0, 98, 1, 1, 121, 122, 123, 124, 125, 125, 125, 122, 124, 125, 125, + 125, 125, 122, 100, 110, 59, 61, 73, 73, 61, 64, 111, 101, 122, 125, 125, + 125, 125, 125, 122, 125, 125, 125, 125, 123, 122, 182, 1, 1, 1, 116, 98, + 1, 1, 1, 98, 1, 1, 1, 1, 1, 1, 1, 1, 98, 1, 0, 0, + ], + [ + 0, 0, 1, 116, 1, 126, 99, 1, 127, 100, 127, 100, 127, 100, 127, 100, 127, + 100, 127, 100, 110, 59, 61, 64, 59, 61, 64, 111, 101, 127, 100, 127, 100, + 127, 100, 127, 100, 127, 100, 127, 1, 99, 126, 1, 116, 1, 1, 1, 116, 1, + 183, 98, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 0, 0, + ], + [ + 0, 0, 1, 1, 1, 128, 99, 1, 129, 100, 129, 100, 129, 100, 129, 100, 129, + 100, 129, 100, 110, 62, 61, 64, 59, 61, 60, 111, 101, 129, 100, 129, 100, + 129, 100, 129, 100, 129, 100, 129, 1, 99, 128, 1, 98, 1, 1, 98, 1, 1, 184, + 185, 184, 184, 186, 184, 184, 186, 186, 186, 186, 186, 0, 0, + ], + [ + 0, 0, 98, 1, 1, 130, 130, 131, 130, 132, 130, 132, 130, 132, 130, 132, + 130, 132, 130, 100, 110, 65, 67, 68, 65, 67, 68, 111, 101, 130, 132, 187, + 132, 187, 132, 187, 132, 187, 132, 187, 131, 187, 187, 1, 196, 197, 1, + 196, 197, 1, 196, 197, 188, 188, 189, 188, 188, 189, 189, 189, 189, 189, + 0, 0, + ], + [ + 0, 0, 133, 134, 135, 1, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 136, 136, 136, 137, 132, 138, 138, 138, 138, 138, 138, 132, 139, 136, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 1, 1, 199, 199, 1, + 199, 199, 1, 199, 199, 189, 189, 189, 189, 191, 192, 189, 189, 189, 189, + 0, 0, + ], + [ + 0, 0, 140, 141, 142, 1, 143, 143, 143, 143, 143, 143, 143, 143, 144, 144, + 144, 144, 145, 146, 147, 147, 147, 147, 147, 147, 147, 147, 148, 145, 206, + 206, 206, 206, 143, 143, 143, 143, 143, 143, 143, 143, 1, 98, 191, 192, 1, + 191, 192, 1, 191, 192, 188, 189, 189, 189, 189, 189, 188, 189, 189, 189, + 0, 0, + ], + [ + 0, 0, 1, 149, 1, 1, 143, 143, 143, 143, 143, 143, 150, 150, 151, 152, 151, + 152, 153, 154, 155, 155, 155, 155, 155, 155, 155, 155, 156, 157, 151, 207, + 151, 207, 143, 143, 143, 143, 143, 143, 143, 143, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 0, 0, + ], + [ + 0, 0, 158, 159, 158, 158, 144, 144, 144, 144, 144, 144, 144, 144, 160, + 161, 160, 161, 130, 132, 132, 132, 132, 132, 132, 132, 132, 132, 132, 130, + 160, 209, 160, 209, 194, 194, 194, 194, 194, 194, 194, 194, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 0, 0, + ], + [ + 0, 0, 61, 162, 61, 61, 163, 164, 164, 165, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 198, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 0, 0, + ], + [ + 0, 0, 61, 162, 61, 61, 166, 167, 168, 167, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 0, 0, + ], + ], +}; + +describe('serialiseRoomNametable', () => { + it('should return an instance of ArrayBuffer.', () => { + const buffer = serialiseRoomNametable(roomNametable); + assert.ok(buffer instanceof ArrayBuffer); + }); + + it('should serialise a room gfx nametable.', () => { + const buffer = serialiseRoomNametable(roomNametable); + const view = new DataView(buffer); + + assert.equal(view.getUint8(0x00), 187); + assert.equal(view.getUint8(0x01), 114); + assert.equal(view.getUint8(0x05), 185); + assert.equal(view.getUint8(0x09), 109); + assert.equal(view.getUint8(0x0d), 230); + }); + + it('should be the inverse of parseRoomNametable.', () => { + const buffer = serialiseRoomNametable(roomNametable); + const { nametable } = parseRoomNametable(buffer, 0, 60); + + assert.deepEqual(roomNametable, nametable); + }); +});