all repos — mgba @ 4680a767c638530856255b133e7a88bf1ebb333e

mGBA Game Boy Advance Emulator

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 "timing.h"
 7
 8DEFINE_VECTOR(mTimingEventList, struct mTimingEvent*);
 9
10void mTimingInit(struct mTiming* timing, int32_t* relativeCycles, int32_t* nextEvent) {
11	mTimingEventListInit(&timing->events, 0);
12	timing->masterCycles = 0;
13	timing->relativeCycles = relativeCycles;
14	timing->nextEvent = nextEvent;
15}
16
17void mTimingDeinit(struct mTiming* timing) {
18	mTimingEventListDeinit(&timing->events);
19}
20
21void mTimingClear(struct mTiming* timing) {
22	mTimingEventListClear(&timing->events);
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	size_t e;
33	for (e = 0; e < mTimingEventListSize(&timing->events); ++e) {
34		struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, e);
35		int32_t nextWhen = next->when - timing->masterCycles;
36		if (nextWhen > when) {
37			mTimingEventListUnshift(&timing->events, e, 1);
38			*mTimingEventListGetPointer(&timing->events, e) = event;
39			return;
40		}
41	}
42	*mTimingEventListAppend(&timing->events) = event;
43}
44
45void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent* event) {
46	size_t e;
47	for (e = 0; e < mTimingEventListSize(&timing->events); ++e) {
48		struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, e);
49		if (next == event) {
50			mTimingEventListShift(&timing->events, e, 1);
51			return;
52		}
53	}
54}
55
56void mTimingTick(struct mTiming* timing, int32_t cycles) {
57	timing->masterCycles += cycles;
58	while (mTimingEventListSize(&timing->events)) {
59		struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, 0);
60		int32_t nextWhen = next->when - timing->masterCycles;
61		if (nextWhen > 0) {
62			*timing->nextEvent = nextWhen;
63			return;
64		}
65		mTimingEventListShift(&timing->events, 0, 1);
66		next->callback(timing, next->context, -nextWhen);
67	}
68}
69
70int32_t mTimingNextEvent(struct mTiming* timing) {
71	if (!mTimingEventListSize(&timing->events)) {
72		return INT_MAX;
73	}
74	struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, 0);
75	return next->when - timing->masterCycles;
76}