all repos — mgba @ b61b8a0d2be4d4ac39b497b4ce85259250eec3d7

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