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}