aboutsummaryrefslogtreecommitdiff
path: root/scumm/gfx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scumm/gfx.cpp')
-rw-r--r--scumm/gfx.cpp96
1 files changed, 81 insertions, 15 deletions
diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp
index 549438da07..6317e4a7a5 100644
--- a/scumm/gfx.cpp
+++ b/scumm/gfx.cpp
@@ -1440,7 +1440,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
if (_vm->_version == 1) {
mask_ptr = getMaskBuffer(x, y, 1);
if (_vm->_features & GF_NES) {
- drawStripNESMask(mask_ptr, stripnr, height);
+ drawStripNESMask(mask_ptr, stripnr, height, _C64ObjectMode);
} else {
drawStripC64Mask(mask_ptr, stripnr, width, height);
}
@@ -1833,8 +1833,7 @@ void Gdi::decompressMaskImgOr(byte *dst, const byte *src, int height) const {
void decodeNESTileData(const byte *src, byte *dest) {
int len = READ_LE_UINT16(src); src += 2;
const byte *end = src + len;
- int numtiles;
- numtiles = *src++; // not currently used
+ int numtiles = *src++; // not currently used
while (src < end) {
byte data = *src++;
for (int j = 0; j < (data & 0x7F); j++)
@@ -1886,12 +1885,13 @@ void Gdi::decodeNESGfx(const byte *room) {
const byte *mdata = room + READ_LE_UINT16(room + 0x0E);
int mask = *mdata++;
- if (mask == 0)
- return;
- if (mask != 1) {
- debug(0,"NES room %i has irregular mask count %i!",_vm->_currentRoom,mask);
+ if (mask == 0) {
+ _NEShasmask = false;
return;
}
+ _NEShasmask = true;
+ if (mask != 1)
+ debug(0,"NES room %i has irregular mask count %i!",_vm->_currentRoom,mask);
int mwidth = *mdata++;
for (i = 0; i < 16; i++) {
n = 0;
@@ -1906,14 +1906,16 @@ void Gdi::decodeNESGfx(const byte *room) {
}
void Gdi::decodeNESObject(const byte *ptr, int xpos, int ypos, int width, int height) {
- int y;
+ int x, y;
_NESObj_x = xpos;
+
+ // decode tile update data
+ memcpy(_NESNametableObj,_NESNametable,16*64);
ypos /= 8;
height /= 8;
-
for (y = ypos; y < ypos + height; y++) {
- int x = xpos;
+ x = xpos;
while (x < xpos + width) {
byte len = *ptr++;
for (int i = 0; i < (len & 0x7F); i++)
@@ -1922,6 +1924,64 @@ void Gdi::decodeNESObject(const byte *ptr, int xpos, int ypos, int width, int he
ptr++;
}
}
+
+ int ax, ay;
+ // decode attribute update data
+ memcpy(_NESAttributesObj, _NESAttributes,64);
+ y = height / 2;
+ ay = ypos;
+ while (y) {
+ ax = xpos + 2;
+ x = 0;
+ int adata = 0;
+ while (x < (width >> 1)) {
+ if (!(x & 3))
+ adata = *ptr++;
+ byte *dest = &_NESAttributesObj[((ay << 2) & 0x30) | ((ax >> 2) & 0xF)];
+
+ int aand = 3;
+ int aor = adata & 3;
+ if (ay & 0x02) {
+ aand <<= 4;
+ aor <<= 4;
+ }
+ if (ax & 0x02) {
+ aand <<= 2;
+ aor <<= 2;
+ }
+ *dest = ((~aand) & *dest) | aor;
+
+ adata >>= 2;
+ ax += 2;
+ x++;
+ }
+ ay += 2;
+ y--;
+ }
+
+ // decode mask update data
+ if (!_NEShasmask)
+ return;
+ memcpy(_NESMasktableObj, _NESMasktable,16*8);
+ int mx, mwidth;
+ int lmask, rmask;
+ mx = *ptr++;
+ mwidth = *ptr++;
+ lmask = *ptr++;
+ rmask = *ptr++;
+
+ y = 0;
+ do {
+ byte *dest = &_NESMasktableObj[y + ypos][mx];
+ *dest++ = (*dest & lmask) | *ptr++;
+ for (x = 1; x < mwidth; x++) {
+ if (x + 1 == mwidth)
+ *dest++ = (*dest & rmask) | *ptr++;
+ else
+ *dest++ = *ptr++;
+ }
+ y++;
+ } while (y < height);
}
void Gdi::drawStripNES(byte *dst, int dstPitch, int stripnr, int top, int height, bool isObject) {
@@ -1937,8 +1997,8 @@ void Gdi::drawStripNES(byte *dst, int dstPitch, int stripnr, int top, int height
return;
}
for (int y = top; y < top + height; y++) {
- int palette = (_NESAttributes[((y << 2) & 0x30) | ((x >> 2) & 0xF)] >> (((y & 2) << 1) | (x & 2))) & 0x3;
- int tile = isObject ? _NESNametableObj[y][x] : _NESNametable[y][x];
+ int palette = ((isObject ? _NESAttributesObj : _NESAttributes)[((y << 2) & 0x30) | ((x >> 2) & 0xF)] >> (((y & 2) << 1) | (x & 2))) & 0x3;
+ int tile = (isObject ? _NESNametableObj : _NESNametable)[y][x];
for (int i = 0; i < 8; i++) {
byte c0 = _vm->_NESPatTable[tile * 16 + i];
@@ -1950,15 +2010,21 @@ void Gdi::drawStripNES(byte *dst, int dstPitch, int stripnr, int top, int height
}
}
-void Gdi::drawStripNESMask(byte *dst, int stripnr, int height) const {
+void Gdi::drawStripNESMask(byte *dst, int stripnr, int height, bool isObject) const {
+ if (!_NEShasmask)
+ return;
height /= 8;
- int x = stripnr;
+ int x = stripnr + 2;
+
+ if (isObject)
+ x += _NESObj_x; // for objects, need to start at the left edge of the object, not the screen
if (x > 63) {
debug(0,"NES tried to mask invalid strip %i",stripnr);
return;
}
for (int y = 0; y < height; y++) {
- byte c = ((_NESMasktable[y][x >> 3] >> (x & 7)) & 1) ? 0xFF : 0x00;
+ // the ? 0xFF : 0x00 here might be backwards - '1' bits indicate that sprites can get hidden
+ byte c = (((isObject ? _NESMasktableObj : _NESMasktable)[y][x >> 3] >> (x & 7)) & 1) ? 0xFF : 0x00;
for (int i = 0; i < 8; i++) {
*dst = c;
dst += _numStrips;