diff options
author | Max Horn | 2002-08-20 02:20:40 +0000 |
---|---|---|
committer | Max Horn | 2002-08-20 02:20:40 +0000 |
commit | d2e2134a3ea3fd56bbf208e94bc26a434df9e2a7 (patch) | |
tree | d00be3e3957618b56508cbbf129c2e4b35b73594 | |
parent | 79e1c9cdf824314331206c23d211b8acb4801a86 (diff) | |
download | scummvm-rg350-d2e2134a3ea3fd56bbf208e94bc26a434df9e2a7.tar.gz scummvm-rg350-d2e2134a3ea3fd56bbf208e94bc26a434df9e2a7.tar.bz2 scummvm-rg350-d2e2134a3ea3fd56bbf208e94bc26a434df9e2a7.zip |
implemented the flashlight (TODO: use rounded corners. Left as an exercise to the reader)
svn-id: r4777
-rw-r--r-- | gfx.cpp | 170 | ||||
-rw-r--r-- | gfx.h | 17 | ||||
-rw-r--r-- | script_v1.cpp | 6 | ||||
-rw-r--r-- | scumm.h | 3 |
4 files changed, 133 insertions, 63 deletions
@@ -118,7 +118,7 @@ void Scumm::setDirtyRange(int slot, int top, int bottom) { int i; VirtScreen *vs = &virtscr[slot]; - for (i = 0; i < 40; i++) { + for (i = 0; i < NUM_STRIPS; i++) { vs->tdirty[i] = top; vs->bdirty[i] = bottom; } @@ -150,7 +150,7 @@ void Scumm::drawDirtyScreenParts() src = vs->screenPtr + _screenStartStrip * 8 + camera._cur.y - 100; _system->copy_rect(src, 320, 0, vs->topline, 320, vs->height); - for (i = 0; i < 40; i++) { + for (i = 0; i < NUM_STRIPS; i++) { vs->tdirty[i] = (byte)vs->height; vs->bdirty[i] = 0; } @@ -186,7 +186,7 @@ void Gdi::updateDirtyScreen(VirtScreen *vs) w = 8; start = 0; - for (i = 0; i < 40; i++) { + for (i = 0; i < NUM_STRIPS; i++) { bottom = vs->bdirty[i]; if (_vm->_features & GF_AFTER_V7 && (_vm->camera._cur.y != _vm->camera._last.y)) @@ -195,7 +195,7 @@ void Gdi::updateDirtyScreen(VirtScreen *vs) top = vs->tdirty[i]; vs->tdirty[i] = (byte)vs->height; vs->bdirty[i] = 0; - if (i != 39 && vs->bdirty[i + 1] == (byte)bottom && vs->tdirty[i + 1] == (byte)top) { + if (i != (NUM_STRIPS-1) && vs->bdirty[i + 1] == (byte)bottom && vs->tdirty[i + 1] == (byte)top) { w += 8; continue; } @@ -232,7 +232,7 @@ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b) if (scrollY == -100) scrollY = 0; - ptr = vs->screenPtr + (t * 40 + x) * 8 + _readOffs + scrollY * 320; + ptr = vs->screenPtr + (t * NUM_STRIPS + x) * 8 + _readOffs + scrollY * 320; _vm->_system->copy_rect(ptr, 320, x * 8, vs->topline + t, w, height); } @@ -240,7 +240,6 @@ void blit(byte *dst, byte *src, int w, int h) { assert(h > 0); - do { memcpy(dst, src, w); dst += 320; @@ -397,9 +396,9 @@ void Scumm::initBGBuffers(int height) assert(gdi._numZBuffer >= 1 && gdi._numZBuffer <= 5); if (_features & GF_AFTER_V7) - itemsize = (virtscr[0].height + 4) * 40; + itemsize = (virtscr[0].height + 4) * NUM_STRIPS; else - itemsize = (_scrHeight + 4) * 40; + itemsize = (_scrHeight + 4) * NUM_STRIPS; size = itemsize * gdi._numZBuffer; @@ -583,6 +582,70 @@ void Scumm::moveMemInPalRes(int start, int end, byte direction) void Scumm::drawFlashlight() { + static byte *flashBuffer = NULL; + static int flashX, flashY, flashW, flashH; + + int i, j, offset; + int topline = virtscr[0].topline; + + // Remove the flash light first if it was previously drawn + if (_flashlightIsDrawn) { + updateDirtyRect(0, flashX<<3, (flashX+flashW)<<3, flashY, flashY+flashH, 0x80000000); + + if (flashBuffer) { + + offset = 320 - flashW*8; + i = flashH; + do { + j = flashW*2; + do { + *(uint32 *)flashBuffer = 0; + flashBuffer += 4; + } while (--j); + flashBuffer += offset; + } while (--i); + } + + _flashlightIsDrawn = false; + } + + if (_flashlightXStrips == 0 || _flashlightYStrips == 0) + return; + + // Calculate the area of the flashlight + Actor *a = a = derefActorSafe(_vars[VAR_EGO], "drawFlashlight"); + flashW = _flashlightXStrips; + flashH = _flashlightYStrips * 8; + flashX = a->x/8 - flashW/2 - _screenStartStrip; + flashY = a->y - flashH/2; + + // Clip the flashlight at the borders + if (flashX < 0) + flashX = 0; + else if (flashX > NUM_STRIPS - flashW) + flashX = NUM_STRIPS - flashW; + if (flashY < 0) + flashY = 0; + else if (flashY > virtscr[0].height - flashH) + flashY = virtscr[0].height - flashH; + + // Redraw any actors "under" the flashlight + for (i = flashX; i < flashX+flashW; i++) { + gfxUsageBits[_screenStartStrip + i] |= 0x80000000; + virtscr[0].tdirty[i] = 0; + virtscr[0].bdirty[i] = virtscr[0].height; + } + + byte *bgbak; + offset = (flashY - topline) * 320 + virtscr[0].xstart + flashX*8; + flashBuffer = virtscr[0].screenPtr + offset; + bgbak = getResourceAddress(rtBuffer, 5) + offset; + + blit(flashBuffer, bgbak, flashW*8, flashH); + + // TODO - flashlight should have round corners + + _flashlightIsDrawn = true; } void Scumm::fadeIn(int effect) @@ -683,7 +746,7 @@ void Scumm::redrawBGAreas() val = 0; if (!_fullRedraw && _BgNeedsRedraw) { - for (i = 0; i != 40; i++) { + for (i = 0; i != NUM_STRIPS; i++) { if (gfxUsageBits[_screenStartStrip + i] & 0x80000000) { redrawBGStrip(i, 1); } @@ -694,25 +757,26 @@ void Scumm::redrawBGAreas() diff = (camera._cur.x >> 3) - (camera._last.x >> 3); if (_fullRedraw == 0 && diff == 1) { val = 2; - redrawBGStrip(39, 1); + redrawBGStrip(NUM_STRIPS-1, 1); } else if (_fullRedraw == 0 && diff == -1) { val = 1; redrawBGStrip(0, 1); } else if (_fullRedraw != 0 || diff != 0) { _BgNeedsRedraw = false; _fullRedraw = false; - redrawBGStrip(0, 40); + redrawBGStrip(0, NUM_STRIPS); } } else { if (_fullRedraw == 0 && camera._cur.x - camera._last.x == 8) { val = 2; - redrawBGStrip(39, 1); + redrawBGStrip(NUM_STRIPS-1, 1); } else if (_fullRedraw == 0 && camera._cur.x - camera._last.x == -8) { val = 1; redrawBGStrip(0, 1); } else if (_fullRedraw != 0 || camera._cur.x != camera._last.x) { _BgNeedsRedraw = false; - redrawBGStrip(0, 40); + _flashlightIsDrawn = false; + redrawBGStrip(0, NUM_STRIPS); } } @@ -742,7 +806,7 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, bool lightsOn; // Check whether lights are turned on or not - lightsOn = (_vm->_features & GF_AFTER_V6) || (_vm->_vars[_vm->VAR_CURRENT_LIGHTS] & LIGHTMODE_screen); + lightsOn = (_vm->_features & GF_AFTER_V6) || (vs->number != 0) || (_vm->_vars[_vm->VAR_CURRENT_LIGHTS] & LIGHTMODE_screen); CHECK_HEAP; if (_vm->_features & GF_SMALL_HEADER) @@ -803,7 +867,7 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, if (vs->scrollable) sx -= vs->xstart >> 3; - if ((uint) sx >= 40) + if ((uint) sx >= NUM_STRIPS) return; if (y < vs->tdirty[sx]) @@ -812,12 +876,13 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, if (bottom > vs->bdirty[sx]) vs->bdirty[sx] = bottom; - _backbuff_ptr = vs->screenPtr + (y * 40 + x) * 8; - _bgbak_ptr = _vm->getResourceAddress(rtBuffer, vs->number + 5) + (y * 40 + x) * 8; - if (!twobufs) { + _backbuff_ptr = vs->screenPtr + (y * NUM_STRIPS + x) * 8; + if (twobufs) + _bgbak_ptr = _vm->getResourceAddress(rtBuffer, vs->number + 5) + (y * NUM_STRIPS + x) * 8; + else _bgbak_ptr = _backbuff_ptr; - } - _mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + (y * 40 + x); + + _mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + (y * NUM_STRIPS + x); where_draw_ptr = _bgbak_ptr; decompressBitmap(); @@ -827,12 +892,12 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, _bgbak_ptr = where_draw_ptr; if (_vm->hasCharsetMask(sx << 3, y, (sx + 1) << 3, bottom)) { - if (flag & dbClear || (!lightsOn && vs->number == 0)) + if (flag & dbClear || !lightsOn) clear8ColWithMasking(); else draw8ColWithMasking(); } else { - if (flag & dbClear || (!lightsOn && vs->number == 0)) + if (flag & dbClear || !lightsOn) clear8Col(); else blit(_backbuff_ptr, _bgbak_ptr, 8, h); @@ -841,7 +906,7 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, CHECK_HEAP; if (flag & dbDrawMaskOnBoth) { _z_plane_ptr = zplane_list[1] + READ_LE_UINT16(zplane_list[1] + stripnr * 2 + 8); - _mask_ptr_dest = _vm->getResourceAddress(rtBuffer, 9) + y * 40 + x; + _mask_ptr_dest = _vm->getResourceAddress(rtBuffer, 9) + y * NUM_STRIPS + x; if (_useOrDecompress && flag & dbAllowMaskOr) decompressMaskImgOr(); else @@ -862,7 +927,7 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, else offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2 + 8); - _mask_ptr_dest = _vm->getResourceAddress(rtBuffer, 9) + y * 40 + x + _imgBufOffs[i]; + _mask_ptr_dest = _vm->getResourceAddress(rtBuffer, 9) + y * NUM_STRIPS + x + _imgBufOffs[i]; if (offs) { _z_plane_ptr = zplane_list[i] + offs; @@ -875,7 +940,7 @@ void Gdi::drawBitmap(byte *ptr, VirtScreen *vs, int x, int y, int h, if (_useOrDecompress && flag & dbAllowMaskOr); /* nothing */ else for (int h = 0; h < _numLinesToProcess; h++) - _mask_ptr_dest[h * 40] = 0; + _mask_ptr_dest[h * NUM_STRIPS] = 0; /* needs better abstraction, FIXME */ } } @@ -1050,13 +1115,12 @@ void Gdi::draw8ColWithMasking() if (!(maskbits & 0x01)) dst[7] = src[7]; } else { -/* alignment safe */ ((uint32 *)dst)[0] = ((uint32 *)src)[0]; ((uint32 *)dst)[1] = ((uint32 *)src)[1]; } src += 320; dst += 320; - mask += 40; + mask += NUM_STRIPS; } while (--height); } @@ -1069,9 +1133,7 @@ void Gdi::clear8ColWithMasking() do { maskbits = *mask; - if (!maskbits) { - ((uint32 *)dst)[1] = ((uint32 *)dst)[0] = 0; - } else { + if (maskbits) { if (!(maskbits & 0x80)) dst[0] = 0; if (!(maskbits & 0x40)) @@ -1088,9 +1150,12 @@ void Gdi::clear8ColWithMasking() dst[6] = 0; if (!(maskbits & 0x01)) dst[7] = 0; + } else { + ((uint32 *)dst)[0] = 0; + ((uint32 *)dst)[1] = 0; } dst += 320; - mask += 40; + mask += NUM_STRIPS; } while (--height); } @@ -1098,8 +1163,10 @@ void Gdi::clear8Col() { int height = _numLinesToProcess; byte *dst = _backbuff_ptr; + do { - ((uint32 *)dst)[1] = ((uint32 *)dst)[0] = 0; + ((uint32 *)dst)[0] = 0; + ((uint32 *)dst)[1] = 0; dst += 320; } while (--height); } @@ -1120,14 +1187,14 @@ void Gdi::decompressMaskImg() do { *dst = c; - dst += 40; + dst += NUM_STRIPS; if (!--height) return; } while (--b); } else { do { *dst = *src++; - dst += 40; + dst += NUM_STRIPS; if (!--height) return; } while (--b); @@ -1150,14 +1217,14 @@ void Gdi::decompressMaskImgOr() do { *dst |= c; - dst += 40; + dst += NUM_STRIPS; if (!--height) return; } while (--b); } else { do { *dst |= *src++; - dst += 40; + dst += NUM_STRIPS; if (!--height) return; } while (--b); @@ -1173,7 +1240,8 @@ void Scumm::redrawBGStrip(int start, int num) _curVirtScreen = &virtscr[0]; - gfxUsageBits[s] |= 0x80000000; + for (int i = 0; i < num; i++) + gfxUsageBits[s + i] |= 0x80000000; /*if (_curVirtScreen->height < _scrHeight) { warning("Screen Y size %d < Room height %d", @@ -1681,7 +1749,7 @@ void Scumm::restoreBG(int left, int top, int right, int bottom) backbuff = vs->screenPtr + height; bgbak = getResourceAddress(rtBuffer, vs->number + 5) + height; - mask = getResourceAddress(rtBuffer, 9) + top * 40 + (left >> 3) + _screenStartStrip; + mask = getResourceAddress(rtBuffer, 9) + top * NUM_STRIPS + (left >> 3) + _screenStartStrip; if (vs->number == 0) { mask += vs->topline * 216; } @@ -1695,7 +1763,7 @@ void Scumm::restoreBG(int left, int top, int right, int bottom) if (vs->number == 0 && charset._hasMask && height) { do { memset(mask, 0, widthmod); - mask += 40; + mask += NUM_STRIPS; } while (--height); } } else { @@ -1751,12 +1819,12 @@ void Scumm::setVirtscreenDirty(VirtScreen *vs, int left, int top, int right, int int lp = left >> 3; int rp = right >> 3; - if (lp >= 40 || rp < 0) + if (lp >= NUM_STRIPS || rp < 0) return; if (lp < 0) lp = 0; - if (rp >= 40) - rp = 39; + if (rp >= NUM_STRIPS) + rp = NUM_STRIPS - 1; while (lp <= rp) { if (top < vs->tdirty[lp]) @@ -1867,14 +1935,14 @@ void Scumm::transitionEffect(int a) b = tab_2[i * 4 + 3]; if (t == b) { while (l <= r) { - if (l >= 0 && l < 40 && (uint) t < (uint) bottom) { + if (l >= 0 && l < NUM_STRIPS && (uint) t < (uint) bottom) { virtscr[0].tdirty[l] = t << 3; virtscr[0].bdirty[l] = (t + 1) << 3; } l++; } } else { - if (l < 0 || l >= 40 || b <= t) + if (l < 0 || l >= NUM_STRIPS || b <= t) continue; if (b > bottom) b = bottom; @@ -2112,7 +2180,7 @@ void Scumm::cameraMoved() assert(camera._cur.x >= 160 && camera._cur.y >= 100); _screenStartStrip = (camera._cur.x - 160) >> 3; - _screenEndStrip = _screenStartStrip + 39; + _screenEndStrip = _screenStartStrip + NUM_STRIPS - 1; virtscr[0].xstart = _screenStartStrip << 3; _screenLeft = camera._cur.x - 160; @@ -2126,7 +2194,7 @@ void Scumm::cameraMoved() } _screenStartStrip = (camera._cur.x >> 3) - 20; - _screenEndStrip = _screenStartStrip + 39; + _screenEndStrip = _screenStartStrip + NUM_STRIPS - 1; virtscr[0].xstart = _screenStartStrip << 3; } } @@ -2251,7 +2319,7 @@ void Gdi::resetBackground(int top, int bottom, int strip) if (bottom > vs->bdirty[strip]) vs->bdirty[strip] = bottom; - offs = (top * 40 + _vm->_screenStartStrip + strip); + offs = (top * NUM_STRIPS + _vm->_screenStartStrip + strip); _mask_ptr = _vm->getResourceAddress(rtBuffer, 9) + offs; _bgbak_ptr = _vm->getResourceAddress(rtBuffer, 5) + (offs << 3); _backbuff_ptr = vs->screenPtr + (offs << 3); @@ -2294,10 +2362,10 @@ byte Scumm::isMaskActiveAt(int l, int t, int r, int b, byte *mem) t = 0; r >>= 3; - if (r > 39) - r = 39; + if (r > NUM_STRIPS-1) + r = NUM_STRIPS-1; - mem += l + t * 40; + mem += l + t * NUM_STRIPS; w = r - l; h = b - t + 1; @@ -2307,7 +2375,7 @@ byte Scumm::isMaskActiveAt(int l, int t, int r, int b, byte *mem) if (mem[i]) { return true; } - mem += 40; + mem += NUM_STRIPS; } while (--h); return false; @@ -23,6 +23,9 @@ #ifndef GFX_H #define GFX_H +enum { + NUM_STRIPS = 40 +}; enum VideoMode { /* Video scalers */ VIDEO_SCALE = 0, @@ -52,7 +55,7 @@ struct VirtScreen { /* Virtual screen areas */ int number; uint16 unk1; uint16 topline; - uint16 width,height; + uint16 width, height; uint16 size; byte alloctwobuffers; byte scrollable; @@ -78,10 +81,10 @@ struct ColorCycle { /* Palette cycles */ }; struct BlastObject { /* BlastObjects to draw */ - uint16 number,areaX,areaY,areaWidth,areaHeight; - int16 posX,posY; - uint16 width,height; - uint16 unk3,unk4,image; + uint16 number, areaX, areaY, areaWidth, areaHeight; + int16 posX, posY; + uint16 width, height; + uint16 unk3, unk4, image; uint16 mode; }; @@ -92,7 +95,7 @@ struct BlastObject { /* BlastObjects to draw */ struct BompHeader { /* Bomp header */ uint16 unk; - uint16 width,height; + uint16 width, height; } GCC_PACK; #if !defined(__GNUC__) @@ -102,7 +105,7 @@ struct BompHeader { /* Bomp header */ struct BompDrawData { /* Bomp graphics data */ byte *out; int outwidth, outheight; - int x,y; + int x, y; byte scale_x, scale_y; byte *dataptr; int srcwidth, srcheight; diff --git a/script_v1.cpp b/script_v1.cpp index 3ad7289798..2fa4c55890 100644 --- a/script_v1.cpp +++ b/script_v1.cpp @@ -1545,13 +1545,11 @@ void Scumm::o5_lights() b = fetchScriptByte(); c = fetchScriptByte(); - warning("o5_lights(%d,%d,%d): lights not implemented", a, b, c); - if (c == 0) _vars[VAR_CURRENT_LIGHTS] = a; else if (c == 1) { - _lightDx = a; - _lightDy = b; + _flashlightXStrips = a; + _flashlightYStrips = b; } _fullRedraw = 1; } @@ -755,7 +755,8 @@ public: byte _newEffect, _switchRoomEffect2, _switchRoomEffect; bool _doEffect; - uint16 _lightDx, _lightDy; + uint16 _flashlightXStrips, _flashlightYStrips; + bool _flashlightIsDrawn; void getGraphicsPerformance(); void initScreens(int a, int b, int w, int h); |