all repos — mgba @ a506f6cd9d6fd025410f62e3b663b0aaea3f0b82

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) {
11	mTimingEventListInit(&timing->events, 0);
12	timing->masterCycles = 0;
13	timing->relativeCycles = relativeCycles;
14}
15
16void mTimingDeinit(struct mTiming* timing) {
17	mTimingEventListDeinit(&timing->events);
18}
19
20void mTimingClear(struct mTiming* timing) {
21	mTimingEventListClear(&timing->events);
22	timing->masterCycles = 0;
23}
24
25void mTimingSchedule(struct mTiming* timing, struct mTimingEvent* event, int32_t when) {
26	event->when = when + timing->masterCycles + *timing->relativeCycles;
27	size_t e;
28	for (e = 0; e < mTimingEventListSize(&timing->events); ++e) {
29		struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, e);
30		int32_t nextWhen = next->when - timing->masterCycles;
31		if (nextWhen > when) {
32			mTimingEventListUnshift(&timing->events, e, 1);
33			*mTimingEventListGetPointer(&timing->events, e) = event;
34			return;
35		}
36	}
37	*mTimingEventListAppend(&timing->events) = event;
38}
39
40void mTimingDeschedule(struct mTiming* timing, struct mTimingEvent* event) {
41	size_t e;
42	for (e = 0; e < mTimingEventListSize(&timing->events); ++e) {
43		struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, e);
44		if (next == event) {
45			mTimingEventListShift(&timing->events, e, 1);
46			return;
47		}
48	}
49}
50
51void mTimingTick(struct mTiming* timing, int32_t cycles) {
52	timing->masterCycles += cycles;
53	while (mTimingEventListSize(&timing->events)) {
54		struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, 0);
55		int32_t nextWhen = next->when - timing->masterCycles;
56		if (nextWhen > 0) {
57			return;
58		}
59		mTimingEventListShift(&timing->events, 0, 1);
60		next->callback(timing, next->context, -nextWhen);
61	}
62}
63
64int32_t mTimingNextEvent(struct mTiming* timing) {
65	if (!mTimingEventListSize(&timing->events)) {
66		return INT_MAX;
67	}
68	struct mTimingEvent* next = *mTimingEventListGetPointer(&timing->events, 0);
69	return next->when - timing->masterCycles;
70}