void do_automap( int key_code ) { int pcx_error; ubyte pal[256*3]; window *automap_wind = NULL; automap *am; CALLOC(am, automap, 1); if (am) { automap_wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *)) automap_handler, am); } if (automap_wind == NULL) { Warning("Out of memory"); return; } am->leave_mode = 0; am->pause_game = 1; // Set to 1 if everything is paused during automap...No pause during net. am->max_segments_away = 0; am->segment_limit = 1; am->num_edges = 0; am->highest_edge_index = -1; am->max_edges = Num_segments*12; MALLOC(am->edges, Edge_info, am->max_edges); MALLOC(am->drawingListBright, int, am->max_edges); if (!am->edges || !am->drawingListBright) { if (am->edges) d_free(am->edges); if (am->drawingListBright) d_free(am->drawingListBright); Warning("Out of memory"); return; } am->zoom = 0x9000; am->farthest_dist = (F1_0 * 20 * 50); // 50 segments away am->viewDist = 0; init_automap_colors(am); key_code = key_code; // disable warning... if ((Game_mode & GM_MULTI) && (!Endlevel_sequence)) am->pause_game = 0; if (am->pause_game) { window_set_visible(Game_wind, 0); } if (!am->pause_game) { am->old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE; // Save old wiggle ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE; // Turn off wiggle } //Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES); //make maybe smaller than max gr_set_current_canvas(NULL); automap_build_edge_list(am); if ( am->viewDist==0 ) am->viewDist = ZOOM_DEFAULT; am->viewMatrix = Objects[Players[Player_num].objnum].orient; am->tangles.p = PITCH_DEFAULT; am->tangles.h = 0; am->tangles.b = 0; am->view_target = Objects[Players[Player_num].objnum].pos; if (PlayerCfg.AutomapFreeFlight) vm_vec_scale_add(&am->view_position, &Objects[Players[Player_num].objnum].pos, &am->viewMatrix.fvec, -ZOOM_DEFAULT ); am->t1 = am->entry_time = timer_query(); am->t2 = am->t1; //Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum am->max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); am->segment_limit = am->max_segments_away; adjust_segment_limit(am, am->segment_limit); // ZICO - code from above to show frame in OGL correctly. Redundant, but better readable. // KREATOR - Now applies to all platforms so double buffering is supported gr_init_bitmap_data (&am->automap_background); pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME, &am->automap_background, BM_LINEAR, pal); if (pcx_error != PCX_ERROR_NONE) Error("File %s - PCX error: %s", MAP_BACKGROUND_FILENAME, pcx_errormsg(pcx_error)); gr_remap_bitmap_good(&am->automap_background, pal, -1, -1); gr_init_sub_canvas(&am->automap_view, &grd_curscreen->sc_canvas, (SWIDTH/23), (SHEIGHT/6), (SWIDTH/1.1), (SHEIGHT/1.45)); gr_palette_load( gr_palette ); Automap_active = 1; }
int state_save_all_sub(char *filename, char *desc, int between_levels) { int i,j; FILE * fp; grs_canvas * cnv; FInfo finfo; OSErr err; Str255 pfilename; if ( Game_mode & GM_MULTI ) { #ifdef MULTI_SAVE if ( !FindArg( "-multisave" ) ) #endif return 0; } fp = fopen( filename, "wb" ); if ( !fp ) { start_time(); return 0; } //Save id fwrite( dgss_id, sizeof(char)*4, 1, fp ); //Save version i = STATE_VERSION; fwrite( &i, sizeof(int), 1, fp ); //Save description fwrite( desc, sizeof(char)*DESC_LENGTH, 1, fp ); // Save the current screen shot... cnv = gr_create_canvas( THUMBNAIL_W, THUMBNAIL_H ); if ( cnv ) { gr_set_current_canvas( cnv ); if ( between_levels ) { char * pcx_file; ubyte pcx_palette[768]; grs_bitmap bmp; gr_clear_canvas( BM_XRGB(0,0,0) ); pcx_file = get_briefing_screen( Next_level_num ); if ( pcx_file != NULL ) { bmp.bm_data = NULL; if (pcx_read_bitmap( pcx_file, &bmp, BM_LINEAR, pcx_palette )==PCX_ERROR_NONE) { grs_point vertbuf[3]; gr_clear_canvas( TRANSPARENCY_COLOR ); vertbuf[0].x = vertbuf[0].y = -F1_0*6; // -6 pixel rows for ascpect vertbuf[1].x = vertbuf[1].y = 0; vertbuf[2].x = i2f(THUMBNAIL_W); vertbuf[2].y = i2f(THUMBNAIL_H+7); // + 7 pixel rows for ascpect scale_bitmap(&bmp, vertbuf ); gr_remap_bitmap_good( &cnv->cv_bitmap, pcx_palette, -1, -1 ); myfree( bmp.bm_data ); } } } else { render_frame(0); } fwrite( cnv->cv_bitmap.bm_data, THUMBNAIL_W*THUMBNAIL_H, 1, fp ); gr_free_canvas( cnv ); } else { ubyte color = 0; for ( i=0; i<THUMBNAIL_W*THUMBNAIL_H; i++ ) fwrite( &color, sizeof(ubyte), 1, fp ); } // Save the Between levels flag... fwrite( &between_levels, sizeof(int), 1, fp ); // Save the mission info... #ifdef MAC_SHAREWARE fwrite( mission_save, sizeof(char)*9, 1, fp); #else fwrite( &Mission_list[Current_mission_num], sizeof(char)*9, 1, fp ); #endif //Save level info fwrite( &Current_level_num, sizeof(int), 1, fp ); fwrite( &Next_level_num, sizeof(int), 1, fp ); //Save GameTime fwrite( &GameTime, sizeof(fix), 1, fp ); //Save player info fwrite( &Players[Player_num], sizeof(player), 1, fp ); // Save the current weapon info fwrite( &Primary_weapon, sizeof(byte), 1, fp ); fwrite( &Secondary_weapon, sizeof(byte), 1, fp ); // Save the difficulty level fwrite( &Difficulty_level, sizeof(int), 1, fp ); // Save the Cheats_enabled fwrite( &Cheats_enabled, sizeof(int), 1, fp ); fwrite( &Game_turbo_mode, sizeof(int), 1, fp ); if ( !between_levels ) { //Finish all morph objects for (i=0; i<=Highest_object_index; i++ ) { if ( (Objects[i].type != OBJ_NONE) && (Objects[i].render_type==RT_MORPH)) { morph_data *md; md = find_morph_data(&Objects[i]); if (md) { md->obj->control_type = md->morph_save_control_type; md->obj->movement_type = md->morph_save_movement_type; md->obj->render_type = RT_POLYOBJ; md->obj->mtype.phys_info = md->morph_save_phys_info; md->obj = NULL; } else { //maybe loaded half-morphed from disk Objects[i].flags |= OF_SHOULD_BE_DEAD; Objects[i].render_type = RT_POLYOBJ; Objects[i].control_type = CT_NONE; Objects[i].movement_type = MT_NONE; } } } //Save object info i = Highest_object_index+1; fwrite( &i, sizeof(int), 1, fp ); fwrite( Objects, sizeof(object)*i, 1, fp ); //Save wall info i = Num_walls; fwrite( &i, sizeof(int), 1, fp ); fwrite( Walls, sizeof(wall)*i, 1, fp ); //Save door info i = Num_open_doors; fwrite( &i, sizeof(int), 1, fp ); fwrite( ActiveDoors, sizeof(active_door)*i, 1, fp ); //Save trigger info fwrite( &Num_triggers, sizeof(int), 1, fp ); fwrite( Triggers, sizeof(trigger)*Num_triggers, 1, fp ); //Save tmap info for (i=0; i<=Highest_segment_index; i++ ) { for (j=0; j<6; j++ ) { fwrite( &Segments[i].sides[j].wall_num, sizeof(short), 1, fp ); fwrite( &Segments[i].sides[j].tmap_num, sizeof(short), 1, fp ); fwrite( &Segments[i].sides[j].tmap_num2, sizeof(short), 1, fp ); } } // Save the fuelcen info fwrite( &Fuelcen_control_center_destroyed, sizeof(int), 1, fp ); fwrite( &Fuelcen_seconds_left, sizeof(int), 1, fp ); fwrite( &Num_robot_centers, sizeof(int), 1, fp ); fwrite( RobotCenters, sizeof(matcen_info)*Num_robot_centers, 1, fp ); fwrite( &ControlCenterTriggers, sizeof(control_center_triggers), 1, fp ); fwrite( &Num_fuelcenters, sizeof(int), 1, fp ); fwrite( Station, sizeof(FuelCenter)*Num_fuelcenters, 1, fp ); // Save the control cen info fwrite( &Control_center_been_hit, sizeof(int), 1, fp ); fwrite( &Control_center_player_been_seen, sizeof(int), 1, fp ); fwrite( &Control_center_next_fire_time, sizeof(int), 1, fp ); fwrite( &Control_center_present, sizeof(int), 1, fp ); fwrite( &Dead_controlcen_object_num, sizeof(int), 1, fp ); // Save the AI state ai_save_state( fp ); // Save the automap visited info fwrite( Automap_visited, sizeof(ubyte)*MAX_SEGMENTS, 1, fp ); } fwrite( &state_game_id, sizeof(uint), 1, fp ); fwrite( &Laser_rapid_fire, sizeof(int), 1, fp ); fwrite( &Ugly_robot_cheat, sizeof(int), 1, fp ); fwrite( &Ugly_robot_texture, sizeof(int), 1, fp ); fwrite( &Physics_cheat_flag, sizeof(int), 1, fp ); fwrite( &Lunacy, sizeof(int), 1, fp ); fclose(fp); // set the type and creator of the saved game file strcpy(pfilename, filename); c2pstr(pfilename); err = HGetFInfo(0, 0, pfilename, &finfo); finfo.fdType = 'SVGM'; finfo.fdCreator = 'DCNT'; err = HSetFInfo(0, 0, pfilename, &finfo); start_time(); return 1; }
int state_save_old_game(int slotnum, char * sg_name, player * sg_player, int sg_difficulty_level, int sg_primary_weapon, int sg_secondary_weapon, int sg_next_level_num ) { int i; int temp_int; ubyte temp_byte; char desc[DESC_LENGTH+1]; char filename[128]; grs_canvas * cnv; FILE * fp; sprintf( filename, "%s.sg%d", sg_player->callsign, slotnum ); fp = fopen( filename, "wb" ); if ( !fp ) return 0; //Save id fwrite( dgss_id, sizeof(char)*4, 1, fp ); //Save version temp_int = STATE_VERSION; fwrite( &temp_int, sizeof(int), 1, fp ); //Save description strncpy( desc, sg_name, DESC_LENGTH ); fwrite( desc, sizeof(char)*DESC_LENGTH, 1, fp ); // Save the current screen shot... cnv = gr_create_canvas( THUMBNAIL_W, THUMBNAIL_H ); if ( cnv ) { char * pcx_file; ubyte pcx_palette[768]; grs_bitmap bmp; gr_set_current_canvas( cnv ); gr_clear_canvas( BM_XRGB(0,0,0) ); pcx_file = get_briefing_screen( sg_next_level_num ); if ( pcx_file != NULL ) { bmp.bm_data = NULL; if (pcx_read_bitmap( pcx_file, &bmp, BM_LINEAR, pcx_palette )==PCX_ERROR_NONE) { grs_point vertbuf[3]; gr_clear_canvas( TRANSPARENCY_COLOR ); vertbuf[0].x = vertbuf[0].y = -F1_0*6; // -6 pixel rows for ascpect vertbuf[1].x = vertbuf[1].y = 0; vertbuf[2].x = i2f(THUMBNAIL_W); vertbuf[2].y = i2f(THUMBNAIL_H+7); // + 7 pixel rows for ascpect scale_bitmap(&bmp, vertbuf ); gr_remap_bitmap_good( &cnv->cv_bitmap, pcx_palette, -1, -1 ); myfree( bmp.bm_data ); } } fwrite( cnv->cv_bitmap.bm_data, THUMBNAIL_W*THUMBNAIL_H, 1, fp ); gr_free_canvas( cnv ); } else { ubyte color = 0; for ( i=0; i<THUMBNAIL_W*THUMBNAIL_H; i++ ) fwrite( &color, sizeof(ubyte), 1, fp ); } // Save the Between levels flag... temp_int = 1; fwrite( &temp_int, sizeof(int), 1, fp ); // Save the mission info... #ifdef MAC_SHAREWARE fwrite( mission_save, sizeof(char)*9, 1, fp); #else fwrite( &Mission_list[0], sizeof(char)*9, 1, fp ); #endif //Save level info temp_int = sg_player->level; fwrite( &temp_int, sizeof(int), 1, fp ); temp_int = sg_next_level_num; fwrite( &temp_int, sizeof(int), 1, fp ); //Save GameTime temp_int = 0; fwrite( &temp_int, sizeof(fix), 1, fp ); //Save player info fwrite( sg_player, sizeof(player), 1, fp ); // Save the current weapon info temp_byte = sg_primary_weapon; fwrite( &temp_byte, sizeof(byte), 1, fp ); temp_byte = sg_secondary_weapon; fwrite( &temp_byte, sizeof(byte), 1, fp ); // Save the difficulty level temp_int = sg_difficulty_level; fwrite( &temp_int, sizeof(int), 1, fp ); // Save the Cheats_enabled temp_int = 0; fwrite( &temp_int, sizeof(int), 1, fp ); temp_int = 0; // turbo mode fwrite( &temp_int, sizeof(int), 1, fp ); fwrite( &state_game_id, sizeof(uint), 1, fp ); fwrite( &Laser_rapid_fire, sizeof(int), 1, fp ); fwrite( &Ugly_robot_cheat, sizeof(int), 1, fp ); fwrite( &Ugly_robot_texture, sizeof(int), 1, fp ); fwrite( &Physics_cheat_flag, sizeof(int), 1, fp ); fwrite( &Lunacy, sizeof(int), 1, fp ); fclose(fp); return 1; }
void do_automap( int key_code ) { int done=0; vms_matrix tempm; vms_angvec tangles; int leave_mode=0; int first_time=1; int pcx_error; int i; int c; char filename[] = "MAP.PCX"; fix entry_time; int pause_game=1; // Set to 1 if everything is paused during automap...No pause during net. fix t1, t2; control_info saved_control_info; int Max_segments_away = 0; int SegmentLimit = 1; key_code = key_code; // disable warning... if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence)) pause_game = 0; if (pause_game) stop_time(); create_name_canv(); Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES); //make maybe smaller than max //Edges = malloc( sizeof(Edge_info)*Max_edges); //if ( Edges == NULL ) { // mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024)); // return; //} //DrawingListBright = malloc( sizeof(short)*Max_edges); //if ( DrawingListBright == NULL ) { // mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024)); // return; //} mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES )); mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 )); gr_palette_clear(); gr_init_sub_canvas(&Page,&VR_render_buffer[0],0, 0, 640, 480); gr_init_sub_canvas(&DrawingPage,&Page,38,77,564,381); #if 0 gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,320,400); gr_init_sub_canvas(&Pages[1],grd_curcanv,0,401,320,400); gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,288,272); gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,288,272); #endif gr_set_current_canvas(&Page); pcx_error = pcx_read_bitmap(filename,&(grd_curcanv->cv_bitmap),BM_LINEAR,NULL); if ( pcx_error != PCX_ERROR_NONE ) { printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error)); Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error)); return; } gr_set_curfont(Gamefonts[GFONT_BIG_1]); gr_set_fontcolor(BM_XRGB(20, 20, 20), -1); gr_printf( 80, 36,TXT_AUTOMAP,GFONT_BIG_1); gr_set_curfont(Gamefonts[GFONT_SMALL]); gr_set_fontcolor(BM_XRGB(20, 20, 20), -1); gr_printf( 265, 27,TXT_TURN_SHIP); gr_printf( 265, 44,TXT_SLIDE_UPDOWN); gr_printf( 265, 61,TXT_VIEWING_DISTANCE); gr_set_current_canvas(&DrawingPage); automap_build_edge_list(); if ( ViewDist==0 ) ViewDist = ZOOM_DEFAULT; ViewMatrix = Objects[Players[Player_num].objnum].orient; tangles.p = PITCH_DEFAULT; tangles.h = 0; tangles.b = 0; done = 0; view_target = Objects[Players[Player_num].objnum].pos; t1 = entry_time = timer_get_fixed_seconds(); t2 = t1; //Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); SegmentLimit = Max_segments_away; adjust_segment_limit(SegmentLimit); while(!done) { #ifndef MAC_SHAREWARE redbook_restart_track(); #endif if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME) leave_mode = 1; if ( !Controls.automap_state && (leave_mode==1) ) done=1; if (!pause_game) { ushort old_wiggle; saved_control_info = Controls; // Save controls so we can zero them memset(&Controls,0,sizeof(control_info)); // Clear everything... old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE; // Save old wiggle ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE; // Turn off wiggle #ifdef NETWORK if (multi_menu_poll()) done = 1; #endif // GameLoop( 0, 0 ); // Do game loop with no rendering and no reading controls. ConsoleObject->mtype.phys_info.flags |= old_wiggle; // Restore wiggle Controls = saved_control_info; } controls_read_all(); if ( Controls.automap_down_count ) { if (leave_mode==0) done = 1; c = 0; } while( (c=key_inkey()) ) { switch( c ) { #ifndef NDEBUG case KEY_BACKSP: Int3(); break; #endif case KEY_PRINT_SCREEN: save_screen_shot(1); break; case KEY_ESC: if (leave_mode==0) done = 1; break; case KEY_ALTED+KEY_F: // Alt+F shows full map, if cheats enabled if (Cheats_enabled) { uint t; t = Players[Player_num].flags; Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT; automap_build_edge_list(); Players[Player_num].flags=t; } break; #ifndef NDEBUG case KEY_DEBUGGED+KEY_F: { for (i=0; i<=Highest_segment_index; i++ ) Automap_visited[i] = 1; automap_build_edge_list(); Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); SegmentLimit = Max_segments_away; adjust_segment_limit(SegmentLimit); } break; #endif case KEY_MINUS: if (SegmentLimit > 1) { SegmentLimit--; adjust_segment_limit(SegmentLimit); } break; case KEY_EQUAL: if (SegmentLimit < Max_segments_away) { SegmentLimit++; adjust_segment_limit(SegmentLimit); } break; } } if ( Controls.fire_primary_down_count ) { // Reset orientation ViewDist = ZOOM_DEFAULT; tangles.p = PITCH_DEFAULT; tangles.h = 0; tangles.b = 0; view_target = Objects[Players[Player_num].objnum].pos; } ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR; tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR ); tangles.h += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR ); tangles.b += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 ); if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time ) { vms_angvec tangles1; vms_vector old_vt; old_vt = view_target; tangles1 = tangles; vm_angles_2_matrix(&tempm,&tangles1); vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm); vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED ); vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED ); if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) ) { view_target = old_vt; } } vm_angles_2_matrix(&tempm,&tangles); vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm); if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE; if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE; draw_automap(); if ( first_time ) { first_time = 0; gr_palette_load( gr_palette ); } t2 = timer_get_fixed_seconds(); if (pause_game) FrameTime=t2-t1; t1 = t2; } //free(Edges); //free(DrawingListBright); gr_free_canvas(name_canv); name_canv=NULL; mprintf( (0, "Automap memory freed\n" )); game_flush_inputs(); if (pause_game) start_time(); }
//if filename passed is NULL, show normal credits void credits_show(char *credits_filename) { credits *cr; window *wind; int i; int pcx_error; char * tempp; char filename[32]; ubyte backdrop_palette[768]; MALLOC(cr, credits, 1); if (!cr) return; cr->have_bin_file = 0; cr->buffer_line = 0; cr->first_line_offset = 0; cr->extra_inc = 0; cr->done = 0; cr->row = 0; // Clear out all tex buffer lines. for (i=0; i<NUM_LINES; i++ ) cr->buffer[i][0] = 0; sprintf(filename, "%s", CREDITS_FILE); cr->have_bin_file = 0; if (credits_filename) { strcpy(filename,credits_filename); cr->have_bin_file = 1; } cr->file = PHYSFSX_openReadBuffered( filename ); if (cr->file == NULL) { char nfile[32]; if (credits_filename) { d_free(cr); return; //ok to not find special filename } tempp = strchr(filename, '.'); *tempp = '\0'; sprintf(nfile, "%s.txb", filename); cr->file = PHYSFSX_openReadBuffered(nfile); if (cr->file == NULL) Error("Missing CREDITS.TEX and CREDITS.TXB file\n"); cr->have_bin_file = 1; } set_screen_mode(SCREEN_MENU); gr_use_palette_table( "credits.256" ); cr->backdrop.bm_data=NULL; pcx_error = pcx_read_bitmap(STARS_BACKGROUND,&cr->backdrop, BM_LINEAR,backdrop_palette); if (pcx_error != PCX_ERROR_NONE) { PHYSFS_close(cr->file); d_free(cr); return; } songs_play_song( SONG_CREDITS, 1 ); gr_remap_bitmap_good( &cr->backdrop,backdrop_palette, -1, -1 ); gr_set_current_canvas(NULL); show_fullscr(&cr->backdrop); gr_palette_load( gr_palette ); key_flush(); wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *))credits_handler, cr); if (!wind) { d_event event = { EVENT_WINDOW_CLOSE }; credits_handler(NULL, &event, cr); return; } while (window_exists(wind)) event_process(); }
void credits_show() { int i, j, l, done; CFILE * file; char buffer[NUM_LINES][80]; grs_bitmap backdrop; ubyte backdrop_palette[768]; int pcx_error; int buffer_line = 0; fix last_time; fix time_delay = 4180 / f2fl(Scale_y); // ~ F1_0 / 12.9 int first_line_offset,extra_inc=0; int have_bin_file = 0; char * tempp; grs_point scale_pts[] = FULLSCREEN_SCALE_PTS; ubyte *fade_values = malloc(grd_curscreen->sc_h); for (i = 0; i < grd_curscreen->sc_h; ++i) { fade_values[i] = fade_values_200[(int)(((float)i / (float)grd_curscreen->sc_h) * 200)]; } set_screen_mode(SCREEN_MENU); // Clear out all tex buffer lines. for (i=0; i<NUM_LINES; i++ ) buffer[i][0] = 0; have_bin_file = 0; file = cfopen( "credits.tex", "rb" ); if (file == NULL) { file = cfopen("credits.txb", "rb"); if (file == NULL) Error("Missing CREDITS.TEX and CREDITS.TXB file\n"); have_bin_file = 1; } gr_use_palette_table( "credits.256" ); header_font = gr_init_font( "font1-1.fnt" ); title_font = gr_init_font( "font2-3.fnt" ); names_font = gr_init_font( "font2-2.fnt" ); backdrop.bm_data=NULL; pcx_error = pcx_read_bitmap("stars.pcx",&backdrop,BM_LINEAR,backdrop_palette); if (pcx_error != PCX_ERROR_NONE) { cfclose(file); return; } songs_play_song( SONG_CREDITS, 0 ); gr_remap_bitmap_good( &backdrop,backdrop_palette, -1, -1 ); gr_set_current_canvas(NULL); scale_bitmap(&backdrop,scale_pts); gr_palette_fade_in( gr_palette, 32, 0 ); vfx_set_palette_sub( gr_palette ); //gr_clear_canvas(BM_XRGB(0,0,0)); key_flush(); last_time = timer_get_fixed_seconds(); done = 0; first_line_offset = 0; while( 1 ) { int k; do { buffer_line = (buffer_line+1) % NUM_LINES; if (cfgets( buffer[buffer_line], 80, file )) { char *p; if (have_bin_file) { // is this a binary tbl file for (i = 0; i < strlen(buffer[buffer_line]) - 1; i++) { encode_rotate_left(&(buffer[buffer_line][i])); buffer[buffer_line][i] ^= BITMAP_TBL_XOR; encode_rotate_left(&(buffer[buffer_line][i])); } } p = strchr(&buffer[buffer_line][0],'\n'); if (p) *p = '\0'; } else { //fseek( file, 0, SEEK_SET); buffer[buffer_line][0] = 0; done++; } } while (extra_inc--); extra_inc = 0; for (i=0; i<ROW_SPACING; i++ ) { int y; y = first_line_offset - i; #ifndef OGLES gr_set_current_canvas(VR_offscreen_buffer); #endif scale_bitmap(&backdrop, scale_pts); for (j=0; j<NUM_LINES; j++ ) { char *s; l = (buffer_line + j + 1 ) % NUM_LINES; s = buffer[l]; if ( s[0] == '!' ) { s++; } else if ( s[0] == '$' ) { grd_curcanv->cv_font = header_font; s++; } else if ( s[0] == '*' ) { grd_curcanv->cv_font = title_font; s++; } else grd_curcanv->cv_font = names_font; gr_bitblt_fade_table = fade_values; tempp = strchr( s, '\t' ); if ( tempp ) { int w, h, aw; *tempp = 0; gr_get_string_size( s, &w, &h, &aw ); w *= f2fl(Scale_x); h *= f2fl(Scale_y); gr_scale_printf( (160-w)/2, y, Scale_factor, Scale_factor, s ); gr_get_string_size( &tempp[1], &w, &h, &aw ); w *= f2fl(Scale_x); h *= f2fl(Scale_y); gr_scale_printf( 160+((160-w)/2), y, Scale_factor, Scale_factor, &tempp[1] ); *tempp = '\t'; } else { gr_scale_printf( 0x8000, y, Scale_factor, Scale_factor, s ); } gr_bitblt_fade_table = NULL; if (buffer[l][0] == '!') y += ROW_SPACING/2; else y += ROW_SPACING; } #ifdef OGLES showRenderBuffer(); #else gr_bm_ubitblt(grd_curscreen->sc_w, grd_curscreen->sc_h, 0, 0, 0, 0, &(VR_offscreen_buffer->cv_bitmap), &(grd_curscreen->sc_canvas.cv_bitmap) ); #endif while( timer_get_fixed_seconds() < last_time+time_delay ); last_time = timer_get_fixed_seconds(); k = key_inkey(); #ifndef NDEBUG if (k == KEY_BACKSP) { Int3(); k=0; } #endif // { // fix ot = time_delay; // time_delay += (keyd_pressed[KEY_X] - keyd_pressed[KEY_Z])*100; // if (ot!=time_delay) { // mprintf( (0, "[%x] ", time_delay )); // } // } if (k == KEY_PRINT_SCREEN) { save_screen_shot(0); k = 0; } if ((k>0)||(done>NUM_LINES)) { gr_close_font(header_font); gr_close_font(title_font); gr_close_font(names_font); gr_palette_fade_out( gr_palette, 32, 0 ); gr_use_palette_table( "palette.256" ); free(backdrop.bm_data); cfclose(file); songs_play_song( SONG_TITLE, 1 ); return; } } if (buffer[(buffer_line + 1 ) % NUM_LINES][0] == '!') { first_line_offset -= ROW_SPACING-ROW_SPACING/2; if (first_line_offset <= -ROW_SPACING) { first_line_offset += ROW_SPACING; extra_inc++; } } } free(fade_values); }