static void command_trace(void) { #if defined(MAME_DEBUG) && defined(NEW_DEBUGGER) int cpunum; FILE *file; char filename[256]; for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { if (cpu_gettotalcpu() == 1) snprintf(filename, sizeof(filename) / sizeof(filename[0]), "_%s.tr", current_testcase.name); else snprintf(filename, sizeof(filename) / sizeof(filename[0]), "_%s.%d.tr", current_testcase.name, cpunum); file = fopen(filename, "w"); if (file) { report_message(MSG_INFO, "Tracing CPU #%d: %s", cpunum, filename); debug_cpu_trace(cpunum, file, FALSE, NULL); } } #else state = STATE_ABORTED; report_message(MSG_FAILURE, "Cannot trace; debugger not present"); #endif }
int cpuint_init(void) { int cpunum; int irqline; /* loop over all CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { /* reset the IRQ lines */ for (irqline = 0; irqline < MAX_IRQ_LINES; irqline++) { irq_line_state[cpunum][irqline] = CLEAR_LINE; interrupt_vector[cpunum][irqline] = irq_line_vector[cpunum][irqline] = cpunum_default_irq_vector(cpunum); } /* reset the IRQ event queues */ irq_event_index[cpunum] = 0; } /* set up some stuff to save */ state_save_set_current_tag(0); state_save_register_UINT8("cpu", 0, "irq enable", interrupt_enable, cpu_gettotalcpu()); state_save_register_INT32("cpu", 0, "irq vector", &interrupt_vector[0][0],cpu_gettotalcpu() * MAX_IRQ_LINES); state_save_register_UINT8("cpu", 0, "irqline state", &irq_line_state[0][0], cpu_gettotalcpu() * MAX_IRQ_LINES); state_save_register_INT32("cpu", 0, "irqline vector", &irq_line_vector[0][0], cpu_gettotalcpu() * MAX_IRQ_LINES); return 0; }
static void cpu_pre_run(void) { int cpunum; logerror("Machine reset\n"); begin_resource_tracking(); /* read hi scores information from hiscore.dat */ hs_open(Machine->gamedrv->name); hs_init(); /* initialize the various timers (suspends all CPUs at startup) */ cpu_inittimers(); watchdog_counter = -1; /* reset sound chips */ sound_reset(); /* first pass over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { /* enable all CPUs (except for audio CPUs if the sound is off) */ if (!(Machine->drv->cpu[cpunum].cpu_flags & CPU_AUDIO_CPU) || Machine->sample_rate != 0) cpunum_resume(cpunum, SUSPEND_ANY_REASON); else cpunum_suspend(cpunum, SUSPEND_REASON_DISABLE, 1); /* reset the interrupt state */ cpuint_reset_cpu(cpunum); /* reset the total number of cycles */ cpu[cpunum].totalcycles = 0; cpu[cpunum].localtime = 0; } vblank = 0; /* do this AFTER the above so machine_init() can use cpu_halt() to hold the */ /* execution of some CPUs, or disable interrupts */ if (Machine->drv->machine_init) (*Machine->drv->machine_init)(); /* now reset each CPU */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) cpunum_reset(cpunum, Machine->drv->cpu[cpunum].reset_param, cpu_irq_callbacks[cpunum]); /* reset the globals */ cpu_vblankreset(); current_frame = 0; state_save_dump_registry(); }
void gottlieb_sh_w(int offset,int data) { data &= 0xff; if (data != 0xff) { if (Machine->gamedrv->samplenames) { /* if we have loaded samples, we must be Q*Bert */ switch(data ^ 0xff) { case 0x12: /* play a sample here (until Votrax speech is emulated) */ sample_start (0, 0, 0); break; case 0x14: /* play a sample here (until Votrax speech is emulated) */ sample_start (0, 1, 0); break; case 0x16: /* play a sample here (until Votrax speech is emulated) */ sample_start (0, 2, 0); break; case 0x11: /* play a sample here (until Votrax speech is emulated) */ sample_start (0, 3, 0); break; } } soundlatch_w(offset,data); switch (cpu_gettotalcpu()) { case 2: /* Revision 1 sound board */ cpu_cause_interrupt(1,M6502_INT_IRQ); break; case 3: case 4: /* Revision 2 & 3 sound board */ cpu_cause_interrupt(cpu_gettotalcpu()-1,M6502_INT_IRQ); cpu_cause_interrupt(cpu_gettotalcpu()-2,M6502_INT_IRQ); break; } } }
void cpuint_init(running_machine *machine) { int cpunum; int line; /* loop over all CPUs and input lines */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { /* reset any driver hooks into the IRQ acknowledge callbacks */ drv_irq_callbacks[cpunum] = NULL; /* clear out all the CPU states */ for (line = 0; line < MAX_INPUT_LINES; line++) { input_line_state[cpunum][line] = CLEAR_LINE; interrupt_vector[cpunum][line] = input_line_vector[cpunum][line] = cputype_default_irq_vector(Machine->drv->cpu[cpunum].type); input_event_index[cpunum][line] = 0; } } /* set up some stuff to save */ state_save_push_tag(0); state_save_register_item_2d_array("cpu", 0, interrupt_vector); state_save_register_item_2d_array("cpu", 0, input_line_state); state_save_register_item_2d_array("cpu", 0, input_line_vector); state_save_pop_tag(); }
static void cpu_vblankcallback(int param) { int cpunum; if (vblank_countdown == 1) vblank = 1; /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { /* if the interrupt multiplier is valid */ if (cpu[cpunum].vblankint_multiplier != -1) { /* decrement; if we hit zero, generate the interrupt and reset the countdown */ if (!--cpu[cpunum].vblankint_countdown) { /* a param of -1 means don't call any callbacks */ if (param != -1) { /* if the CPU has a VBLANK handler, call it */ if (Machine->drv->cpu[cpunum].vblank_interrupt && cpu_getstatus(cpunum)) { cpuintrf_push_context(cpunum); (*Machine->drv->cpu[cpunum].vblank_interrupt)(); cpuintrf_pop_context(); } /* update the counters */ cpu[cpunum].iloops--; } /* reset the countdown and timer */ cpu[cpunum].vblankint_countdown = cpu[cpunum].vblankint_multiplier; timer_adjust(cpu[cpunum].vblankint_timer, TIME_NEVER, 0, 0); } } /* else reset the VBLANK timer if this is going to be a real VBLANK */ else if (vblank_countdown == 1) timer_adjust(cpu[cpunum].vblankint_timer, TIME_NEVER, 0, 0); } /* is it a real VBLANK? */ if (!--vblank_countdown) { /* do we update the screen now? */ if (!(Machine->drv->video_attributes & VIDEO_UPDATE_AFTER_VBLANK)) time_to_quit = updatescreen(); /* Set the timer to update the screen */ timer_set(TIME_IN_USEC(Machine->drv->vblank_duration), 0, cpu_updatecallback); /* reset the globals */ cpu_vblankreset(); /* reset the counter */ vblank_countdown = vblank_multiplier; } }
void cpu_exit(void) { int cpunum; /* shut down the CPU cores */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) cpuintrf_exit_cpu(cpunum); }
static void interrupt_reset(running_machine *machine) { int cpunum; /* on a reset, enable all interrupts */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) interrupt_enable[cpunum] = 1; }
void cpunum_set_input_line_vector(int cpunum, int line, int vector) { if (cpunum < cpu_gettotalcpu() && line >= 0 && line < MAX_INPUT_LINES) { LOG(("cpunum_set_input_line_vector(%d,%d,$%04x)\n",cpunum,line,vector)); interrupt_vector[cpunum][line] = vector; return; } LOG(("cpunum_set_input_line_vector CPU#%d line %d > max input lines\n", cpunum, line)); }
void cpu_irq_line_vector_w(int cpunum, int irqline, int vector) { if (cpunum < cpu_gettotalcpu() && irqline >= 0 && irqline < MAX_IRQ_LINES) { LOG(("cpu_irq_line_vector_w(%d,%d,$%04x)\n",cpunum,irqline,vector)); interrupt_vector[cpunum][irqline] = vector; return; } LOG(("cpu_irq_line_vector_w CPU#%d irqline %d > max irq lines\n", cpunum, irqline)); }
void cpu_interrupt_enable(int cpunum, int enabled) { assert_always(cpunum >= 0 && cpunum < cpu_gettotalcpu(), "cpu_interrupt_enable() called for invalid cpu num!"); /* set the new state */ interrupt_enable[cpunum] = enabled; /* make sure there are no queued interrupts */ if (enabled == 0) timer_call_after_resynch(NULL, cpunum, clear_all_lines); }
int debug_comment_init(void) { /* allocate enough comment groups for the total # of cpu's */ debug_comments = (comment_group*) malloc(cpu_gettotalcpu() * sizeof(comment_group)); /* automatically load em up */ debug_comment_load(); add_exit_callback(debug_comment_exit); return 1; }
void cpuint_reset(void) { int cpunum, line; /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) for (line = 0; line < MAX_INPUT_LINES; line++) { interrupt_vector[cpunum][line] = cpunum_default_irq_vector(cpunum); input_event_index[cpunum][line] = 0; } }
static void debug_comment_free(void) { int i, j; for (i = 0; i < cpu_gettotalcpu(); i++) { for (j = 0; j < debug_comments[i].comment_count; j++) { free(debug_comments[i].comment_info[j]); } debug_comments[i].comment_count = 0; } free(debug_comments); }
static void cpu_vblankreset(void) { int cpunum; /* read hi scores from disk */ hs_update(); /* read keyboard & update the status of the input ports */ update_input_ports(); /* reset the cycle counters */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { if (!(cpu[cpunum].suspend & SUSPEND_REASON_DISABLE)) cpu[cpunum].iloops = Machine->drv->cpu[cpunum].vblank_interrupts_per_frame - 1; else cpu[cpunum].iloops = -1; } }
bool retro_serialize(void *data, size_t size) { int cpunum; if(retro_serialize_size() && data && size) { /* write the save state */ state_save_save_begin(data); /* write tag 0 */ state_save_set_current_tag(0); if(state_save_save_continue()) { return false; } /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { cpuintrf_push_context(cpunum); /* make sure banking is set */ activecpu_reset_banking(); /* save the CPU data */ state_save_set_current_tag(cpunum + 1); if(state_save_save_continue()) return false; cpuintrf_pop_context(); } /* finish and close */ state_save_save_finish(); return true; } return false; }
bool retro_unserialize(const void * data, size_t size) { int cpunum; /* if successful, load it */ if (retro_serialize_size() && data && size && !state_save_load_begin((void*)data, size)) { /* read tag 0 */ state_save_set_current_tag(0); if(state_save_load_continue()) return false; /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { cpuintrf_push_context(cpunum); /* make sure banking is set */ activecpu_reset_banking(); /* load the CPU data */ state_save_set_current_tag(cpunum + 1); if(state_save_load_continue()) return false; cpuintrf_pop_context(); } /* finish and close */ state_save_load_finish(); return true; } return false; }
void osd_update_video_and_audio(mame_display *display) { int i; double time_limit; double current_time; int cpunum; /* if the visible area has changed, update it */ if (display->changed_flags & GAME_VISIBLE_AREA_CHANGED) { ui_set_visible_area(display->game_visible_area.min_x, display->game_visible_area.min_y, display->game_visible_area.max_x, display->game_visible_area.max_y); } /* is this the first update? if so, eat it */ if (!seen_first_update) { seen_first_update = TRUE; return; } /* if we have already aborted or completed, our work is done */ if ((state == STATE_ABORTED) || (state == STATE_DONE)) return; /* have we hit the time limit? */ current_time = timer_get_time(); time_limit = (current_testcase.time_limit != 0.0) ? current_testcase.time_limit : TIME_IN_SEC(600); if (current_time > time_limit) { state = STATE_ABORTED; report_message(MSG_FAILURE, "Time limit of %.2f seconds exceeded", time_limit); return; } /* update the runtime hash */ if (0) { for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { runtime_hash *= 57; runtime_hash ^= cpunum_get_reg(cpunum, REG_PC); /* TODO - Add more registers? */ } } for (i = 0; i < sizeof(commands) / sizeof(commands[i]); i++) { if (current_command->command_type == commands[i].command_type) { commands[i].proc(); break; } } /* if we are ready for the next command, advance to it */ if (state == STATE_READY) { /* if we are at the end, and we are dumping screenshots, and we didn't * just dump a screenshot, dump one now */ if ((test_flags & MESSTEST_ALWAYS_DUMP_SCREENSHOT) && (current_command[0].command_type != MESSTEST_COMMAND_SCREENSHOT) && (current_command[1].command_type == MESSTEST_COMMAND_END)) { dump_screenshot(TRUE); } current_command++; } }
/* callback for the timer */ static void nmi_callback(int param) { cpu_cause_interrupt(cpu_gettotalcpu()-1, M6502_INT_NMI); }
int debug_comment_save(void) { int i, j; char crc_buf[20]; xml_data_node *root = xml_file_create(); xml_data_node *commentnode, *systemnode; int total_comments = 0; /* if we don't have a root, bail */ if (!root) return 0; /* create a comment node */ commentnode = xml_add_child(root, "mamecommentfile", NULL); if (!commentnode) goto error; xml_set_attribute_int(commentnode, "version", COMMENT_VERSION); /* create a system node */ systemnode = xml_add_child(commentnode, "system", NULL); if (!systemnode) goto error; xml_set_attribute(systemnode, "name", Machine->gamedrv->name); /* for each cpu */ for (i = 0; i < cpu_gettotalcpu(); i++) { xml_data_node *curnode = xml_add_child(systemnode, "cpu", NULL); if (!curnode) goto error; xml_set_attribute_int(curnode, "num", i); for (j = 0; j < debug_comments[i].comment_count; j++) { xml_data_node *datanode = xml_add_child(curnode, "comment", debug_comments[i].comment_info[j]->text); if (!datanode) goto error; xml_set_attribute_int(datanode, "address", debug_comments[i].comment_info[j]->address); xml_set_attribute_int(datanode, "color", debug_comments[i].comment_info[j]->color); sprintf(crc_buf, "%08X", debug_comments[i].comment_info[j]->crc); xml_set_attribute(datanode, "crc", crc_buf); total_comments++; } } /* flush the file */ if (total_comments > 0) { mame_file *fp = mame_fopen(Machine->gamedrv->name, 0, FILETYPE_COMMENT, 1); xml_file_write(root, fp); mame_fclose(fp); } /* free and get out of here */ xml_file_free(root); return 1; error: xml_file_free(root); return 0; }
static void cpu_inittimers(void) { double first_time; int cpunum, max, ipf; /* allocate a dummy timer at the minimum frequency to break things up */ ipf = Machine->drv->cpu_slices_per_frame; if (ipf <= 0) ipf = 1; timeslice_period = TIME_IN_HZ(Machine->drv->frames_per_second * ipf); timeslice_timer = timer_alloc(cpu_timeslicecallback); timer_adjust(timeslice_timer, timeslice_period, 0, timeslice_period); /* allocate timers to handle interleave boosts */ interleave_boost_timer = timer_alloc(NULL); interleave_boost_timer_end = timer_alloc(end_interleave_boost); /* * The following code finds all the CPUs that are interrupting in sync with the VBLANK * and sets up the VBLANK timer to run at the minimum number of cycles per frame in * order to service all the synced interrupts */ /* find the CPU with the maximum interrupts per frame */ max = 1; for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { ipf = Machine->drv->cpu[cpunum].vblank_interrupts_per_frame; if (ipf > max) max = ipf; } /* now find the LCD with the rest of the CPUs (brute force - these numbers aren't huge) */ vblank_multiplier = max; while (1) { for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { ipf = Machine->drv->cpu[cpunum].vblank_interrupts_per_frame; if (ipf > 0 && (vblank_multiplier % ipf) != 0) break; } if (cpunum == cpu_gettotalcpu()) break; vblank_multiplier += max; } /* initialize the countdown timers and intervals */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { ipf = Machine->drv->cpu[cpunum].vblank_interrupts_per_frame; if (ipf > 0) cpu[cpunum].vblankint_countdown = cpu[cpunum].vblankint_multiplier = vblank_multiplier / ipf; else cpu[cpunum].vblankint_countdown = cpu[cpunum].vblankint_multiplier = -1; } /* allocate a vblank timer at the frame rate * the LCD number of interrupts per frame */ vblank_period = TIME_IN_HZ(Machine->drv->frames_per_second * vblank_multiplier); vblank_timer = timer_alloc(cpu_vblankcallback); vblank_countdown = vblank_multiplier; /* * The following code creates individual timers for each CPU whose interrupts are not * synced to the VBLANK, and computes the typical number of cycles per interrupt */ /* start the CPU interrupt timers */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { ipf = Machine->drv->cpu[cpunum].vblank_interrupts_per_frame; /* compute the average number of cycles per interrupt */ if (ipf <= 0) ipf = 1; cpu[cpunum].vblankint_period = TIME_IN_HZ(Machine->drv->frames_per_second * ipf); cpu[cpunum].vblankint_timer = timer_alloc(NULL); /* see if we need to allocate a CPU timer */ ipf = Machine->drv->cpu[cpunum].timed_interrupts_per_second; if (ipf) { cpu[cpunum].timedint_period = cpu_computerate(ipf); cpu[cpunum].timedint_timer = timer_alloc(cpu_timedintcallback); timer_adjust(cpu[cpunum].timedint_timer, cpu[cpunum].timedint_period, cpunum, cpu[cpunum].timedint_period); } } /* note that since we start the first frame on the refresh, we can't pulse starting immediately; instead, we back up one VBLANK period, and inch forward until we hit positive time. That time will be the time of the first VBLANK timer callback */ first_time = -TIME_IN_USEC(Machine->drv->vblank_duration) + vblank_period; while (first_time < 0) { cpu_vblankcallback(-1); first_time += vblank_period; } timer_set(first_time, 0, cpu_firstvblankcallback); }
static void handle_load(running_machine *machine) { mame_private *mame = machine->mame_data; mame_file_error filerr; mame_file *file; /* if no name, bail */ if (mame->saveload_pending_file == NULL) { mame->saveload_schedule_callback = NULL; return; } /* if there are anonymous timers, we can't load just yet because the timers might */ /* overwrite data we have loaded */ if (timer_count_anonymous() > 0) { /* if more than a second has passed, we're probably screwed */ if (sub_mame_times(mame_timer_get_time(), mame->saveload_schedule_time).seconds > 0) { popmessage("Unable to load due to pending anonymous timers. See error.log for details."); goto cancel; } return; } /* open the file */ filerr = mame_fopen(SEARCHPATH_STATE, mame->saveload_pending_file, OPEN_FLAG_READ, &file); if (filerr == FILERR_NONE) { /* start loading */ if (state_save_load_begin(file) == 0) { int cpunum; /* read tag 0 */ state_save_push_tag(0); state_save_load_continue(); state_save_pop_tag(); /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { cpuintrf_push_context(cpunum); /* make sure banking is set */ activecpu_reset_banking(); /* load the CPU data */ state_save_push_tag(cpunum + 1); state_save_load_continue(); state_save_pop_tag(); /* make sure banking is set */ activecpu_reset_banking(); cpuintrf_pop_context(); } /* finish and close */ state_save_load_finish(); popmessage("State successfully loaded."); } else popmessage("Error: Failed to load state"); mame_fclose(file); } else popmessage("Error: Failed to load state"); cancel: /* unschedule the load */ free(mame->saveload_pending_file); mame->saveload_pending_file = NULL; mame->saveload_schedule_callback = NULL; }
static void handle_save(running_machine *machine) { mame_private *mame = machine->mame_data; mame_file_error filerr; mame_file *file; /* if no name, bail */ if (mame->saveload_pending_file == NULL) { mame->saveload_schedule_callback = NULL; return; } /* if there are anonymous timers, we can't save just yet */ if (timer_count_anonymous() > 0) { /* if more than a second has passed, we're probably screwed */ if (sub_mame_times(mame_timer_get_time(), mame->saveload_schedule_time).seconds > 0) { popmessage("Unable to save due to pending anonymous timers. See error.log for details."); goto cancel; } return; } /* open the file */ filerr = mame_fopen(SEARCHPATH_STATE, mame->saveload_pending_file, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file); if (filerr == FILERR_NONE) { int cpunum; /* write the save state */ if (state_save_save_begin(file) != 0) { popmessage("Error: Unable to save state due to illegal registrations. See error.log for details."); mame_fclose(file); goto cancel; } /* write the default tag */ state_save_push_tag(0); state_save_save_continue(); state_save_pop_tag(); /* loop over CPUs */ for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { cpuintrf_push_context(cpunum); /* make sure banking is set */ activecpu_reset_banking(); /* save the CPU data */ state_save_push_tag(cpunum + 1); state_save_save_continue(); state_save_pop_tag(); cpuintrf_pop_context(); } /* finish and close */ state_save_save_finish(); mame_fclose(file); /* pop a warning if the game doesn't support saves */ if (!(machine->gamedrv->flags & GAME_SUPPORTS_SAVE)) popmessage("State successfully saved.\nWarning: Save states are not officially supported for this game."); else popmessage("State successfully saved."); } else popmessage("Error: Failed to save state"); cancel: /* unschedule the save */ free(mame->saveload_pending_file); mame->saveload_pending_file = NULL; mame->saveload_schedule_callback = NULL; }
int osd_update(mame_time emutime) { int i; double time_limit; double current_time; int cpunum; render_target_get_primitives(target); /* is this the first update? if so, eat it */ if (!seen_first_update) { seen_first_update = TRUE; goto done; } /* if we have already aborted or completed, our work is done */ if ((state == STATE_ABORTED) || (state == STATE_DONE)) { mame_schedule_exit(Machine); goto done; } /* have we hit the time limit? */ current_time = timer_get_time(); time_limit = (current_testcase.time_limit != 0.0) ? current_testcase.time_limit : TIME_IN_SEC(600); if (current_time > time_limit) { state = STATE_ABORTED; report_message(MSG_FAILURE, "Time limit of %.2f seconds exceeded", time_limit); goto done; } /* update the runtime hash */ if (0) { for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++) { runtime_hash *= 57; runtime_hash ^= cpunum_get_reg(cpunum, REG_PC); /* TODO - Add more registers? */ } } for (i = 0; i < sizeof(commands) / sizeof(commands[i]); i++) { if (current_command->command_type == commands[i].command_type) { commands[i].proc(); break; } } /* if we are ready for the next command, advance to it */ if (state == STATE_READY) { /* if we are at the end, and we are dumping screenshots, and we didn't * just dump a screenshot, dump one now */ if ((test_flags & MESSTEST_ALWAYS_DUMP_SCREENSHOT) && (current_command[0].command_type != MESSTEST_COMMAND_SCREENSHOT) && (current_command[1].command_type == MESSTEST_COMMAND_END)) { dump_screenshot(TRUE); } current_command++; } done: return FALSE; }
static WRITE8_HANDLER( mcu_reset_w ) { /* the bootlegs don't have a MCU, so make sure it's there before trying to reset it */ if (cpu_gettotalcpu() >= 4) cpunum_set_input_line(3, INPUT_LINE_RESET, data ? CLEAR_LINE : ASSERT_LINE); }