all repos — mgba @ 6af486c7f083ae98e1c5c217b939c075b2b41505

mGBA Game Boy Advance Emulator

src/core/timing.c (view raw)

  1/* Copyright (c) 2013-2016 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/core/timing.h>
  7
  8void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent) {
  9	timing->root = NULL;
 10	timing->reroot = NULL;
 11	timing->masterCycles = 0;
 12	timing->relativeCycles = relativeCycles;
 13	timing->nextEvent = nextEvent;
 14}
 15
 16void mTimingDeinit(struct mTiming* timing) {
 17}
 18
 19void mTimingClear(struct mTiming* timing) {
 20	timing->root = NULL;
 21	timing->reroot = NULL;
 22	timing->masterCycles = 0;
 23}
 24
 25void mTimingSchedule(struct mTiming* timing, struct mTimingEvent* event, int32_t when) {
 26	int32_t nextEvent = when + *timing->relativeCycles;
 27	event->when = nextEvent + timing->masterCycles;
 28	if (nextEvent < *timing->nextEvent) {
 29		*timing->nextEvent = nextEvent;
 30	}
 31	struct mTimingEvent** previous = &timing->root;
 32	struct mTimingEvent* next = timing->root;
 33	unsigned priority = event->priority;
 34	while (next) {
 35		int32_t nextWhen = next->when - timing->masterCycles;
 36		if (nextWhen > when || (nextWhen == when && next->priority > priority)) {
 37			break;
 38		}
 39		previous = &next->next;
 40		next = next->next;
 41	}
 42	event->next = next;
 43	*previous = event;
 44}
 45
 46void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent* event) {
 47	struct mTimingEvent** previous = &timing->root;
 48	struct mTimingEvent* next = timing->root;
 49	while (next) {
 50		if (next == event) {
 51			*previous = next->next;
 52			return;
 53		}
 54		previous = &next->next;
 55		next = next->next;
 56	}
 57}
 58
 59bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent* event) {
 60	const struct mTimingEvent* next = timing->root;
 61	while (next) {
 62		if (next == event) {
 63			return true;
 64		}
 65		next = next->next;
 66	}
 67	return false;
 68}
 69
 70int32_t mTimingTick(struct mTiming* timing, int32_t cycles) {
 71	timing->masterCycles += cycles;
 72	uint32_t masterCycles = timing->masterCycles;
 73	while (timing->root) {
 74		struct mTimingEvent* next = timing->root;
 75		int32_t nextWhen = next->when - masterCycles;
 76		if (nextWhen > 0) {
 77			return nextWhen;
 78		}
 79		timing->root = next->next;
 80		next->callback(timing, next->context, -nextWhen);
 81	}
 82	if (timing->reroot) {
 83		timing->root = timing->reroot;
 84		timing->reroot = NULL;
 85		*timing->nextEvent = mTimingNextEvent(timing); 
 86	}
 87	return *timing->nextEvent;
 88}
 89
 90int32_t mTimingCurrentTime(const struct mTiming* timing) {
 91	return timing->masterCycles + *timing->relativeCycles;
 92}
 93
 94int32_t mTimingNextEvent(struct mTiming* timing) {
 95	struct mTimingEvent* next = timing->root;
 96	if (!next) {
 97		return INT_MAX;
 98	}
 99	return next->when - timing->masterCycles - *timing->relativeCycles;
100}
101
102int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent* event) {
103	return event->when - timing->masterCycles - *timing->relativeCycles;
104}