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