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 | } |