Skip to content

Commit

Permalink
Move tileset and palette out of nametable object 🚪.
Browse files Browse the repository at this point in the history
  • Loading branch information
gmarty committed May 25, 2024
1 parent 9845b2a commit 19acdc7
Show file tree
Hide file tree
Showing 15 changed files with 387 additions and 277 deletions.
9 changes: 3 additions & 6 deletions src/components/RoomGfx.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import GfxCanvasContainer from '../containers/GfxCanvasContainer';

const RoomGfx = ({
baseTiles,
tileset,
nametable,
objectImages,
roomgfc,
Expand All @@ -27,12 +28,8 @@ const RoomGfx = ({
) : null}
<Link
className="text-center text-sm"
to={
type === 'room'
? `/roomgfx/${nametable.tileset}`
: `/titlegfx/${nametable.tileset}`
}>
Tileset {nametable.tileset} ({roomgfc.gfx.length / 8 / 2} tiles)
to={type === 'room' ? `/roomgfx/${tileset}` : `/titlegfx/${tileset}`}>
Tileset {tileset} ({roomgfc.gfx.length / 8 / 2} tiles)
<GfxCanvasContainer
gfx={roomgfc.gfx}
nametable={nametable}
Expand Down
2 changes: 1 addition & 1 deletion src/containers/GfxCanvasContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const draw = (
const tilesNum = gfx.length / 8 / 2;

// Massage the different tilesets to speed up code later.
const nametableTiles = nametable?.nametableObj?.flat();
const nametableTiles = nametable?.flat();
const objectImagesTiles = objectImages
?.map((objectImages) => objectImages.tiles)
.filter(Boolean)
Expand Down
15 changes: 7 additions & 8 deletions src/containers/RoomsContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ const RoomsContainer = ({ rooms, titles, roomgfx, globdata }) => {

const currentId = typeof id === 'undefined' ? null : parseInt(id, 10);
const baseTiles = roomgfx?.find(({ metadata }) => metadata.id === 0);
let roomgfc = roomgfx?.find(
({ metadata }) => metadata.id === room?.nametable?.tileset,
);
let roomgfc = roomgfx?.find(({ metadata }) => metadata.id === room?.tileset);

useEffect(() => {
const room =
Expand Down Expand Up @@ -56,16 +54,16 @@ const RoomsContainer = ({ rooms, titles, roomgfx, globdata }) => {
};

const updatePalette = (i, colourId) => {
const newRoom = structuredClone(room);
const newScreen = structuredClone(room);
if (i % 4 === 0) {
// Keep the first colours in sync.
for (let i = 0; i < 16; i += 4) {
newRoom.nametable.palette[i] = colourId;
newScreen.palette[i] = colourId;
}
} else {
newRoom.nametable.palette[i] = colourId;
newScreen.palette[i] = colourId;
}
setRoom(newRoom);
setRoom(newScreen);
};

if (room && !room.header) {
Expand Down Expand Up @@ -125,13 +123,14 @@ const RoomsContainer = ({ rooms, titles, roomgfx, globdata }) => {
/>
{currentTab === 'Palettes' && (
<Palettes
palette={room.nametable.palette}
palette={room.palette}
onUpdate={updatePalette}
/>
)}
{currentTab === 'Tilesets' && (
<RoomGfx
baseTiles={baseTiles}
tileset={room.tileset}
nametable={room.nametable}
objectImages={room.objectImages}
roomgfc={roomgfc}
Expand Down
8 changes: 4 additions & 4 deletions src/containers/ScreenCanvasContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ const draw = (
crop,
) => {
const { width, height } = room.header;
const { palette } = room.nametable;
const { palette } = room;
const baseTilesNum = baseTiles?.gfx?.length / 8 / 2;
const nametableObj = structuredClone(room.nametable.nametableObj);
const nametable = structuredClone(room.nametable);
const attributes = structuredClone(room.attributes);

// Overwrite tiles and palette with selected object.
Expand All @@ -78,7 +78,7 @@ const draw = (

for (let j = 0; j < objectImage.tiles.length; j++) {
for (let i = 0; i < objectImage.tiles[j].length; i++) {
nametableObj[y + j][x + i + 2] = objectImage.tiles[j][i];
nametable[y + j][x + i + 2] = objectImage.tiles[j][i];
}
}

Expand Down Expand Up @@ -121,7 +121,7 @@ const draw = (
// Now generate the image of the room.
for (let sprY = 0; sprY < height; sprY++) {
for (let sprX = 0; sprX < 62; sprX++) {
let tile = nametableObj[sprY][sprX];
let tile = nametable[sprY][sprX];

let gfx = baseTiles?.gfx;
if (tile >= baseTilesNum) {
Expand Down
16 changes: 6 additions & 10 deletions src/containers/TitlesContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,21 @@ const TitlesContainer = ({ rooms, titles }) => {
width: title.width,
height: title.height,
};
title.nametable = {
tileset: id,
palette: title.palette,
nametableObj: title.nametableObj,
};

setTitle(title);
}, [id, titles]);

const updatePalette = (i, colourId) => {
const newRoom = structuredClone(title);
const newScreen = structuredClone(title);
if (i % 4 === 0) {
// Keep the first colours in sync.
for (let i = 0; i < 16; i += 4) {
newRoom.nametable.palette[i] = colourId;
newScreen.palette[i] = colourId;
}
} else {
newRoom.nametable.palette[i] = colourId;
newScreen.palette[i] = colourId;
}
setTitle(newRoom);
setTitle(newScreen);
};

if (!title) {
Expand Down Expand Up @@ -87,13 +82,14 @@ const TitlesContainer = ({ rooms, titles }) => {
/>
{currentTab === 'Palettes' && (
<Palettes
palette={title.nametable.palette}
palette={title.palette}
onUpdate={updatePalette}
/>
)}
{currentTab === 'Tilesets' && (
<RoomGfx
baseTiles={{ gfx: [] }}
tileset={id}
nametable={title.nametable}
objectImages={title.objectImages}
roomgfc={{ gfx: title.gfx }}
Expand Down
24 changes: 24 additions & 0 deletions src/lib/parser/parsePalette.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Parser from './parser.js';

// Generic palette parser used in rooms and title screens.
const parsePalette = (arrayBuffer, offset = 0) => {
const parser = new Parser(arrayBuffer);

const palette = Array(16);
for (let i = 0; i < 16; i++) {
palette[i] = parser.getUint8();
}

const paletteMap = {
type: 'palette',
from: offset,
to: offset + 16,
};

return {
palette,
paletteMap,
};
};

export default parsePalette;
26 changes: 24 additions & 2 deletions src/lib/parser/parseRooms.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Parser from './parser.js';
import parseRoomHeader from './room/parseRoomHeader.js';
import parseRoomNametable from './room/parseRoomNametable.js';
import parsePalette from './parsePalette.js';
import parseRoomAttributes from './room/parseRoomAttributes.js';
import parseRoomBoxes from './room/parseRoomBoxes.js';
import parseRoomMatrix from './room/parseRoomMatrix.js';
Expand Down Expand Up @@ -61,10 +62,29 @@ const parseRooms = (arrayBuffer, i = 0, offset = 0, characters = {}) => {
});
}

// Parse the tileset id.
const tilesetParser = new Parser(
arrayBuffer.slice(nametableOffs, nametableOffs + 1),
);
const tileset = tilesetParser.getUint8();
map.push({
type: 'tileset',
from: nametableOffs,
to: nametableOffs,
});

// Parse the palette.
const { palette, paletteMap } = parsePalette(
arrayBuffer.slice(nametableOffs + 1, nametableOffs + 17),
nametableOffs + 1,
);

map.push(paletteMap);

// Parse gfx nametable.
const { nametable, nametableMap } = parseRoomNametable(
arrayBuffer.slice(nametableOffs, attrOffs),
nametableOffs,
arrayBuffer.slice(nametableOffs + 17, attrOffs),
nametableOffs + 17,
width,
);

Expand Down Expand Up @@ -396,6 +416,8 @@ const parseRooms = (arrayBuffer, i = 0, offset = 0, characters = {}) => {
boxes,
matrixUnks,
matrix,
tileset,
palette,
nametable,
attributes,
masktable,
Expand Down
36 changes: 22 additions & 14 deletions src/lib/parser/parseTitles.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Parser from './parser.js';
import parsePalette from './parsePalette.js';

const assert = console.assert;

Expand All @@ -10,6 +11,7 @@ const parseTitles = (arrayBuffer, i = 0, offset = 0) => {
size: arrayBuffer.byteLength,
// decompressedSize: 0, // Commented out until the buffer size is known.
};
const map = [];

const unk1 = parser.getUint16(); // Probably the chunk length unused in titles.
const unk2 = parser.getUint16();
Expand Down Expand Up @@ -51,26 +53,26 @@ const parseTitles = (arrayBuffer, i = 0, offset = 0) => {
assert(width === 32, 'Title width is not 32.');
assert(height === 30, 'Title height is not 30.');

const nametable = Array(width * height);
const nametableTmp = Array(width * height);
n = 0;
while (n < nametable.length) {
while (n < nametableTmp.length) {
const loop = parser.getUint8();
if (loop & 0x80) {
for (let j = 0; j < (loop & 0x7f); j++) {
nametable[n++] = parser.getUint8();
nametableTmp[n++] = parser.getUint8();
}
} else {
const data = parser.getUint8();
for (let j = 0; j < (loop & 0x7f); j++) {
nametable[n++] = data;
nametableTmp[n++] = data;
}
}
}

// Slice the nametableObj so it is formatted like rooms'.
const nametableObj = new Array(height);
// Slice the nametable so it is formatted like rooms'.
const nametable = new Array(height);
for (let i = 0; i < height; i++) {
nametableObj[i] = nametable.slice(i * width, (i + 1) * width);
nametable[i] = nametableTmp.slice(i * width, (i + 1) * width);
}

// Parse gfx attrtable.
Expand Down Expand Up @@ -100,17 +102,22 @@ const parseTitles = (arrayBuffer, i = 0, offset = 0) => {
}
}

// Parse palette.
const stepNum = parser.getUint8();

assert(stepNum === 3, 'stepNum is not 3.');

const palette = [];
for (let i = 0; i < 16; i++) {
palette[i] = parser.getUint8();
}
// Parse the palette.
const { palette, paletteMap } = parsePalette(
arrayBuffer.slice(parser.pointer, parser.pointer + 16),
parser.pointer,
);

const endOfData = parser.getUint8();
map.push(paletteMap);

const endOfDataParser = new Parser(
arrayBuffer.slice(parser.pointer + 16, parser.pointer + 17),
);
const endOfData = endOfDataParser.getUint8();

assert(endOfData === 0xff, 'endOfData is not 0xff.');

Expand All @@ -123,7 +130,7 @@ const parseTitles = (arrayBuffer, i = 0, offset = 0) => {
gfx,
width,
height,
nametableObj,
nametable,
attrWidth,
attrHeight,
attributes,
Expand All @@ -136,6 +143,7 @@ const parseTitles = (arrayBuffer, i = 0, offset = 0) => {
unk4,
unk5,
unk6,
map,
};
};

Expand Down
34 changes: 12 additions & 22 deletions src/lib/parser/room/parseRoomNametable.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@ 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 < nametableObj.length; i++) {
nametableObj[i] = Array(64).fill(0);
nametableObj[i][0] = 0;
nametableObj[i][1] = 0;
const nametable = Array(16);
for (let i = 0; i < nametable.length; i++) {
nametable[i] = Array(64).fill(0);
nametable[i][0] = 0;
nametable[i][1] = 0;

assert(
nametableObj[i][0] === 0,
nametable[i][0] === 0,
'Gfx nametable strip does not start with 0x00 0x00.',
);
assert(
nametableObj[i][1] === 0,
nametable[i][1] === 0,
'Gfx nametable strip does not start with 0x00 0x00.',
);

Expand All @@ -31,22 +25,22 @@ const parseRoomNametable = (arrayBuffer, offset = 0, width = 0) => {
const loop = parser.getUint8();
if (loop & 0x80) {
for (let j = 0; j < (loop & 0x7f); j++) {
nametableObj[i][2 + n++] = parser.getUint8();
nametable[i][2 + n++] = parser.getUint8();
}
} else {
const data = parser.getUint8();
for (let j = 0; j < (loop & 0x7f); j++) {
nametableObj[i][2 + n++] = data;
nametable[i][2 + n++] = data;
}
}
}

assert(
nametableObj[i][62] === 0,
nametable[i][62] === 0,
'Gfx nametable strip does not end with 0x00 0x00.',
);
assert(
nametableObj[i][63] === 0,
nametable[i][63] === 0,
'Gfx nametable strip does not end with 0x00 0x00.',
);
}
Expand All @@ -58,11 +52,7 @@ const parseRoomNametable = (arrayBuffer, offset = 0, width = 0) => {
};

return {
nametable: {
tileset,
palette,
nametableObj,
},
nametable,
nametableMap,
};
};
Expand Down
Loading

0 comments on commit 19acdc7

Please sign in to comment.