void script_write(u16 var8, u16 vara) { u8 *script_name = 0; switch (var8) { case 0: script_name = "load.logic"; break; case 1: script_name = "load.view"; break; case 2: script_name = "load.pic"; break; case 3: script_name = "load.sound"; break; case 4: script_name = "draw.pic"; break; case 5: script_name = "add.to.pic"; break; case 6: script_name = "discard.pic"; break; case 7: script_name = "discard.view"; break; case 8: script_name = "overlay.pic"; break; default: script_name = "unknown"; break; } //printf("script write %s - %d\n", script_name, vara); if (flag_test(0x07) == 0) { if (write_ok != 0) { if (script_next >= ((state.script_size << 1) + script_head) ) set_agi_error(0xB, mem_script); script_next[0] = (u8)var8; script_next[1] = (u8)vara; script_next += 2; state.script_count++; } if ( ((script_next - script_head) / 2) > mem_script) { mem_script = (script_next - script_head) / 2; //printf("mem_script = %d\n", mem_script); } } }
//if a ball drains during the mode and with time still on the ballsave timer - send it back in play CALLSET_BOOL_ENTRY (cryoprison, ball_drain) { //thrown by device.c if (flag_test(FLAG_IS_CRYOPRISON_MB_RUNNING) && cryoprison_ballsave) { sound_start (ST_SPEECH, SPCH_JOHN_SCREAM, SL_2S, PRI_GAME_QUICK5); serve_ball_auto (); return FALSE; //this is not a valid drain, don't count it } else return TRUE; //this is a valid drain }//end of callset
//flashing overides being on solid, so if multiple modes //are running, lamp will flash, but when timer ends, will go back to solid void flash_combos(void){ if (flag_test (FLAG_IS_COMBO_SIDERAMP_ACTIVATED) ) lamp_tristate_flash (LM_SIDE_RAMP_ARROW); if (flag_test (FLAG_IS_COMBO_LEFTRAMP_ACTIVATED) ) lamp_tristate_flash (LM_LEFT_RAMP_ARROW); if (flag_test (FLAG_IS_COMBO_RIGHTRAMP_ACTIVATED) ) lamp_tristate_flash (LM_RIGHT_RAMP_ARROW); if (flag_test (FLAG_IS_COMBO_UNDER_ACTIVATED) ) lamp_tristate_flash (LM_UNDERGROUND_ARROW); if (flag_test (FLAG_IS_COMBO_CENTERRAMP_ACTIVATED) ) lamp_tristate_flash (LM_CENTER_RAMP_ARROW); if (flag_test (FLAG_IS_COMBO_LEFTORB_ACTIVATED) ) lamp_tristate_flash (LM_LEFT_LOOP_ARROW); if (flag_test (FLAG_IS_COMBO_RIGHTORB_ACTIVATED) ) lamp_tristate_flash (LM_RIGHT_LOOP_ARROW); }//end of function
void rudy_eye_change (U8 flags) { if (flag_test (FLAG_MULTIBALL_LIT)) flags = EYELID_CLOSED; if (flags != rudy_eyes) { rudy_eyes = flags; task_create_gid1 (GID_RUDY_UPDATE, rudy_eye_update); } }
//we always start with these 3 lights on because those are the skillshots void combo_reset (void) { flag_on (FLAG_IS_COMBO_SIDERAMP_ACTIVATED); flag_on (FLAG_IS_COMBO_LEFTRAMP_ACTIVATED); flag_off (FLAG_IS_COMBO_RIGHTRAMP_ACTIVATED); flag_on (FLAG_IS_COMBO_UNDER_ACTIVATED); flag_off (FLAG_IS_COMBO_CENTERRAMP_ACTIVATED); flag_off (FLAG_IS_COMBO_LEFTORB_ACTIVATED); flag_off (FLAG_IS_COMBO_RIGHTORB_ACTIVATED); flag_on (FLAG_IS_COMBOS_RESTARTABLE); if (flag_test (FLAG_IS_COMPUTER_ACTIVATED) ) computer_light_on(); all_arrow_update(); // at arrow_handler.c }//end of function
//Once huxley mode is enabled it is started by a huxley shot (backwards to retina scan) void huxley_made(void){ play_huxley_sounds(); if (flag_test(FLAG_IS_HUXLEY_ENABLED) ) timed_mode_begin (&huxley_mode);//start mode else { score (HUXLEY_SCORE); deff_start_sync (DEFF_HUXLEY_INFO_EFFECT); sol_request_async (SOL_EJECT); //request to fire the eject sol task_sleep (TIME_300MS); flag_off(FLAG_KILL_NORMAL_EJECT); }//end of else }//end of function
u8 *cmd_restart_game(u8 *c) { u16 snd_state; u16 user_result; u16 input_state; sound_stop(); input_state = input_edit_status(); input_edit_on(); if (flag_test(F16_RESTARTMODE) != 0) user_result = 1; else user_result = message_box("Press ENTER to restart\nthe game.\n\nPress ESC to continue\nthis game."); if ( user_result != 0) { cmd_cancel_line(0); snd_state = flag_test(F09_SOUND); //clear_memory(); // shouldn't be necessary game_init(); volumes_close(); flag_set(F06_RESTART); if ( snd_state != 0) flag_set(F09_SOUND); state.ticks = 0; if (trace_logic != 0) logic_load_2(trace_logic); menu_enable_all(); } if ( (user_result != 0) || (input_state != 0) ) input_edit_off(); if (user_result != 0) return 0; else return c; }
/**************************************************************************** * * display effects * ****************************************************************************/ void freeze_effect_deff(void) { U16 fno; dmd_alloc_pair_clean (); sound_start (ST_EFFECT, SIREN, SL_4S, PRI_GAME_QUICK5); for (fno = IMG_CONTROLLER_START; fno <= IMG_FREEZE_A_END; fno += 2) { dmd_alloc_pair_clean (); frame_draw(fno); dmd_show2 (); task_sleep (TIME_100MS); }//end of inner loop task_sleep (TIME_300MS); dmd_alloc_pair_clean ();// Clean both pages dmd_map_overlay (); dmd_clean_page_low (); if ( flag_test(FLAG_IS_MULTIBALL_ENABLED) ) { font_render_string_center (&font_halobold12, DMD_MIDDLE_X, DMD_BIG_CY_Top, "MULTIBALL"); font_render_string_center (&font_halobold12, DMD_MIDDLE_X + 10, DMD_BIG_CY_Bot, "READY"); } else { font_render_string_center (&font_halobold12, DMD_MIDDLE_X, DMD_BIG_CY_Top, "FREEZE"); } dmd_text_outline (); dmd_alloc_pair (); frame_draw(IMG_FREEZE_A_END); dmd_overlay_outline (); dmd_show2 (); if (DM_IN_DMD_TEST) freeze_MessageCounter++; if (flag_test(FLAG_IS_MULTIBALL_ENABLED)) { if ( (lock_SoundCounter++ % 2) == 0 )//check if even sound_start (ST_SPEECH, SPCH_MULTIBALL_ACTIVATED, SL_4S, PRI_GAME_QUICK5); else sound_start (ST_SPEECH, SPCH_SHOOT_LEFT_LOOP, SL_4S, PRI_GAME_QUICK5); } task_sleep_sec (1); deff_exit (); }//end of mode_effect_deff
//rotate rollovers when buttons pressed CALLSET_ENTRY (rollovers, sw_right_button, sw_upper_right_button) { if (valid_playfield && !flag_test(FLAG_VIDEO_MODE_RUNNING) ) { if (top_rollover_activated && lower_rollover_activated) { //left not activated lamp_tristate_on(LM_MIDDLE_ROLLOVER); lamp_tristate_off(LM_TOP_ROLLOVER); lamp_tristate_on(LM_LOWER_ROLLOVER); middle_rollover_activated = TRUE; top_rollover_activated = FALSE; lower_rollover_activated = TRUE; } else if (middle_rollover_activated && lower_rollover_activated) { //center not activated lamp_tristate_on(LM_MIDDLE_ROLLOVER); lamp_tristate_on(LM_TOP_ROLLOVER); lamp_tristate_off(LM_LOWER_ROLLOVER); middle_rollover_activated = TRUE; top_rollover_activated = TRUE; lower_rollover_activated = FALSE; } else if (middle_rollover_activated && top_rollover_activated) { //right not activated lamp_tristate_off(LM_MIDDLE_ROLLOVER); lamp_tristate_on(LM_TOP_ROLLOVER); lamp_tristate_on(LM_LOWER_ROLLOVER); middle_rollover_activated = FALSE; top_rollover_activated = TRUE; lower_rollover_activated = TRUE; } else if (middle_rollover_activated) { //center and right not activated lamp_tristate_off(LM_MIDDLE_ROLLOVER); lamp_tristate_on(LM_TOP_ROLLOVER); lamp_tristate_off(LM_LOWER_ROLLOVER); middle_rollover_activated = FALSE; top_rollover_activated = TRUE; lower_rollover_activated = FALSE; } else if (top_rollover_activated) { //left and right not activated lamp_tristate_off(LM_MIDDLE_ROLLOVER); lamp_tristate_off(LM_TOP_ROLLOVER); lamp_tristate_on(LM_LOWER_ROLLOVER); middle_rollover_activated = FALSE; top_rollover_activated = FALSE; lower_rollover_activated = TRUE; } else if (lower_rollover_activated) { //left and center not activated lamp_tristate_on(LM_MIDDLE_ROLLOVER); lamp_tristate_off(LM_TOP_ROLLOVER); lamp_tristate_off(LM_LOWER_ROLLOVER); middle_rollover_activated = TRUE; top_rollover_activated = FALSE; lower_rollover_activated = FALSE; } }//end of if (in_live_game) }//end of function to rotate right
void common_outlane (void) { score (SC_50K); rudy_look_straight (); if (!flag_test (FLAG_STEPS_OPEN)) sample_start (SND_OUTLANE, SL_500MS); if (lamp_test (LM_SPECIALS)) { lamp_off (LM_SPECIALS); flag_off (FLAG_OUTLANES_LIT); special_award (); } }
void combo_hit(void ) { //video mode if (++combo_counter >= combo_vm_goal && !flag_test (FLAG_VIDEO_MODE_ENABLED) ) { if (IN_TEST) combo_vm_goal += 2; else { #ifdef CONFIG_DIFFICULTY_LEVEL if (system_config.difficulty == EASY) combo_vm_goal += COMBO_EASY_GOAL_STEP; else combo_vm_goal += COMBO_HARD_GOAL_STEP; #elif combo_vm_goal += COMBO_EASY_GOAL_STEP; #endif }//end of else flag_on (FLAG_VIDEO_MODE_ENABLED); deff_start (DEFF_VM_EFFECT); } //computer award else if (combo_counter >= combo_goal && !flag_test (FLAG_IS_COMPUTER_ACTIVATED) ) { if (IN_TEST) combo_goal += 2; else { #ifdef CONFIG_DIFFICULTY_LEVEL if (system_config.difficulty == EASY) combo_goal += COMBO_EASY_GOAL_STEP; else combo_goal += COMBO_HARD_GOAL_STEP; #elif combo_goal += COMBO_EASY_GOAL_STEP; #endif }//end of else computer_light_on(); //at underground.c deff_start (DEFF_COMBO_EFFECT); } //not at a goal yet else deff_start (DEFF_COMBO_EFFECT); // reset the task timer choose_random_flag_set(); all_arrow_update(); task_recreate_gid (GID_COMBO, combo_task); }//end of function
static enum trap_door_state trap_door_decide (void) { if (in_live_game) { if (flag_test (FLAG_JACKPOT_LIT) || frenzy_lit_p ()) return OPEN; else return CLOSED; } else { return CLOSED; } }
CALLSET_ENTRY (slot, dev_slot_enter) { if (task_kill_gid (GID_CAMERA_SLOT_PROX_DETECT) || task_kill_gid (GID_PIANO_SLOT_PROX_DETECT)) { /* Proximity sensor did not trip ; must be the powerball */ pb_detect_event (PF_PB_DETECTED); pb_announce (); } if (!in_live_game) return; else if (task_find_or_kill_gid (GID_DEADEND_TO_SLOT) || task_find_or_kill_gid (GID_GUMBALL_TO_SLOT) || task_find_or_kill_gid (GID_PIANO_TO_SLOT) || task_find_or_kill_gid (GID_CAMERA_TO_SLOT)) { /* dead end was recently hit, so ignore slot */ /* piano was recently hit, so ignore slot */ /* camera was recently hit, so ignore slot */ } else if (event_did_follow (skill_shot, slot) || skill_shot_enabled || global_flag_test (GLOBAL_FLAG_SSSMB_RUNNING)) { /* TODO, this may be buggy during sssmb */ /* skill shot has been missed or ball landed in plunger lane*/ if (timer_kill_gid (GID_SDSS_APPROACHING)) callset_invoke (sdss_ready); callset_invoke (skill_missed); } else if (timed_mode_running_p (&sslot_mode)) { //TODO If shot from lite slot lane, allow player to choose award shot_sslot (); } else if (can_award_door_panel () && flag_test (FLAG_SLOT_DOOR_LIT)) { shot_slot_door (); } else { shot_slot_oddchange (); } /* Sleep so the deffs can get a chance to start and stop it * kicking out too early */ task_sleep (TIME_400MS); }
/**************************************************************************** * * ramps lighting effects * ****************************************************************************/ void ramp_quickfreeze_leff (void) { for (;;) { //listed from botton to top leff_on (LM_QUICK_FREEZE); task_sleep (TIME_100MS); leff_off (LM_QUICK_FREEZE); leff_on (LM_LEFT_RAMP_CAR_CHASE); task_sleep (TIME_100MS); leff_off (LM_LEFT_RAMP_CAR_CHASE); leff_on (LM_LEFT_RAMP_EXPLODE); task_sleep (TIME_100MS); leff_off (LM_LEFT_RAMP_EXPLODE); leff_on (LM_LEFT_RAMP_JACKPOT); task_sleep (TIME_100MS); leff_off (LM_LEFT_RAMP_JACKPOT); leff_on (LM_LEFT_RAMP_ARROW); task_sleep (TIME_100MS); leff_off (LM_LEFT_RAMP_ARROW); task_sleep (TIME_100MS); if (flag_test(FLAG_IS_LRAMP_QUICKFREEZE_ACTIVATED)) leff_on (LM_QUICK_FREEZE); if (is_carchase_mode_running() ) leff_on (LM_LEFT_RAMP_CAR_CHASE); if (is_explode_mode_running() ) leff_on (LM_LEFT_LOOP_EXPLODE); if (get_jackpot_arrows(lramp_mask) ) leff_on (LM_LEFT_RAMP_JACKPOT); if (flag_test(FLAG_IS_L_RAMP_ARROW_ACTIVATED)) leff_on (LM_LEFT_RAMP_ARROW); task_sleep (TIME_1S); leff_off (LM_QUICK_FREEZE); leff_off (LM_LEFT_RAMP_CAR_CHASE); leff_off (LM_LEFT_RAMP_EXPLODE); leff_off (LM_LEFT_RAMP_JACKPOT); leff_off (LM_LEFT_RAMP_ARROW); task_sleep (TIME_200MS); }//END OF LOOP leff_exit(); }//end of function
/**************************************************************************** * * orbits lighting effects * ****************************************************************************/ void orbits_runner_leff (void) { //left loop for (;;) { //listed from botton to top leff_on (LM_EXTRA_BALL); task_sleep (TIME_100MS); leff_off (LM_EXTRA_BALL); leff_on (LM_START_MULTIBALL); task_sleep (TIME_100MS); leff_off (LM_START_MULTIBALL); leff_on (LM_LEFT_LOOP_EXPLODE); task_sleep (TIME_100MS); leff_off (LM_LEFT_LOOP_EXPLODE); leff_on (LM_LEFT_LOOP_JACKPOT); task_sleep (TIME_100MS); leff_off (LM_LEFT_LOOP_JACKPOT); leff_on (LM_LEFT_LOOP_ARROW); task_sleep (TIME_100MS); leff_off (LM_LEFT_LOOP_ARROW); task_sleep (TIME_100MS); if (flag_test(FLAG_IS_EXTRABALL_LIT)) leff_on (LM_EXTRA_BALL); if (flag_test(FLAG_IS_MULTIBALL_ENABLED)) leff_on (LM_START_MULTIBALL); if (is_explode_mode_running() ) lamp_tristate_flash (LM_LEFT_LOOP_EXPLODE); if (get_jackpot_arrows(lloop_mask)) leff_on (LM_LEFT_LOOP_JACKPOT); if (flag_test(FLAG_IS_L_LOOP_ARROW_ACTIVATED)) leff_on (LM_LEFT_LOOP_ARROW); task_sleep (TIME_2S); leff_off (LM_EXTRA_BALL); leff_off (LM_START_MULTIBALL); leff_off (LM_LEFT_LOOP_EXPLODE); leff_off (LM_LEFT_LOOP_JACKPOT); leff_off (LM_LEFT_LOOP_ARROW); task_sleep (TIME_100MS); }//end of loop leff_exit(); }//end of function
void ramp_clawready_leff (void) { for (;;) { //listed from botton to top leff_on (LM_CLAW_READY); task_sleep (TIME_100MS); leff_off (LM_CLAW_READY); leff_on (LM_RIGHT_RAMP_CAR_CHASE); task_sleep (TIME_100MS); leff_off (LM_RIGHT_RAMP_CAR_CHASE); leff_on (LM_RIGHT_RAMP_EXPLODE); task_sleep (TIME_100MS); leff_off (LM_RIGHT_RAMP_EXPLODE); leff_on (LM_RIGHT_RAMP_JACKPOT); task_sleep (TIME_100MS); leff_off (LM_RIGHT_RAMP_JACKPOT); leff_on (LM_RIGHT_RAMP_ARROW); task_sleep (TIME_100MS); leff_off (LM_RIGHT_RAMP_ARROW); task_sleep (TIME_100MS); if (flag_test(FLAG_IS_R_RAMP_CLAWREADY)) leff_on (LM_CLAW_READY); if (is_carchase_mode_running() ) leff_on (LM_RIGHT_RAMP_CAR_CHASE); if (is_explode_mode_running() ) leff_on (LM_RIGHT_LOOP_EXPLODE); if (get_jackpot_arrows(rramp_mask) ) leff_on (LM_RIGHT_RAMP_JACKPOT); if (flag_test(FLAG_IS_R_RAMP_ARROW_ACTIVATED)) leff_on (LM_RIGHT_RAMP_ARROW); task_sleep (TIME_1S); leff_off (LM_CLAW_READY); leff_off (LM_RIGHT_RAMP_CAR_CHASE); leff_off (LM_RIGHT_RAMP_EXPLODE); leff_off (LM_RIGHT_RAMP_JACKPOT); leff_off (LM_RIGHT_RAMP_ARROW); task_sleep (TIME_200MS); }//END OF LOOP leff_exit(); }//end of function
//puts in grace period if set CALLSET_ENTRY (cryoprison, single_ball_play) { if (flag_test(FLAG_IS_CRYOPRISON_MB_RUNNING)) { mb_mode_end_ball (&cryoprison_mode); end_super_jackpot_reminder(); combo_init(); diverter_check(); enable_back_in_the_fridge(); //at completion of our 4th MB we enable the wizard mode //this acts as kind of a grace period for the jackpots task_sleep_sec(3); flag_off(FLAG_IS_CRYOPRISON_MB_RUNNING); jackpot_reset(); } }//end of function
CALLSET_ENTRY (jets, jet_hit) { // task_recreate_gid (GID_JETS, jet_hit_task); //score_copy (temp_score, current_score); flasher_pulse (FLASH_RIGHT_HELMET); /* Make a sound, based on level */ if (!free_timer_test (timer_jets_level_up)) sound_send (jet_sounds[jets_level][jets_sound_index]); jets_sound_index++; if (jets_sound_index > 2) jets_sound_index = 0; if (timed_mode_running_p (&jets_frenzy_mode)) { score (SC_500K); } else if (score_compare (total_jets_score, score_table[SC_500K]) >= 0) { timed_mode_begin (&jets_frenzy_mode); score (SC_500K); score_add (jets_frenzy_total, score_table[SC_500K]); } else { /* Score the hit, based on level */ score_add (total_jets_score, score_table[jets_hit_scores[jets_level]]); score_long (score_table[jets_hit_scores[jets_level]]); bounded_increment (jets_hit, 255); /* Level up if needed */ if (jets_hit >= jets_needed[jets_level]) { bounded_increment (jets_level, 4); score_long (score_table[jets_level_up_scores[jets_level]]); jets_hit = 0; free_timer_restart (timer_jets_level_up, TIME_2S); sound_send (SND_WHOOSH_UP_1); } if ((score_compare (total_jets_score, score_table[SC_250K]) >= 0) && !flag_test (FLAG_250K_JETS)) callset_invoke (wheel_award_jets); deff_restart (DEFF_JET_HIT); } }
// trace initialise void trace_init(void) { if ( (trace_state==0) && (flag_test(F10_DEBUG)!=0) ) { trace_state = 1; trace_top = state.window_row_min + trace_top_given + 1; trace_bottom = trace_height + trace_top - 1; trace_left = 2; trace_right = trace_left + 0x23; trace_win_x = trace_left * 4 - 5; trace_win_y = trace_bottom * 8 + 5; trace_win_h = trace_height * 8 + 0xA; trace_win_w = 0x9A; gfx_msgbox(trace_win_x,trace_win_y,trace_win_w,trace_win_h,0x0F,0x04); } }
ssize_t read_file(iface_t *ifa, char *buf) { struct if_file *ifc = (struct if_file *) ifa->info; ssize_t nread; for(;;) { if ((nread=read(ifc->fd,buf,BUFSIZ)) <=0) { if (!flag_test(ifa,F_PERSIST)) break; close(ifc->fd); if ((ifc->fd=open(ifc->filename,O_RDONLY)) < 0) { logerr(errno,"Failed to re-open FIFO %s for reading\n", ifc->filename); break; } continue; } else break; } return nread; }
//sw_top_popper CALLSET_ENTRY (top_popper, dev_top_sol_enter) { ball_search_monitor_stop (); //BACK IN FRIDGE WIZARD MODE if (flag_test(FLAG_BACK_IN_THE_FRIDGE_ACTIVATED)) { start_back_in_the_fridge (); task_sleep_sec(1); leff_start (LEFF_TOP_POPPER); sol_request_async(SOL_TOP_POPPER); } //EXTRABALL AWARD OR MULTIBALL START OR BOTH else if (flag_test(FLAG_IS_EXTRABALL_LIT) || (!flag_test(FLAG_BACK_IN_THE_FRIDGE_RUNNING) && flag_test (FLAG_IS_MULTIBALL_ENABLED) )) { //EXTRABALL AWARD if (flag_test(FLAG_IS_EXTRABALL_LIT) ) { increment_extra_balls(); end_extraball(); leff_start (LEFF_EXTRABALL); deff_start_sync (DEFF_EXTRA_BALL_EFFECT); task_sleep_sec(1); }//end of EB //START MULTIBALL if ( !flag_test(FLAG_BACK_IN_THE_FRIDGE_RUNNING) && flag_test (FLAG_IS_MULTIBALL_ENABLED) ) { multiball_start(); task_sleep_sec(1); }//end of multiball start //do for both leff_start (LEFF_TOP_POPPER); sol_request_async(SOL_TOP_POPPER); }//END of EB or MB //START VIDEO MODE else if ( !flag_test(FLAG_BACK_IN_THE_FRIDGE_RUNNING) && !flag_test(FLAG_IS_FORTRESS_MB_RUNNING) && !flag_test(FLAG_IS_MUSEUM_MB_RUNNING) && !flag_test(FLAG_IS_CRYOPRISON_MB_RUNNING) && !flag_test(FLAG_IS_WASTELAND_MB_RUNNING) && !flag_test(FLAG_IS_DEMOTIME_RUNNING) && flag_test (FLAG_VIDEO_MODE_ENABLED) )//this is set at combos start_video_mode(1); //NOTHING SPECIAL else { score (TOP_POP_SCORE);//located in kernal/score.c //LIGHTING EFFECTS // leff_start (LEFF_UNDERGROUND_KICKOUT); deff_start_sync (DEFF_TOP_POPPER_EFFECT); //if nothing special, do normal display effects leff_start (LEFF_TOP_POPPER); sol_request_async(SOL_TOP_POPPER); }//end of else NOTHING SPECIAL ball_search_monitor_start (); }//end of function
/**************************************************************************** * * display effects * ****************************************************************************/ void combo_effect_deff(void) { U16 fno; if (IN_TEST) combo_counter++; sound_start (ST_EFFECT, SUBWAY2, SL_2S, SP_NORMAL); if (combo_counter % 2 == 0) { for (fno = IMG_COMBO1_START; fno <= IMG_COMBO1_END; fno += 2) { dmd_alloc_pair (); frame_draw(fno); dmd_show2 (); task_sleep (TIME_100MS); }//end of for loop sound_start (ST_EFFECT, SUBWAY2, SL_2S, SP_NORMAL); dmd_map_overlay (); dmd_clean_page_low (); if (flag_test (FLAG_IS_COMPUTER_ACTIVATED) ) sprintf ("COMPUTER READY"); else sprintf ("%d TO COMPUTER", combo_goal - combo_counter); font_render_string_center (&font_fixed6, DMD_MIDDLE_X, DMD_MED_CY_3, sprintf_buffer); sprintf ("%d", combo_counter); font_render_string_center (&font_fixed10, DMD_MIDDLE_X - 15, DMD_MED_CY_1 + 4, sprintf_buffer); dmd_text_outline (); dmd_alloc_pair (); frame_draw(IMG_COMBO1_END); dmd_overlay_outline (); dmd_show2 (); }//end f % 2 else { for (fno = IMG_COMBO2_START; fno <= IMG_COMBO2_END; fno += 2) { dmd_alloc_pair (); frame_draw(fno); dmd_show2 (); task_sleep (TIME_100MS); }//end of for loop sound_start (ST_EFFECT, SUBWAY2, SL_2S, SP_NORMAL); dmd_map_overlay (); dmd_clean_page_low (); if (flag_test (FLAG_VIDEO_MODE_ENABLED) ) { font_render_string_center (&font_term6, DMD_MIDDLE_X - 20, DMD_MED_CY_2 + 6, "VIDEO MODE"); font_render_string_center (&font_term6, DMD_MIDDLE_X + 45, DMD_MED_CY_3, "READY"); } else { sprintf ("%d TO", combo_vm_goal - combo_counter); font_render_string_left (&font_term6, 5, DMD_MED_CY_2, sprintf_buffer); font_render_string_left (&font_term6, 50, DMD_MED_CY_3 - 5, "VIDEO MODE"); } sprintf ("%d", combo_counter); font_render_string_center (&font_fixed10, DMD_MIDDLE_X - 20, DMD_MED_CY_1 + 2, sprintf_buffer); dmd_text_outline (); dmd_alloc_pair (); frame_draw(IMG_COMBO2_END); dmd_overlay_outline (); dmd_show2 (); }//end of else task_sleep_sec (2); deff_exit (); }//end of deff
CALLSET_ENTRY (superjets, display_update) { if (in_game && !flag_test(FLAG_VIDEO_MODE_RUNNING) ) timed_mode_display_update (&superjets_mode); }
void write_file(iface_t *ifa) { struct if_file *ifc = (struct if_file *) ifa->info; senblk_t *sptr; int usereturn=flag_test(ifa,F_NOCR)?0:1; int data=0; int cnt=1; struct iovec iov[2]; /* ifc->fd will only be < 0 if we're opening a FIFO. */ if (ifc->fd < 0) { if ((ifc->fd=open(ifc->filename,O_WRONLY)) < 0) { logerr(errno,"Failed to open FIFO %s for writing\n",ifc->filename); iface_thread_exit(errno); } if ((ifa->q =init_q(ifc->qsize)) == NULL) { logerr(errno,"Could not create queue for FIFO %s",ifc->filename); iface_thread_exit(errno); } } if (ifa->tagflags) { if ((iov[0].iov_base=malloc(TAGMAX)) == NULL) { logerr(errno,"Disabing tag output on interface id %u (%s)", ifa->id,(ifa->name)?ifa->name:"unlabelled"); ifa->tagflags=0; } else { cnt=2; data=1; } } for(;;) { if ((sptr = next_senblk(ifa->q)) == NULL) { break; } if (senfilter(sptr,ifa->ofilter)) { senblk_free(sptr,ifa->q); continue; } if (!usereturn) { sptr->data[sptr->len-2] = '\n'; sptr->len--; } if (ifa->tagflags) if ((iov[0].iov_len = gettag(ifa,iov[0].iov_base,sptr)) == 0) { logerr(errno,"Disabing tag output on interface id %u (%s)", ifa->id,(ifa->name)?ifa->name:"unlabelled"); ifa->tagflags=0; cnt=1; data=0; free(iov[0].iov_base); } iov[data].iov_base=sptr->data; iov[data].iov_len=sptr->len; if (writev(ifc->fd,iov,cnt) <0) { if (!(flag_test(ifa,F_PERSIST) && errno == EPIPE) ) break; if ((ifc->fd=open(ifc->filename,O_WRONLY)) < 0) break; } senblk_free(sptr,ifa->q); } if (cnt == 2) free(iov[0].iov_base); iface_thread_exit(errno); }
iface_t *init_file (iface_t *ifa) { struct if_file *ifc; struct kopts *opt; struct stat statbuf; int ret; int append=0; uid_t uid=-1; gid_t gid=-1; struct passwd *owner; struct group *group; mode_t tperm,perm=0; char *cp; if ((ifc = (struct if_file *)malloc(sizeof(struct if_file))) == NULL) { logerr(errno,"Could not allocate memory"); return(NULL); } memset ((void *)ifc,0,sizeof(struct if_file)); ifc->qsize=DEFFILEQSIZE; ifc->fd=-1; ifa->info = (void *) ifc; for(opt=ifa->options;opt;opt=opt->next) { if (!strcasecmp(opt->var,"filename")) { if (strcmp(opt->val,"-")) if ((ifc->filename=strdup(opt->val)) == NULL) { logerr(errno,"Failed to duplicate argument string"); return(NULL); } } else if (!strcasecmp(opt->var,"qsize")) { if (!(ifc->qsize=atoi(opt->val))) { logerr(0,"Invalid queue size specified: %s",opt->val); return(NULL); } } else if (!strcasecmp(opt->var,"append")) { if (!strcasecmp(opt->val,"yes")) { append++; } else if (!strcasecmp(opt->val,"no")) { append = 0; } else { logerr(0,"Invalid option \"append=%s\"",opt->val); return(NULL); } } else if (!strcasecmp(opt->var,"owner")) { if ((owner=getpwnam(opt->val)) == NULL) { logerr(0,"No such user '%s'",opt->val); return(NULL); } uid=owner->pw_uid; } else if (!strcasecmp(opt->var,"group")) { if ((group=getgrnam(opt->val)) == NULL) { logerr(0,"No such group '%s'",opt->val); return(NULL); } gid=group->gr_gid; } else if (!strcasecmp(opt->var,"perm")) { for (cp=opt->val;*cp;cp++) { if (*cp >= '0' && *cp < '8') { perm <<=3; perm += (*cp-'0'); } else { perm = 0; break; } } perm &= ACCESSPERMS; if (perm == 0) { logerr(0,"Invalid permissions for tty device \'%s\'",opt->val); return 0; } } else { logerr(0,"Unknown interface option %s\n",opt->var); return(NULL); } } /* We do allow use of stdin and stdout, but not if they're connected to * a terminal. This allows re-direction in background mode */ if (ifc->filename == NULL) { if (flag_test(ifa,F_PERSIST)) { logerr(0,"Can't use persist mode with stdin/stdout"); return(NULL); } if (((ifa->direction != IN) && (((struct if_engine *)ifa->lists->engine->info)->flags & K_NOSTDOUT)) || ((ifa->direction != OUT) && (((struct if_engine *)ifa->lists->engine->info)->flags & K_NOSTDIN))) { logerr(0,"Can't use terminal stdin/stdout in background mode"); return(NULL); } ifc->fd = (ifa->direction == IN)?STDIN_FILENO:STDOUT_FILENO; } else { if (ifa->direction == BOTH) { logerr(0,"Bi-directional file I/O only supported for stdin/stdout"); return(NULL); } if ((ret=stat(ifc->filename,&statbuf)) < 0) { if (ifa->direction != OUT) { logerr(errno,"stat %s",ifc->filename); return(NULL); } } if ((ret == 0) && S_ISFIFO(statbuf.st_mode)) { /* Special rules for FIFOs. Opening here would hang for a reading * interface with no writer. Given that we're single threaded here, * that would be bad */ if (access(ifc->filename,(ifa->direction==IN)?R_OK:W_OK) != 0) { logerr(errno,"Could not access %s",ifc->filename); return(NULL); } } else { if (flag_test(ifa,F_PERSIST)) { logerr(0,"Can't use persist mode on %s: Not a FIFO", ifc->filename); return(NULL); } if (perm) tperm=umask(0); errno=0; if (ifa->direction != IN && (ifc->fd=open(ifc->filename, O_WRONLY|O_CREAT|O_EXCL|((append)?O_APPEND:0), (perm)?perm:0664)) >= 0) { if (gid != 0 || uid != -1) { if (chown(ifc->filename,uid,gid) < 0) { logerr(errno, "Failed to set ownership or group on output file %s",ifc->filename); return(NULL); } } } else { if (errno && errno != EEXIST) { logerr(errno,"Failed to create file %s",ifc->filename); return(NULL); } if ((ifc->fd=open(ifc->filename,(ifa->direction==IN)?O_RDONLY: (O_WRONLY|((append)?O_APPEND:O_TRUNC)))) < 0) { logerr(errno,"Failed to open file %s",ifc->filename); return(NULL); } } /* reset umask: not really necessary */ if (perm) (void) umask(tperm); } } free_options(ifa->options); ifa->write=write_file; ifa->read=file_read_wrapper; ifa->readbuf=read_file; ifa->cleanup=cleanup_file; if (ifa->direction != IN && ifc->fd >= 0) if ((ifa->q =init_q(ifc->qsize)) == NULL) { logerr(0,"Could not create queue"); cleanup_file(ifa); return(NULL); } if (ifa->direction == BOTH) { if ((ifa->next=ifdup(ifa)) == NULL) { logerr(0,"Interface duplication failed"); cleanup_file(ifa); return(NULL); } ifa->direction=OUT; ifa->pair->direction=IN; ifc = (struct if_file *) ifa->pair->info; ifc->fd=STDIN_FILENO; } return(ifa); }
char *formatflags() { static char fmt[20]; fmt[0] = flag_test(wqcastlep(), 'Q'); fmt[1] = flag_test(wkcastlep(), 'K'); fmt[2] = flag_test(bqcastlep(), 'q'); fmt[3] = flag_test(bkcastlep(), 'k'); fmt[4] = flag_test(castledp(), 'C'); fmt[5] = flag_test(enpassantedp(), 'E'); fmt[6] = flag_test(doublepushp(), 'P'); fmt[7] = flag_test(wkcastledp(), 'K'); fmt[8] = flag_test(wqcastledp(), 'Q'); fmt[9] = flag_test(bkcastledp(), 'k'); fmt[10] = flag_test(bqcastledp(), 'q'); fmt[11] = tomove() == WHITE ? 'W' : 'B'; fmt[12] = 0; return fmt; }
CALLSET_ENTRY (prison_break, display_update) { if (in_game && !flag_test(FLAG_VIDEO_MODE_RUNNING) ) timed_mode_display_update (&prison_break_mode); }
int main(int argc, char ** argv) { long templ; pthread_t tid; pid_t pid; char *config=NULL; iface_t *engine; struct if_engine *ifg; iface_t *ifptr,*ifptr2,*rptr; iface_t **tiptr; unsigned int i=1; int opt,err=0; void *ret; struct kopts *options=NULL; sigset_t set; struct iolists lists = { /* initialize io_mutex separately below */ .init_mutex = PTHREAD_MUTEX_INITIALIZER, .init_cond = PTHREAD_COND_INITIALIZER, .dead_cond = PTHREAD_COND_INITIALIZER, .initialized = NULL, .outputs = NULL, .inputs = NULL, .dead = NULL }; struct rlimit lim; int gotinputs=0; int rcvdsig; struct sigaction sa; pthread_mutex_init(&lists.io_mutex,NULL); /* command line argument processing */ while ((opt=getopt(argc,argv,"d:f:o:V")) != -1) { switch (opt) { case 'd': if ((((templ=strtol(optarg,NULL,0)) == 0) && (errno == EINVAL || errno == ERANGE )) || (templ < 0) || (templ > 9)) { logerr(errno,"Bad debug level %s: Must be 1-9",optarg); err++; } else debuglevel=templ; break; case 'o': if (cmdlineopt(&options,optarg) < 0) err++; break; case 'f': config=optarg; break; case 'V': printf("%s\n",VERSION); if (argc == 2) exit(0); else err++; break; default: err++; } } if (err) { fprintf(stderr, "Usage: %s [-V] | [ -f <config file>] [-o <option=value>]... [<interface specification> ...]\n",argv[0]); exit(1); } /* If a config file is specified by a commad line argument, read it. If * not, look for a default config file unless told not to using "-f-" on the * command line */ if ((config && (strcmp(config,"-"))) || (!config && (config = get_def_config()))) { DEBUG(1,"Using config file %s",config); if ((engine=parse_file(config)) == NULL) { fprintf(stderr,"Error parsing config file: %s\n",errno? strerror(errno):"Syntax Error"); exit(1); } } else { /* global options for engine configuration are also returned in config * file parsing. If we didn't do that, get default options here */ DEBUG(1,"Not using config file"); engine = get_default_global(); } proc_engine_options(engine,options); engine->lists = &lists; lists.engine=engine; for (tiptr=&engine->next;optind < argc;optind++) { if (!(ifptr=parse_arg(argv[optind]))) { fprintf(stderr,"Failed to parse interface specifier %s\n", argv[optind]); exit(1); } ifptr->next=(*tiptr); (*tiptr)=ifptr; tiptr=&ifptr->next; } /* We choose to go into the background here before interface initialzation * rather than later. Disadvantage: Errors don't get fed back on stderr. * Advantage: We can close all the file descriptors now rather than pulling * then from under erroneously specified stdin/stdout etc. */ ifg=(struct if_engine *)engine->info; if (ifg->flags & K_BACKGROUND) { if ((pid = fork()) < 0) { perror("fork failed"); exit(1); } else if (pid) exit(0); /* Continue here as child */ /* Really should close all file descriptors. Harder to do in OS * independent way. Just close the ones we know about for this cut * Check first if connected to a tty to allow redirection / piping in * background mode */ if (isatty(fileno(stdin))) { fclose(stdin); ifg->flags |= K_NOSTDIN; } if (isatty(fileno(stdout))) { fclose(stdout); ifg->flags |= K_NOSTDOUT; } if (isatty(fileno(stderr))) { fclose(stderr); ifg->flags |= K_NOSTDERR; } setsid(); (void) chdir("/"); umask(0); } /* log to stderr or syslog, as appropriate */ initlog((ifg->flags & K_NOSTDERR)?ifg->logto:-1); /* Lower max open files if necessary. We do this to ensure that ids for * all connections can be represented in IDMINORBITS. Actually we only * need to do that per server, so this is a bit of a hack and should be * corrected */ if (getrlimit(RLIMIT_NOFILE,&lim) < 0) logterm(errno,"Couldn't get resource limits"); if (lim.rlim_cur > 1<<IDMINORBITS) { logwarn("Lowering NOFILE from %u to %u",lim.rlim_cur,1<<IDMINORBITS); lim.rlim_cur=1<<IDMINORBITS; if(setrlimit(RLIMIT_NOFILE,&lim) < 0) logterm(errno,"Could not set file descriptor limit"); } /* our list of "real" interfaces starts after the first which is the * dummy "interface" specifying the multiplexing engine * walk the list, initialising the interfaces. Sometimes "BOTH" interfaces * are initialised to one IN and one OUT which then need to be linked back * into the list */ for (ifptr=engine->next,tiptr=&lists.initialized,i=0;ifptr;ifptr=ifptr2) { ifptr2 = ifptr->next; if (i == MAXINTERFACES) logterm(0,"Too many interfaces"); ifptr->id=++i<<IDMINORBITS; if (ifptr->name) { if (insertname(ifptr->name,ifptr->id) < 0) logterm(errno,"Failed to associate interface name and id"); } ifptr->lists = &lists; if ((rptr=(*iftypes[ifptr->type].init_func)(ifptr)) == NULL) { logerr(0,"Failed to initialize Interface %s",(ifptr->name)? ifptr->name:"(unnamed)"); if (!flag_test(ifptr,F_OPTIONAL)) { timetodie++; break; } /* Free all resources associated with interface * This is a bigger task than it looks. Before the "optional" * flag this was not an issue as we'd just be exiting after this * Now we need to clean up properly but not yet implemented. This * is a little memory leak with each failed init attempt */ free(ifptr); continue; } for (;ifptr;ifptr = ifptr->next) { /* This loop should be done once for IN or OUT interfaces twice for * interfaces where the initialisation routine has expanded them to an * IN/OUT pair. */ if (ifptr->direction == IN) ifptr->q=engine->q; if (ifptr->checksum <0) ifptr->checksum = engine->checksum; if (ifptr->strict <0) ifptr->strict = engine->strict; (*tiptr)=ifptr; tiptr=&ifptr->next; if (ifptr->next==ifptr2) ifptr->next=NULL; } } /* One more spin through the list now we've initialised the name to id * mapping so we can update references to "name" with an id */ for (ifptr=engine->next;ifptr;ifptr=ifptr->next) { if (ifptr->ofilter) if (name2id(ifptr->ofilter)) logterm(errno,"Name to interface translation failed"); } /* Create the key for thread local storage: in this case for a pointer to * the interface each thread is handling */ if (pthread_key_create(&ifkey,iface_destroy)) { logerr(errno,"Error creating key"); timetodie++; } if (timetodie) { for (ifptr=lists.initialized;ifptr;ifptr=ifptr2) { ifptr2=ifptr->next; iface_destroy(ifptr); } exit(1); } if (name2id(engine->ofilter)) logterm(errno,"Failed to translate interface names to IDs"); if (engine->options) free_options(engine->options); pthread_setspecific(ifkey,(void *)&lists); reaper=pthread_self(); sigemptyset(&set); sigemptyset(&sa.sa_mask); sa.sa_handler=terminate; sa.sa_flags=0; sigaction(SIGUSR1,&sa,NULL); sigaddset(&set,SIGUSR1); sigaddset(&set,SIGUSR2); sigaddset(&set,SIGALRM); sigaddset(&set,SIGTERM); sigaddset(&set,SIGINT); pthread_sigmask(SIG_BLOCK, &set, NULL); sigdelset(&set,SIGUSR1); signal(SIGPIPE,SIG_IGN); pthread_create(&tid,NULL,run_engine,(void *) engine); pthread_mutex_lock(&lists.io_mutex); for (ifptr=lists.initialized;ifptr;ifptr=ifptr->next) { /* Check we've got at least one input */ if ((ifptr->direction == IN ) || (ifptr->direction == BOTH)) gotinputs=1; /* Create a thread to run each interface */ pthread_create(&tid,NULL,(void *)start_interface,(void *) ifptr); } while (lists.initialized) pthread_cond_wait(&lists.init_cond,&lists.io_mutex); /* Have to wait until here to do something about no inputs to * avoid deadlock on io_mutex */ if (!gotinputs) { logerr(0,"No Inputs!"); pthread_mutex_lock(&engine->q->q_mutex); engine->q->active=0; pthread_cond_broadcast(&engine->q->freshmeat); pthread_mutex_unlock(&engine->q->q_mutex); timetodie++; } /* While there are remaining outputs, wait until something is added to the * dead list, reap everything on the dead list and check for outputs again * until all the outputs have been reaped * Note that when there are no more inputs, we set the * engine's queue inactive causing it to set all the outputs' queues * inactive and shutting them down. Thus the last input exiting also shuts * everything down */ while (lists.outputs || lists.inputs || lists.dead) { if (lists.dead == NULL && (timetodie <= 0)) { pthread_mutex_unlock(&lists.io_mutex); /* Here we're waiting for SIGTERM/SIGINT (user shutdown requests), * SIGUSR2 (notifications of termination from interface threads) * and (later) SIGALRM to notify of the grace period expiry */ (void) sigwait(&set,&rcvdsig); pthread_mutex_lock(&lists.io_mutex); } if ((timetodie > 0) || ( lists.outputs == NULL && (timetodie == 0)) || rcvdsig == SIGTERM || rcvdsig == SIGINT) { timetodie=-1; /* Once we've caught a user shutdown address we don't need to be * told twice */ signal(SIGTERM,SIG_IGN); signal(SIGINT,SIG_IGN); sigdelset(&set,SIGTERM); sigdelset(&set,SIGINT); for (ifptr=lists.inputs;ifptr;ifptr=ifptr->next) { pthread_kill(ifptr->tid,SIGUSR1); } for (ifptr=lists.outputs;ifptr;ifptr=ifptr->next) { if (ifptr->q == NULL) pthread_kill(ifptr->tid,SIGUSR1); } /* Set up the graceperiod alarm */ if (graceperiod) alarm(graceperiod); } if (rcvdsig == SIGALRM || graceperiod == 0) { sigdelset(&set,SIGALRM); /* Make sure we don't come back here with 0 graceperiod */ if (graceperiod == 0) graceperiod=1; for (ifptr=lists.outputs;ifptr;ifptr=ifptr->next) { if (ifptr->q) pthread_kill(ifptr->tid,SIGUSR1); } } for (ifptr=lists.dead;ifptr;ifptr=lists.dead) { lists.dead=ifptr->next; pthread_join(ifptr->tid,&ret); free(ifptr); } } /* For neatness... */ pthread_mutex_unlock(&lists.io_mutex); exit(0); }
/* generic read routine * Args: Interface Pointer * Returns: nothing */ void do_read(iface_t *ifa) { senblk_t sblk; char buf[BUFSIZ]; char tbuf[TAGMAX]; char *bptr,*eptr,*ptr; int nread,countmax,count=0; enum sstate senstate; int nocr=flag_test(ifa,F_NOCR)?1:0; int loose = (ifa->strict)?0:1; sblk.src=ifa->id; senstate=SEN_NODATA; while ((nread=(*ifa->readbuf)(ifa,buf)) > 0) { for(bptr=buf,eptr=buf+nread;bptr<eptr;bptr++) { switch (*bptr) { case '$': case '!': ptr=sblk.data; countmax=SENMAX-(nocr|loose); count=1; *ptr++=*bptr; senstate=SEN_SENPROC; continue; case '\\': if (senstate==SEN_TAGPROC) { *ptr++=*bptr; senstate=SEN_TAGSEEN; } else { senstate=SEN_TAGPROC; ptr=tbuf; countmax=TAGMAX-1; *ptr++=*bptr; count=1; } continue; case '\r': case '\n': case '\0': if (senstate == SEN_SENPROC || senstate == SEN_TAGSEEN) { if (loose || (nocr && *bptr == '\n')) { *ptr++='\r'; *ptr='\n'; sblk.len = count+2; } else { if ((!nocr) && *bptr == '\r') { senstate = SEN_CR; *ptr++=*bptr; ++count; } else { senstate = SEN_NODATA; } continue; } } else if (senstate == SEN_CR) { if (*bptr != '\n') { senstate = SEN_NODATA; continue; } *ptr=*bptr; sblk.len = ++count; } else { senstate = SEN_NODATA; continue; } if (!(ifa->checksum && checkcksum(&sblk) && (sblk.len > 0 )) && senfilter(&sblk,ifa->ifilter) == 0) { push_senblk(&sblk,ifa->q); } senstate=SEN_NODATA; continue; default: break; } if (senstate != SEN_SENPROC && senstate != SEN_TAGPROC) { if (senstate != SEN_NODATA ) senstate=SEN_NODATA; continue; } if (count++ > countmax) { senstate=SEN_NODATA; continue; } *ptr++=*bptr; } } iface_thread_exit(errno); }
CALLSET_ENTRY (trivial, sw_left_outlane) { if (!flag_test (FLAG_BALL_AT_STEPS)) common_outlane (); }