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 mTimingScheduleAbsolute(struct mTiming* timing, struct mTimingEvent* event, int32_t when) {
54 mTimingSchedule(timing, event, when - mTimingCurrentTime(timing));
55}
56
57void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent* event) {
58 if (timing->reroot) {
59 timing->root = timing->reroot;
60 timing->reroot = NULL;
61 }
62 struct mTimingEvent** previous = &timing->root;
63 struct mTimingEvent* next = timing->root;
64 while (next) {
65 if (next == event) {
66 *previous = next->next;
67 return;
68 }
69 previous = &next->next;
70 next = next->next;
71 }
72}
73
74bool mTimingIsScheduled(const struct mTiming* timing, const struct mTimingEvent* event) {
75 const struct mTimingEvent* next = timing->root;
76 if (!next) {
77 next = timing->reroot;
78 }
79 while (next) {
80 if (next == event) {
81 return true;
82 }
83 next = next->next;
84 }
85 return false;
86}
87
88int32_t mTimingTick(struct mTiming* timing, int32_t cycles) {
89 timing->masterCycles += cycles;
90 uint32_t masterCycles = timing->masterCycles;
91 while (timing->root) {
92 struct mTimingEvent* next = timing->root;
93 int32_t nextWhen = next->when - masterCycles;
94 if (nextWhen > 0) {
95 return nextWhen;
96 }
97 timing->root = next->next;
98 next->callback(timing, next->context, -nextWhen);
99 }
100 if (timing->reroot) {
101 timing->root = timing->reroot;
102 timing->reroot = NULL;
103 *timing->nextEvent = mTimingNextEvent(timing);
104 }
105 return *timing->nextEvent;
106}
107
108int32_t mTimingCurrentTime(const struct mTiming* timing) {
109 return timing->masterCycles + *timing->relativeCycles;
110}
111
112uint64_t mTimingGlobalTime(const struct mTiming* timing) {
113 return timing->globalCycles + *timing->relativeCycles;
114}
115
116int32_t mTimingNextEvent(struct mTiming* timing) {
117 struct mTimingEvent* next = timing->root;
118 if (!next) {
119 return INT_MAX;
120 }
121 return next->when - timing->masterCycles - *timing->relativeCycles;
122}
123
124int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent* event) {
125 return event->when - timing->masterCycles - *timing->relativeCycles;
126}