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}