1982 | | void Scumm::unkScreenEffect6() |
| 1982 | // Update width x height areas of the screen, in random order, until the whole |
| 1983 | // screen has been updated. For instance: |
| 1984 | // |
| 1985 | // dissolveEffect(1, 1) produces a pixel-by-pixel dissolve |
| 1986 | // dissolveEffect(8, 8) produces a square-by-square dissolve |
| 1987 | // dissolveEffect(virtsrc[0].width, 1) produces a line-by-line dissolve |
| 1988 | |
| 1989 | void Scumm::dissolveEffect(int width, int height) |
1984 | | /* XXX: not implemented */ |
1985 | | warning("stub unkScreenEffect6"); |
| 1991 | VirtScreen *vs = &virtscr[0]; |
| 1992 | int *offsets; |
| 1993 | int blits_before_refresh, blits; |
| 1994 | int x, y; |
| 1995 | int w, h; |
| 1996 | int i; |
| 1997 | |
| 1998 | // There's probably some less memory-hungry way of doing this. But |
| 1999 | // since we're only dealing with relatively small images, it shouldn't |
| 2000 | // be too bad. |
| 2001 | |
| 2002 | w = vs->width / width; |
| 2003 | h = vs->height / height; |
| 2004 | |
| 2005 | // When used used correctly, vs->width % width and vs->height % height |
| 2006 | // should both be zero, but just to be safe... |
| 2007 | |
| 2008 | if (vs->width % width) |
| 2009 | w++; |
| 2010 | |
| 2011 | if (vs->height % height) |
| 2012 | h++; |
| 2013 | |
| 2014 | offsets = (int *) malloc(w * h * sizeof(int)); |
| 2015 | if (offsets == NULL) { |
| 2016 | warning("dissolveEffect: out of memory"); |
| 2017 | return; |
| 2018 | } |
| 2019 | |
| 2020 | // Create a permutation of offsets into the frame buffer |
| 2021 | |
| 2022 | if (width == 1 && height == 1) { |
| 2023 | // Optimized case for pixel-by-pixel dissolve |
| 2024 | |
| 2025 | for (i = 0; i < vs->size; i++) |
| 2026 | offsets[i] = i; |
| 2027 | |
| 2028 | for (i = 1; i < w * h; i++) { |
| 2029 | int j; |
| 2030 | |
| 2031 | j = getRandomNumber(i - 1); |
| 2032 | offsets[i] = offsets[j]; |
| 2033 | offsets[j] = i; |
| 2034 | } |
| 2035 | } else { |
| 2036 | int *offsets2; |
| 2037 | |
| 2038 | for (i = 0, x = 0; x < vs->width; x += width) |
| 2039 | for (y = 0; y < vs->height; y += height) |
| 2040 | offsets[i++] = y * vs->width + x; |
| 2041 | |
| 2042 | offsets2 = (int *) malloc(w * h * sizeof(int)); |
| 2043 | if (offsets2 == NULL) { |
| 2044 | warning("dissolveEffect: out of memory"); |
| 2045 | free(offsets); |
| 2046 | return; |
| 2047 | } |
| 2048 | |
| 2049 | memcpy(offsets2, offsets, w * h * sizeof(int)); |
| 2050 | |
| 2051 | for (i = 1; i < w * h; i++) { |
| 2052 | int j; |
| 2053 | |
| 2054 | j = getRandomNumber(i - 1); |
| 2055 | offsets[i] = offsets[j]; |
| 2056 | offsets[j] = offsets2[i]; |
| 2057 | } |
| 2058 | |
| 2059 | free(offsets2); |
| 2060 | } |
| 2061 | |
| 2062 | // Blit the image piece by piece to the screen. The idea here is that |
| 2063 | // the whole update should take about a quarter of a second, assuming |
| 2064 | // most of the time is spent in waitForTimer(). It looks good to me, |
| 2065 | // but might still need some tuning. |
| 2066 | |
| 2067 | updatePalette(); |
| 2068 | |
| 2069 | blits = 0; |
| 2070 | blits_before_refresh = (3 * w * h) / 25; |
| 2071 | |
| 2072 | for (i = 0; i < w * h; i++) { |
| 2073 | x = offsets[i] % vs->width; |
| 2074 | y = offsets[i] / vs->width; |
| 2075 | _system->copy_rect(vs->screenPtr + vs->xstart + y * vs->width + x, vs->width, x, y, width, height); |
| 2076 | |
| 2077 | if (++blits >= blits_before_refresh) { |
| 2078 | blits = 0; |
| 2079 | _system->update_screen(); |
| 2080 | waitForTimer(30); |
| 2081 | } |
| 2082 | } |
| 2083 | |
| 2084 | free(offsets); |
| 2085 | |
| 2086 | if (blits != 0) { |
| 2087 | _system->update_screen(); |
| 2088 | waitForTimer(30); |
| 2089 | } |