all repos — mgba @ f6755a6e1b7b0cf2b944cd8ca842746f11d6bf82

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