void CLIB_DECL running_machine::vlogerror(const char *format, va_list args) { // process only if there is a target if (m_logerror_list != NULL) { profiler_mark_start(PROFILER_LOGERROR); // dump to the buffer vsnprintf(giant_string_buffer, ARRAY_LENGTH(giant_string_buffer), format, args); // log to all callbacks for (logerror_callback_item *cb = m_logerror_list; cb != NULL; cb = cb->m_next) (*cb->m_func)(*this, giant_string_buffer); profiler_mark_end(); } }
int running_machine::run(bool firstrun) { int error = MAMERR_NONE; // use try/catch for deep error recovery try { // move to the init phase m_current_phase = MACHINE_PHASE_INIT; // if we have a logfile, set up the callback if (options_get_bool(&m_options, OPTION_LOG)) { file_error filerr = mame_fopen(SEARCHPATH_DEBUGLOG, "error.log", OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &m_logfile); assert_always(filerr == FILERR_NONE, "unable to open log file"); add_logerror_callback(logfile_callback); } // then finish setting up our local machine start(); // load the configuration settings and NVRAM bool settingsloaded = config_load_settings(this); nvram_load(this); sound_mute(this, FALSE); // display the startup screens ui_display_startup_screens(this, firstrun, !settingsloaded); // perform a soft reset -- this takes us to the running phase soft_reset(); // run the CPUs until a reset or exit m_hard_reset_pending = false; while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE) { profiler_mark_start(PROFILER_EXTRA); // execute CPUs if not paused if (!m_paused) m_scheduler.timeslice(); // otherwise, just pump video updates through else video_frame_update(this, false); // handle save/load if (m_saveload_schedule != SLS_NONE) handle_saveload(); profiler_mark_end(); } // and out via the exit phase m_current_phase = MACHINE_PHASE_EXIT; // save the NVRAM and configuration sound_mute(this, true); nvram_save(this); config_save_settings(this); } catch (emu_fatalerror &fatal) { mame_printf_error("%s\n", fatal.string()); error = MAMERR_FATALERROR; if (fatal.exitcode() != 0) error = fatal.exitcode(); } catch (emu_exception &) { mame_printf_error("Caught unhandled emulator exception\n"); error = MAMERR_FATALERROR; } catch (std::bad_alloc &) { mame_printf_error("Out of memory!\n"); error = MAMERR_FATALERROR; } // call all exit callbacks registered call_notifiers(MACHINE_NOTIFY_EXIT); // close the logfile if (m_logfile != NULL) mame_fclose(m_logfile); return error; }
astring *_profiler_get_text(running_machine *machine, astring *string) { static const profile_string names[] = { { PROFILER_MEMREAD, "Memory Read" }, { PROFILER_MEMWRITE, "Memory Write" }, { PROFILER_VIDEO, "Video Update" }, { PROFILER_DRAWGFX, "drawgfx" }, { PROFILER_COPYBITMAP, "copybitmap" }, { PROFILER_TILEMAP_DRAW, "Tilemap Draw" }, { PROFILER_TILEMAP_DRAW_ROZ, "Tilemap ROZ Draw" }, { PROFILER_TILEMAP_UPDATE, "Tilemap Update" }, { PROFILER_BLIT, "OSD Blitting" }, { PROFILER_SOUND, "Sound Generation" }, { PROFILER_TIMER_CALLBACK, "Timer Callbacks" }, { PROFILER_INPUT, "Input Processing" }, { PROFILER_MOVIE_REC, "Movie Recording" }, { PROFILER_LOGERROR, "Error Logging" }, { PROFILER_EXTRA, "Unaccounted/Overhead" }, { PROFILER_USER1, "User 1" }, { PROFILER_USER2, "User 2" }, { PROFILER_USER3, "User 3" }, { PROFILER_USER4, "User 4" }, { PROFILER_USER5, "User 5" }, { PROFILER_USER6, "User 6" }, { PROFILER_USER7, "User 7" }, { PROFILER_USER8, "User 8" }, { PROFILER_PROFILER, "Profiler" }, { PROFILER_IDLE, "Idle" } }; UINT64 computed, normalize, total; int curtype, curmem, switches; profiler_mark_start(PROFILER_PROFILER); /* compute the total time for all bits, not including profiler or idle */ computed = 0; for (curtype = 0; curtype < PROFILER_PROFILER; curtype++) for (curmem = 0; curmem < ARRAY_LENGTH(global_profiler.data); curmem++) computed += global_profiler.data[curmem].duration[curtype]; /* save that result in normalize, and continue adding the rest */ normalize = computed; for ( ; curtype < PROFILER_TOTAL; curtype++) for (curmem = 0; curmem < ARRAY_LENGTH(global_profiler.data); curmem++) computed += global_profiler.data[curmem].duration[curtype]; /* this becomes the total; if we end up with 0 for anything, we were just started, so return empty */ total = computed; astring_reset(string); if (total == 0 || normalize == 0) goto out; /* loop over all types and generate the string */ for (curtype = 0; curtype < PROFILER_TOTAL; curtype++) { /* determine the accumulated time for this type */ computed = 0; for (curmem = 0; curmem < ARRAY_LENGTH(global_profiler.data); curmem++) computed += global_profiler.data[curmem].duration[curtype]; /* if we have non-zero data and we're ready to display, do it */ if (global_profiler.dataready && computed != 0) { int nameindex; /* start with the un-normalized percentage */ astring_catprintf(string, "%02d%% ", (int)((computed * 100 + total/2) / total)); /* followed by the normalized percentage for everything but profiler and idle */ if (curtype < PROFILER_PROFILER) astring_catprintf(string, "%02d%% ", (int)((computed * 100 + normalize/2) / normalize)); /* and then the text */ if (curtype >= PROFILER_CPU_FIRST && curtype <= PROFILER_CPU_MAX) astring_catprintf(string, "CPU '%s'", device_list_find_by_index(machine->config->devicelist, CPU, curtype - PROFILER_CPU_FIRST)->tag); else for (nameindex = 0; nameindex < ARRAY_LENGTH(names); nameindex++) if (names[nameindex].type == curtype) { astring_catc(string, names[nameindex].string); break; } /* followed by a carriage return */ astring_catc(string, "\n"); } } /* followed by context switches */ if (global_profiler.dataready) { switches = 0; for (curmem = 0; curmem < ARRAY_LENGTH(global_profiler.data); curmem++) switches += global_profiler.data[curmem].context_switches; astring_catprintf(string, "%d CPU switches\n", switches / (int) ARRAY_LENGTH(global_profiler.data)); } /* advance to the next dataset and reset it to 0 */ global_profiler.dataindex = (global_profiler.dataindex + 1) % ARRAY_LENGTH(global_profiler.data); memset(&global_profiler.data[global_profiler.dataindex], 0, sizeof(global_profiler.data[global_profiler.dataindex])); /* we are ready once we have wrapped around */ if (global_profiler.dataindex == 0) global_profiler.dataready = TRUE; out: profiler_mark_end(); return string; }
void timer_execute_timers(running_machine *machine) { timer_private *global = machine->timer_data; emu_timer *timer; /* if the current quantum has expired, find a new one */ if (attotime_compare(global->exec.basetime, global->quantum_current->expire) >= 0) { int curr; global->quantum_current->requested = 0; global->quantum_current = &global->quantum_list[0]; for (curr = 1; curr < ARRAY_LENGTH(global->quantum_list); curr++) if (global->quantum_list[curr].requested != 0 && global->quantum_list[curr].requested < global->quantum_current->requested) global->quantum_current = &global->quantum_list[curr]; global->exec.curquantum = global->quantum_current->actual; } LOG(("timer_set_global_time: new=%s head->expire=%s\n", attotime_string(global->exec.basetime, 9), attotime_string(global->activelist->expire, 9))); /* now process any timers that are overdue */ while (attotime_compare(global->activelist->expire, global->exec.basetime) <= 0) { int was_enabled = global->activelist->enabled; /* if this is a one-shot timer, disable it now */ timer = global->activelist; if (attotime_compare(timer->period, attotime_zero) == 0 || attotime_compare(timer->period, attotime_never) == 0) timer->enabled = FALSE; /* set the global state of which callback we're in */ global->callback_timer_modified = FALSE; global->callback_timer = timer; global->callback_timer_expire_time = timer->expire; /* call the callback */ if (was_enabled && timer->callback != NULL) { LOG(("Timer %s:%d[%s] fired (expire=%s)\n", timer->file, timer->line, timer->func, attotime_string(timer->expire, 9))); profiler_mark_start(PROFILER_TIMER_CALLBACK); (*timer->callback)(machine, timer->ptr, timer->param); profiler_mark_end(); } /* clear the callback timer global */ global->callback_timer = NULL; /* reset or remove the timer, but only if it wasn't modified during the callback */ if (!global->callback_timer_modified) { /* if the timer is temporary, remove it now */ if (timer->temporary) timer_remove(timer); /* otherwise, reschedule it */ else { timer->start = timer->expire; timer->expire = attotime_add(timer->expire, timer->period); timer_list_remove(timer); timer_list_insert(timer); } } } }
static TIMER_CALLBACK( sound_update ) { UINT32 finalmix_step, finalmix_offset; int samples_this_update = 0; int sample; sound_private *global = machine->sound_data; INT16 *finalmix; INT32 *leftmix, *rightmix; VPRINTF(("sound_update\n")); profiler_mark_start(PROFILER_SOUND); leftmix = global->leftmix; rightmix = global->rightmix; finalmix = global->finalmix; /* force all the speaker streams to generate the proper number of samples */ for (speaker_device *speaker = speaker_first(*machine); speaker != NULL; speaker = speaker_next(speaker)) speaker->mix(leftmix, rightmix, samples_this_update, !global->enabled || global->nosound_mode); /* now downmix the final result */ finalmix_step = video_get_speed_factor(); finalmix_offset = 0; for (sample = global->finalmix_leftover; sample < samples_this_update * 100; sample += finalmix_step) { int sampindex = sample / 100; INT32 samp; /* clamp the left side */ samp = leftmix[sampindex]; if (samp < -32768) samp = -32768; else if (samp > 32767) samp = 32767; finalmix[finalmix_offset++] = samp; /* clamp the right side */ samp = rightmix[sampindex]; if (samp < -32768) samp = -32768; else if (samp > 32767) samp = 32767; finalmix[finalmix_offset++] = samp; } global->finalmix_leftover = sample - samples_this_update * 100; /* play the result */ if (finalmix_offset > 0) { osd_update_audio_stream(machine, finalmix, finalmix_offset / 2); video_avi_add_sound(machine, finalmix, finalmix_offset / 2); if (global->wavfile != NULL) wav_add_data_16(global->wavfile, finalmix, finalmix_offset); } /* update the streamer */ streams_update(machine); profiler_mark_end(); }
static void draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect) { int offs; const UINT8 *gfx; profiler_mark_start(PROFILER_USER1); gfx = memory_region(machine, "gfx2"); for (offs = 0;offs < spriteram_size;offs += 4) { int sx,sy,flipy,zoom,ch,x,px,y; const UINT8 *lookup; const UINT8 *zoomx_rom,*zoomy_rom; sx = spriteram[offs+3] - ((spriteram[offs+2] & 0x80) << 1); sy = 256-64 - spriteram[offs] + ((spriteram[offs+1] & 0x80) << 1); flipy = spriteram[offs+1] & 0x40; zoom = spriteram[offs+1] & 0x3f; zoomy_rom = gfx + (zoom << 6); zoomx_rom = gfx + 0x2000 + (zoom << 3); lookup = buggychl_sprite_lookup + ((spriteram[offs+2] & 0x7f) << 6); for (y = 0;y < 64;y++) { int dy = flip_screen_y_get(machine) ? (255 - sy - y) : (sy + y); if ((dy & ~0xff) == 0) { int charline,base_pos; charline = zoomy_rom[y] & 0x07; base_pos = zoomy_rom[y] & 0x38; if (flipy) base_pos ^= 0x38; px = 0; for (ch = 0;ch < 4;ch++) { int pos,code,realflipy; const UINT8 *pendata; pos = base_pos + 2*ch; code = 8 * (lookup[pos] | ((lookup[pos+1] & 0x07) << 8)); realflipy = (lookup[pos+1] & 0x80) ? !flipy : flipy; code += (realflipy ? (charline ^ 7) : charline); pendata = gfx_element_get_data(machine->gfx[1], code); for (x = 0;x < 16;x++) { int col; col = pendata[x]; if (col) { int dx = flip_screen_x_get(machine) ? (255 - sx - px) : (sx + px); if ((dx & ~0xff) == 0) *BITMAP_ADDR16(bitmap, dy, dx) = sprite_color_base + col; } /* the following line is almost certainly wrong */ if (zoomx_rom[7-(2*ch+x/8)] & (1 << (x & 7))) px++; } } } } } profiler_mark_end(); }