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