Beispiel #1
0
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();
	}
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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);
			}
		}
	}
}
Beispiel #5
0
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();
}
Beispiel #6
0
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();
}