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}