Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Routines to display the credits.
23
 *
24
 */
25
 
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <stdarg.h>
30
#include <ctype.h>
31
#include <utility>
32
 
33
#include "dxxerror.h"
34
#include "pstypes.h"
35
#include "gr.h"
36
#include "window.h"
37
#include "key.h"
38
#include "mouse.h"
39
#include "palette.h"
40
#include "game.h"
41
#include "timer.h"
42
#include "gamefont.h"
43
#include "pcx.h"
44
#include "credits.h"
45
#include "u_mem.h"
46
#include "screens.h"
47
#include "digi.h"
48
#include "rbaudio.h"
49
#include "text.h"
50
#include "songs.h"
51
#include "menu.h"
52
#include "config.h"
53
#include "physfsx.h"
54
#if defined(DXX_BUILD_DESCENT_II)
55
#include "mission.h"
56
#include "gamepal.h"
57
#include "args.h"
58
#endif
59
#include "piggy.h"
60
#include <memory>
61
 
62
#define ROW_SPACING                     (SHEIGHT / 17)
63
#define NUM_LINES                       20 //14
64
#define MAKE_CREDITS_PAIR(F)    std::pair<const char *, int>(F ".tex", sizeof(F) + 1)
65
#if defined(DXX_BUILD_DESCENT_I)
66
#define CREDITS_FILE                    MAKE_CREDITS_PAIR("credits")
67
#elif defined(DXX_BUILD_DESCENT_II)
68
#define CREDITS_FILE                    (       \
69
        PHYSFSX_exists("mcredits.tex", 1)       \
70
                ? MAKE_CREDITS_PAIR("mcredits") \
71
                : PHYSFSX_exists("ocredits.tex", 1)     \
72
                        ? MAKE_CREDITS_PAIR("ocredits")         \
73
                        : MAKE_CREDITS_PAIR("credits")  \
74
        )
75
#define ALLOWED_CHAR                    (!Current_mission ? 'R' : (is_SHAREWARE ? 'S' : 'R'))
76
#endif
77
 
78
namespace {
79
 
80
struct credits : ignore_window_pointer_t
81
{
82
        RAIIPHYSFS_File file;
83
        int have_bin_file;
84
        std::array<PHYSFSX_gets_line_t<80>, NUM_LINES> buffer;
85
        int buffer_line;
86
        int first_line_offset;
87
        int extra_inc;
88
        int done;
89
        int row;
90
        grs_main_bitmap backdrop;
91
};
92
 
93
}
94
 
