all repos — mgba @ 9295c3c893646713d8fce7f9d15be320787b9d97

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