all repos — mgba @ 741ac61baac7bec7101e7c24b35a13ad3e69d058

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	if (timing->reroot) {
 32		timing->root = timing->reroot;
 33		timing->reroot = NULL;
 34	}
 35	struct mTimingEvent** previous = &timing->root;
 36	struct mTimingEvent* next = timing->root;
 37	unsigned priority = event->priority;
 38	while (next) {
 39		int32_t nextWhen = next->when - timing->masterCycles;
 40		if (nextWhen > nextEvent || (nextWhen == nextEvent && next->priority > priority)) {
 41			break;
 42		}
 43		previous = &next->next;
 44		next = next->next;
 45	}
 46	event->next = next;
 47	*previous = event;
 48}
 49
 50void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent* event) {
 51	if (timing->reroot) {
 52		timing->root = timing->reroot;
 53		timing->reroot = NULL;
 54	}
 55	struct mTimingEvent** previous = &timing->root;
 56	struct mTimingEvent* next = timing->root;
 57	while (next) {
 58		if (next == event) {
 59			*previous = next->next;
 60			return;
 61		}
 62		previous = &next->next;
 63		next = next->next;
 64	}
 65}
 66
 67bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent* event) {
 68	const struct mTimingEvent* next = timing->root;
 69	if (!next) {
 70		next = timing->reroot;
 71	}
 72	while (next) {
 73		if (next == event) {
 74			return true;
 75		}
 76		next = next->next;
 77	}
 78	return false;
 79}
 80
 81int32_t mTimingTick(struct mTiming* timing, int32_t cycles) {
 82	timing->masterCycles += cycles;
 83	uint32_t masterCycles = timing->masterCycles;
 84	while (timing->root) {
 85		struct mTimingEvent* next = timing->root;
 86		int32_t nextWhen = next->when - masterCycles;
 87		if (nextWhen > 0) {
 88			return nextWhen;
 89		}
 90		timing->root = next->next;
 91		next->callback(timing, next->context, -nextWhen);
 92	}
 93	if (timing->reroot) {
 94		timing->root = timing->reroot;
 95		timing->reroot = NULL;
 96		*timing->nextEvent = mTimingNextEvent(timing); 
 97	}
 98	return *timing->nextEvent;
 99}
100
101int32_t mTimingCurrentTime(const struct mTiming* timing) {
102	return timing->masterCycles + *timing->relativeCycles;
103}
104
105int32_t mTimingNextEvent(struct mTiming* timing) {
106	struct mTimingEvent* next = timing->root;
107	if (!next) {
108		return INT_MAX;
109	}
110	return next->when - timing->masterCycles - *timing->relativeCycles;
111}
112
113int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent* event) {
114	return event->when - timing->masterCycles - *timing->relativeCycles;
115}