1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Mission begin melt/wipe screen special effect.
31 *
32 *-----------------------------------------------------------------------------
33 */
34
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "z_zone.h"
41 #include "doomdef.h"
42 #include "i_video.h"
43 #include "v_video.h"
44 #include "m_random.h"
45 #include "f_wipe.h"
46 #ifdef GL_DOOM
47 #include "gl_struct.h"
48 #endif
49 #include "e6y.h"//e6y
50
51 //
52 // SCREEN WIPE PACKAGE
53 //
54
55 // Parts re-written to support true-color video modes. Column-major
56 // formatting removed. - POPE
57
58 // CPhipps - macros for the source and destination screens
59 #define SRC_SCR 2
60 #define DEST_SCR 3
61
62 static screeninfo_t wipe_scr_start;
63 static screeninfo_t wipe_scr_end;
64 static screeninfo_t wipe_scr;
65
66 // e6y: resolution limitation is removed
67 static int *y_lookup = NULL;
68
69 // e6y: resolution limitation is removed
R_InitMeltRes(void)70 void R_InitMeltRes(void)
71 {
72 if (y_lookup) free(y_lookup);
73
74 y_lookup = calloc(1, SCREENWIDTH * sizeof(*y_lookup));
75 }
76
wipe_initMelt(int ticks)77 static int wipe_initMelt(int ticks)
78 {
79 int i;
80
81 if (V_GetMode() != VID_MODEGL)
82 {
83 // copy start screen to main screen
84 for(i=0;i<SCREENHEIGHT;i++)
85 memcpy(wipe_scr.data+i*wipe_scr.byte_pitch,
86 wipe_scr_start.data+i*wipe_scr_start.byte_pitch,
87 SCREENWIDTH*V_GetPixelDepth());
88 }
89
90 // setup initial column positions (y<0 => not ready to scroll yet)
91 y_lookup[0] = -(M_Random()%16);
92 for (i=1;i<SCREENWIDTH;i++)
93 {
94 int r = (M_Random()%3) - 1;
95 y_lookup[i] = y_lookup[i-1] + r;
96 if (y_lookup[i] > 0)
97 y_lookup[i] = 0;
98 else
99 if (y_lookup[i] == -16)
100 y_lookup[i] = -15;
101 }
102 return 0;
103 }
104
wipe_doMelt(int ticks)105 static int wipe_doMelt(int ticks)
106 {
107 dboolean done = true;
108 int i;
109 const int depth = V_GetPixelDepth();
110
111 while (ticks--) {
112 for (i=0;i<(SCREENWIDTH);i++) {
113 if (y_lookup[i]<0) {
114 y_lookup[i]++;
115 done = false;
116 continue;
117 }
118 if (y_lookup[i] < SCREENHEIGHT) {
119 byte *s, *d;
120 int j, k, dy;
121
122 /* cph 2001/07/29 -
123 * The original melt rate was 8 pixels/sec, i.e. 25 frames to melt
124 * the whole screen, so make the melt rate depend on SCREENHEIGHT
125 * so it takes no longer in high res
126 */
127 dy = (y_lookup[i] < 16) ? y_lookup[i]+1 : SCREENHEIGHT/25;
128 if (y_lookup[i]+dy >= SCREENHEIGHT)
129 dy = SCREENHEIGHT - y_lookup[i];
130
131 if (V_GetMode() != VID_MODEGL) {
132 s = wipe_scr_end.data + (y_lookup[i]*wipe_scr_end.byte_pitch+(i*depth));
133 d = wipe_scr.data + (y_lookup[i]*wipe_scr.byte_pitch+(i*depth));
134 for (j=dy;j;j--) {
135 for (k=0; k<depth; k++)
136 d[k] = s[k];
137 d += wipe_scr.byte_pitch;
138 s += wipe_scr_end.byte_pitch;
139 }
140 }
141 y_lookup[i] += dy;
142 if (V_GetMode() != VID_MODEGL) {
143 s = wipe_scr_start.data + (i*depth);
144 d = wipe_scr.data + (y_lookup[i]*wipe_scr.byte_pitch+(i*depth));
145 for (j=SCREENHEIGHT-y_lookup[i];j;j--) {
146 for (k=0; k<depth; k++)
147 d[k] = s[k];
148 d += wipe_scr.byte_pitch;
149 s += wipe_scr_end.byte_pitch;
150 }
151 }
152 done = false;
153 }
154 }
155 }
156 #ifdef GL_DOOM
157 if (V_GetMode() == VID_MODEGL)
158 {
159 gld_wipe_doMelt(ticks, y_lookup);
160 }
161 #endif
162 return done;
163 }
164
165 // CPhipps - modified to allocate and deallocate screens[2 to 3] as needed, saving memory
166
wipe_exitMelt(int ticks)167 static int wipe_exitMelt(int ticks)
168 {
169 #ifdef GL_DOOM
170 if (V_GetMode() == VID_MODEGL)
171 {
172 gld_wipe_exitMelt(ticks);
173 return 0;
174 }
175 #endif
176
177 V_FreeScreen(&wipe_scr_start);
178 wipe_scr_start.width = 0;
179 wipe_scr_start.height = 0;
180 V_FreeScreen(&wipe_scr_end);
181 wipe_scr_end.width = 0;
182 wipe_scr_end.height = 0;
183 // Paranoia
184 screens[SRC_SCR] = wipe_scr_start;
185 screens[DEST_SCR] = wipe_scr_end;
186 return 0;
187 }
188
wipe_StartScreen(void)189 int wipe_StartScreen(void)
190 {
191 if(!render_wipescreen||wasWiped) return 0;//e6y
192 wasWiped = true;//e6y
193
194 #ifdef GL_DOOM
195 if (V_GetMode() == VID_MODEGL)
196 {
197 gld_wipe_StartScreen();
198 return 0;
199 }
200 #endif
201
202 wipe_scr_start.width = SCREENWIDTH;
203 wipe_scr_start.height = SCREENHEIGHT;
204 wipe_scr_start.byte_pitch = screens[0].byte_pitch;
205 wipe_scr_start.short_pitch = screens[0].short_pitch;
206 wipe_scr_start.int_pitch = screens[0].int_pitch;
207
208 //e6y: fixed slowdown at 1024x768 on some systems
209 if (!(wipe_scr_start.byte_pitch % 1024))
210 wipe_scr_start.byte_pitch += 32;
211
212 wipe_scr_start.not_on_heap = false;
213 V_AllocScreen(&wipe_scr_start);
214 screens[SRC_SCR] = wipe_scr_start;
215 V_CopyRect(0, SRC_SCR, 0, 0, SCREENWIDTH, SCREENHEIGHT, VPT_NONE); // Copy start screen to buffer
216 return 0;
217 }
218
wipe_EndScreen(void)219 int wipe_EndScreen(void)
220 {
221 if(!render_wipescreen||!wasWiped) return 0;//e6y
222 wasWiped = false;//e6y
223
224 #ifdef GL_DOOM
225 if (V_GetMode() == VID_MODEGL)
226 {
227 gld_wipe_EndScreen();
228 return 0;
229 }
230 #endif
231
232 wipe_scr_end.width = SCREENWIDTH;
233 wipe_scr_end.height = SCREENHEIGHT;
234 wipe_scr_end.byte_pitch = screens[0].byte_pitch;
235 wipe_scr_end.short_pitch = screens[0].short_pitch;
236 wipe_scr_end.int_pitch = screens[0].int_pitch;
237
238 //e6y: fixed slowdown at 1024x768 on some systems
239 if (!(wipe_scr_end.byte_pitch % 1024))
240 wipe_scr_end.byte_pitch += 32;
241
242 wipe_scr_end.not_on_heap = false;
243 V_AllocScreen(&wipe_scr_end);
244 screens[DEST_SCR] = wipe_scr_end;
245 V_CopyRect(0, DEST_SCR, 0, 0, SCREENWIDTH, SCREENHEIGHT, VPT_NONE); // Copy end screen to buffer
246 V_CopyRect(SRC_SCR, 0, 0, 0, SCREENWIDTH, SCREENHEIGHT, VPT_NONE); // restore start screen
247 return 0;
248 }
249
250 // killough 3/5/98: reformatted and cleaned up
wipe_ScreenWipe(int ticks)251 int wipe_ScreenWipe(int ticks)
252 {
253 static dboolean go; // when zero, stop the wipe
254 if(!render_wipescreen) return 0;//e6y
255 if (!go) // initial stuff
256 {
257 go = 1;
258 wipe_scr = screens[0];
259 wipe_initMelt(ticks);
260 }
261 // do a piece of wipe-in
262 if (wipe_doMelt(ticks)) // final stuff
263 {
264 wipe_exitMelt(ticks);
265 go = 0;
266 }
267 return !go;
268 }
269