From c026038dc0067d0107ced18632b38a76a8145890 Mon Sep 17 00:00:00 2001 From: edo999 Date: Thu, 23 May 2024 11:03:56 +0100 Subject: [PATCH] =?UTF-8?q?Implement=20object=20attributes=20override=20?= =?UTF-8?q?=F0=9F=9B=9E.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/containers/ScreenCanvasContainer.js | 54 +++++++++++++++++++++---- src/lib/parser/parseRooms.js | 14 ++++++- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/containers/ScreenCanvasContainer.js b/src/containers/ScreenCanvasContainer.js index 594b882..7aba9df 100644 --- a/src/containers/ScreenCanvasContainer.js +++ b/src/containers/ScreenCanvasContainer.js @@ -51,17 +51,20 @@ const draw = ( crop, ) => { const { width, height } = room.header; - const { nametableObj, palette } = room.nametable; - const attributes = room.attributes; + const { palette } = room.nametable; const baseTilesNum = baseTiles?.gfx?.length / 8 / 2; - const nametableObjCopy = nametableObj.map((arr) => arr.slice()); + const nametableObj = structuredClone(room.nametable.nametableObj); + const attributes = structuredClone(room.attributes); - // Overwrite tiles with selected object. + // Overwrite tiles and palette with selected object. // Start with highest id as it is the way it is implemented with overlapping object images. for (let i = selectedObjects.length - 1; i >= 0; i--) { + const object = room?.objects[i]; const objectImage = room?.objectImages[i]; - const x = room?.objects[i]?.x; // Can be 0? - const y = room?.objects[i]?.y; // Can be 0? + const x = object?.x; // Can be 0? + const y = object?.y; // Can be 0? + const width = object?.width; + const height = object?.height; if ( !selectedObjects[i] || @@ -75,15 +78,50 @@ const draw = ( for (let j = 0; j < objectImage.tiles.length; j++) { for (let i = 0; i < objectImage.tiles[j].length; i++) { - nametableObjCopy[y + j][x + i + 2] = objectImage.tiles[j][i]; + nametableObj[y + j][x + i + 2] = objectImage.tiles[j][i]; } } + + // Port of https://github.com/scummvm/scummvm/blob/master/engines/scumm/gfx.cpp#L3103-L3134 + let j = height >> 1; + let ay = y; + let ptr = 0; + while (j) { + let ax = x + 2; + let i = 0; + let adata = 0; + while (i < width >> 1) { + if (!(i & 3)) { + adata = objectImage.attributes[ptr++]; + } + + let aand = 3; + let aor = adata & 3; + if (ay & 0x02) { + aand <<= 4; + aor <<= 4; + } + if (ax & 0x02) { + aand <<= 2; + aor <<= 2; + } + const attr = attributes[((ay << 2) & 0x30) | ((ax >> 2) & 0xf)]; + attributes[((ay << 2) & 0x30) | ((ax >> 2) & 0xf)] = + (~aand & attr) | aor; + + adata >>= 2; + ax += 2; + i++; + } + ay += 2; + j--; + } } // Now generate the image of the room. for (let sprY = 0; sprY < height; sprY++) { for (let sprX = 0; sprX < 62; sprX++) { - let tile = nametableObjCopy[sprY][sprX]; + let tile = nametableObj[sprY][sprX]; let gfx = baseTiles?.gfx; if (tile >= baseTilesNum) { diff --git a/src/lib/parser/parseRooms.js b/src/lib/parser/parseRooms.js index 5351835..333919f 100644 --- a/src/lib/parser/parseRooms.js +++ b/src/lib/parser/parseRooms.js @@ -293,9 +293,19 @@ const parseRooms = (arrayBuffer, i = 0, offset = 0, characters = {}) => { } } - // @todo Implement attribute changes and mask tables for object images. + // Parse object attrtable override. + const attributes = []; + if (tiles?.length) { + // Is that this length number of bytes to parse? + for (let i = 0; i < (objWidth >> 1) * (objHeight >> 1); i++) { + attributes.push(objectImagesParser.getUint8()); + } + } + + const objectImage = { tiles, attributes }; + objectImages.push(objectImage); - objectImages.push({ tiles }); + // @todo Implement mask tables for object images. // @fixme This does not account for object scripts. if (objectCodeMap.to < objectOffs + objectImagesParser.pointer) {