95
namespace dsx {
96
static window_event_result credits_handler(window *, const d_event &event, credits *cr)
97
{
98
        int l, y;
99
        window_event_result result;
100
 
101
        switch (event.type)
102
        {
103
                case EVENT_KEY_COMMAND:
104
                        if ((result = call_default_handler(event)) == window_event_result::ignored)     // if not print screen, debug etc
105
                        {
106
                                return window_event_result::close;
107
                        }
108
                        return result;
109
 
110
                case EVENT_MOUSE_BUTTON_DOWN:
111
                case EVENT_MOUSE_BUTTON_UP:
112
                        if (event_mouse_get_button(event) == MBTN_LEFT || event_mouse_get_button(event) == MBTN_RIGHT)
113
                        {
114
                                return window_event_result::close;
115
                        }
116
                        break;
117
 
118
                case EVENT_JOYSTICK_BUTTON_DOWN:
119
                        return window_event_result::close;
120
 
121
                case EVENT_IDLE:
122
                        if (cr->done>NUM_LINES)
123
                        {
124
                                return window_event_result::close;
125
                        }
126
                        break;
127
 
128
                case EVENT_WINDOW_DRAW:
129
                        {
130
#if defined(DXX_BUILD_DESCENT_I)
131
                        timer_delay(F1_0/17);
132
#elif defined(DXX_BUILD_DESCENT_II)
133
                        timer_delay(F1_0/28);
134
#endif
135
 
136
                        if (cr->row == 0)
137
                        {
138
                                do {
139
                                        cr->buffer_line = (cr->buffer_line+1) % NUM_LINES;
140
#if defined(DXX_BUILD_DESCENT_II)
141
                                get_line:;
142
#endif
143
                                        if (PHYSFSX_fgets( cr->buffer[cr->buffer_line], cr->file ))     {
144
                                                char *p;
145
                                                if (cr->have_bin_file) // is this a binary tbl file
146
                                                        decode_text_line (cr->buffer[cr->buffer_line]);
147
#if defined(DXX_BUILD_DESCENT_I)
148
                                                p = strchr(&cr->buffer[cr->buffer_line][0],'\n');
149
                                                if (p) *p = '\0';
150
#elif defined(DXX_BUILD_DESCENT_II)
151
                                                p = cr->buffer[cr->buffer_line];
152
                                                if (p[0] == ';')
153
                                                        goto get_line;
154
 
155
                                                if (p[0] == '%')
156
                                                {
157
                                                        if (p[1] == ALLOWED_CHAR)
158
                                                        {
159
                                                                for (int i = 0; p[i]; i++)
160
                                                                        p[i] = p[i+2];
161
                                                        }
162
                                                        else
163
                                                                goto get_line;
164
                                                }
165
#endif  
166
                                        } else  {
167
                                                //fseek( file, 0, SEEK_SET);
168
                                                cr->buffer[cr->buffer_line][0] = 0;
169
                                                cr->done++;
170
                                        }
171
                                } while (cr->extra_inc--);
172
                                cr->extra_inc = 0;
173
                        }
174
 
175
                        // cheap but effective: towards end of credits sequence, fade out the music volume
176
                        if (cr->done >= NUM_LINES-16)
177
                        {
178
                                static int curvol = -10;
179
                                if (curvol == -10)
180
                                        curvol = GameCfg.MusicVolume;
181
                                if (curvol > (NUM_LINES-cr->done)/2)
182
                                {
183
                                        curvol = (NUM_LINES-cr->done)/2;
184
                                        songs_set_volume(curvol);
185
                                }
186
                        }
187
 
188
                        y = cr->first_line_offset - cr->row;
189
                        auto &canvas = *grd_curcanv;
190
                        show_fullscr(canvas, cr->backdrop);
191
                        for (uint_fast32_t j=0; j != NUM_LINES; ++j, y += ROW_SPACING)
192
                        {
193
                                l = (cr->buffer_line + j + 1 ) %  NUM_LINES;
194
                                const char *s = cr->buffer[l];
195
                                if (!s)
196
                                        continue;
197
 
198
                                const grs_font *cv_font;
199
                                if ( s[0] == '!' ) {
200
                                        s++;
201
                                        cv_font = canvas.cv_font;
202
                                } else
203
                                {
204
                                        const auto c = s[0];
205
                                        cv_font = (c == '$'
206
                                                ? (++s, HUGE_FONT)
207
                                                : (c == '*')
208
                                                        ? (++s, MEDIUM3_FONT)
209
                                                        : MEDIUM2_FONT
210
                                                ).get();
211
                                }
212
 
213
                                const auto tempp = strchr( s, '\t' );
214
                                if ( !tempp )   {
215
                                        // Wacky Fast Credits thing
216
                                        gr_string(canvas, *cv_font, 0x8000, y, s);
217
                                }
218
                        }
219
 
220
                        cr->row += SHEIGHT/200;
221
                        if (cr->row >= ROW_SPACING)
222
                                cr->row = 0;
223
                        break;
224
                        }
225
 
226
                case EVENT_WINDOW_CLOSE:
227
                        songs_set_volume(GameCfg.MusicVolume);
228
                        songs_play_song( SONG_TITLE, 1 );
229
                        std::default_delete<credits>()(cr);
230
                        break;
231
                default:
232
                        break;
233
        }
234
        return window_event_result::ignored;
235
}
236
}
237
 
238
namespace dsx {
239
 
240
static void credits_show_common(RAIIPHYSFS_File file, const int have_bin_file)
241
{
242
        palette_array_t backdrop_palette;
243
        auto cr = std::make_unique<credits>();
244
        *cr = {};
245
        cr->file = std::move(file);
246
        cr->have_bin_file = have_bin_file;
247
 
248
        set_screen_mode(SCREEN_MENU);
249
#if defined(DXX_BUILD_DESCENT_II)
250
        gr_use_palette_table( "credits.256" );
251
#endif
252
        cr->backdrop.bm_data=NULL;
253
 
254
        const auto pcx_error = pcx_read_bitmap(STARS_BACKGROUND, cr->backdrop,backdrop_palette);
255
        if (pcx_error != pcx_result::SUCCESS)
256
        {
257
                return;
258
        }
259
 
260
        songs_play_song( SONG_CREDITS, 1 );
261
 
262
        gr_remap_bitmap_good(cr->backdrop,backdrop_palette, -1, -1);
263
 
264
        gr_set_default_canvas();
265
        show_fullscr(*grd_curcanv, cr->backdrop);
266
        gr_palette_load( gr_palette );
267
 
268
        key_flush();
269
 
270
        credits *pcr = cr.get();
271
        const auto wind = window_create(grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, credits_handler, cr.release());
272
        if (!wind)
273
        {
274
                d_event event = { EVENT_WINDOW_CLOSE };
275
                credits_handler(NULL, event, pcr);
276
                return;
277
        }
278
 
279
        event_process_all();
280
}
281
 
282
void credits_show(const char *const filename)
283
{
284
        if (auto &&file = PHYSFSX_openReadBuffered(filename))
285
                credits_show_common(std::move(file), 1);
286
}
287
 
288
void credits_show()
289
{
290
        const auto &&credits_file = CREDITS_FILE;
291
        int have_bin_file = 0;
292
        auto file = PHYSFSX_openReadBuffered(credits_file.first);
293
        if (!file)
294
        {
295
                char nfile[32];
296
                snprintf(nfile, sizeof(nfile), "%.*sxb", credits_file.second, credits_file.first);
297
                file = PHYSFSX_openReadBuffered(nfile);
298
                if (!file)
299
                        Error("Missing CREDITS.TEX and CREDITS.TXB file\n");
300
                have_bin_file = 1;
301
        }
302
        credits_show_common(std::move(file), have_bin_file);
303
}
304
 
305
}