From 73b031515eadf2865871f3a8a09df9627f7c113e Mon Sep 17 00:00:00 2001 From: Paweł Kołodziejski Date: Sun, 25 Aug 2002 18:40:23 +0000 Subject: applied patch #599909 svn-id: r4855 --- scumm/gfx.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- scumm/scumm.h | 12 +++--- 2 files changed, 125 insertions(+), 17 deletions(-) (limited to 'scumm') diff --git a/scumm/gfx.cpp b/scumm/gfx.cpp index 5431c1aac0..cda2598c70 100644 --- a/scumm/gfx.cpp +++ b/scumm/gfx.cpp @@ -674,7 +674,7 @@ void Scumm::fadeIn(int effect) transitionEffect(effect - 1); break; case 128: - unkScreenEffect6(); + dissolveEffect(8, 8); break; case 130: unkScreenEffect1(); @@ -689,7 +689,7 @@ void Scumm::fadeIn(int effect) unkScreenEffect4(); break; case 134: - unkScreenEffect5(0); + dissolveEffect(1, 1); break; case 135: unkScreenEffect5(1); @@ -731,7 +731,7 @@ void Scumm::fadeOut(int a) transitionEffect(a - 1); break; case 128: - unkScreenEffect6(); + dissolveEffect(8, 8); break; case 129: // Just blit screen 0 to the display (i.e. display will be black) @@ -739,7 +739,7 @@ void Scumm::fadeOut(int a) updateDirtyScreen(0); break; case 134: - unkScreenEffect5(0); + dissolveEffect(1, 1); break; case 135: unkScreenEffect5(1); @@ -1979,16 +1979,124 @@ void Scumm::transitionEffect(int a) } } -void Scumm::unkScreenEffect6() -{ - /* XXX: not implemented */ - warning("stub unkScreenEffect6"); +// Update width x height areas of the screen, in random order, until the whole +// screen has been updated. For instance: +// +// dissolveEffect(1, 1) produces a pixel-by-pixel dissolve +// dissolveEffect(8, 8) produces a square-by-square dissolve +// dissolveEffect(virtsrc[0].width, 1) produces a line-by-line dissolve + +void Scumm::dissolveEffect(int width, int height) { + VirtScreen *vs = &virtscr[0]; + int *offsets; + int blits_before_refresh, blits; + int x, y; + int w, h; + int i; + + // There's probably some less memory-hungry way of doing this. But + // since we're only dealing with relatively small images, it shouldn't + // be too bad. + + w = vs->width / width; + h = vs->height / height; + + // When used used correctly, vs->width % width and vs->height % height + // should both be zero, but just to be safe... + + if (vs->width % width) + w++; + + if (vs->height % height) + h++; + + offsets = (int *) malloc(w * h * sizeof(int)); + if (offsets == NULL) { + warning("dissolveEffect: out of memory"); + return; + } + + // Create a permutation of offsets into the frame buffer + + if (width == 1 && height == 1) { + // Optimized case for pixel-by-pixel dissolve + + for (i = 0; i < vs->size; i++) + offsets[i] = i; + + for (i = 1; i < w * h; i++) { + int j; + + j = getRandomNumber(i - 1); + offsets[i] = offsets[j]; + offsets[j] = i; + } + } else { + int *offsets2; + + for (i = 0, x = 0; x < vs->width; x += width) + for (y = 0; y < vs->height; y += height) + offsets[i++] = y * vs->width + x; + + offsets2 = (int *) malloc(w * h * sizeof(int)); + if (offsets2 == NULL) { + warning("dissolveEffect: out of memory"); + free(offsets); + return; + } + + memcpy(offsets2, offsets, w * h * sizeof(int)); + + for (i = 1; i < w * h; i++) { + int j; + + j = getRandomNumber(i - 1); + offsets[i] = offsets[j]; + offsets[j] = offsets2[i]; + } + + free(offsets2); + } + + // Blit the image piece by piece to the screen. The idea here is that + // the whole update should take about a quarter of a second, assuming + // most of the time is spent in waitForTimer(). It looks good to me, + // but might still need some tuning. + + updatePalette(); + + blits = 0; + blits_before_refresh = (3 * w * h) / 25; + + for (i = 0; i < w * h; i++) { + x = offsets[i] % vs->width; + y = offsets[i] / vs->width; + _system->copy_rect(vs->screenPtr + vs->xstart + y * vs->width + x, vs->width, x, y, width, height); + + if (++blits >= blits_before_refresh) { + blits = 0; + _system->update_screen(); + waitForTimer(30); + } + } + + free(offsets); + + if (blits != 0) { + _system->update_screen(); + waitForTimer(30); + } } -void Scumm::unkScreenEffect5(int a) -{ +void Scumm::unkScreenEffect5(int a) { + // unkScreenEffect5(0), which is used by FOA during the opening + // cutscene when Indy opens the small statue, has been replaced by + // dissolveEffect(1, 1). + // + // I still don't know what unkScreenEffect5(1) is supposed to do. + /* XXX: not implemented */ - warning("stub unkScreenEffect5(%d)", a); + warning("stub unkScreenEffect(%d)", a); } void Scumm::setShake(int mode) diff --git a/scumm/scumm.h b/scumm/scumm.h index 8147020f33..613cde7945 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -55,8 +55,8 @@ enum { NUM_SCRIPT_SLOT = 40, NUM_LOCALSCRIPT = 60, NUM_SHADOW_PALETTE = 8, - MAX_ACTORS = 30, - KEY_SET_OPTIONS = 3456 // WinCE + MAX_ACTORS = 30, + KEY_SET_OPTIONS = 3456 // WinCE }; enum { @@ -292,9 +292,9 @@ enum GameFeatures { GF_DEFAULT = GF_USE_KEY, GF_SMALL_HEADER = 32, - GF_EXTERNAL_CHARSET = GF_SMALL_HEADER, - GF_SMALL_NAMES = 64, - GF_OLD_BUNDLE = 128, + GF_EXTERNAL_CHARSET = GF_SMALL_HEADER, + GF_SMALL_NAMES = 64, + GF_OLD_BUNDLE = 128, GF_16COLOR = 256, GF_OLD256 = 512, GF_AUDIOTRACKS = 1024, @@ -833,8 +833,8 @@ public: void unkScreenEffect3(); void unkScreenEffect4(); void unkScreenEffect5(int a); - void unkScreenEffect6(); void transitionEffect(int a); // former unkScreenEffect7 + void dissolveEffect(int width, int height); // former unkScreenEffect5(0) and unkScreenEffect6 void decompressBomp(byte *dst, byte *src, int w, int h); uint _shakeFrame; -- cgit v1.2.3