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