all repos — mgba @ 5f59ad4c43b530f0754c883e61c2afa8fdd6c3fb

mGBA Game Boy Advance Emulator

src/core/interface.c (view raw)

  1/* Copyright (c) 2013-2015 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/interface.h>
  7
  8#include <mgba/core/core.h>
  9#include <mgba/core/serialize.h>
 10
 11DEFINE_VECTOR(mCoreCallbacksList, struct mCoreCallbacks);
 12
 13static void _rtcGenericSample(struct mRTCSource* source) {
 14	struct mRTCGenericSource* rtc = (struct mRTCGenericSource*) source;
 15	switch (rtc->override) {
 16	default:
 17		if (rtc->custom->sample) {
 18			return rtc->custom->sample(rtc->custom);
 19		}
 20		break;
 21	case RTC_NO_OVERRIDE:
 22	case RTC_FIXED:
 23	case RTC_FAKE_EPOCH:
 24		break;
 25	}
 26}
 27
 28static time_t _rtcGenericCallback(struct mRTCSource* source) {
 29	struct mRTCGenericSource* rtc = (struct mRTCGenericSource*) source;
 30	switch (rtc->override) {
 31	default:
 32		if (rtc->custom->unixTime) {
 33			return rtc->custom->unixTime(rtc->custom);
 34		}
 35		// Fall through
 36	case RTC_NO_OVERRIDE:
 37		return time(0);
 38	case RTC_FIXED:
 39		return rtc->value / 1000LL;
 40	case RTC_FAKE_EPOCH:
 41		return (rtc->value + rtc->p->frameCounter(rtc->p) * (rtc->p->frameCycles(rtc->p) * 1000LL) / rtc->p->frequency(rtc->p)) / 1000LL;
 42	}
 43}
 44
 45static void _rtcGenericSerialize(struct mRTCSource* source, struct mStateExtdataItem* item) {
 46	struct mRTCGenericSource* rtc = (struct mRTCGenericSource*) source;
 47	struct mRTCGenericState state = {
 48		.type = rtc->override,
 49		.padding = 0,
 50		.value = rtc->value
 51	};
 52	void* data;
 53	if (rtc->override >= RTC_CUSTOM_START && rtc->custom->serialize) {
 54		rtc->custom->serialize(rtc->custom, item);
 55		data = malloc(item->size + sizeof(state));
 56		uint8_t* oldData = data;
 57		oldData += sizeof(state);
 58		memcpy(oldData, item->data, item->size);
 59		item->size += sizeof(state);
 60		if (item->clean) {
 61			item->clean(item->data);
 62		}
 63	} else {
 64		item->size = sizeof(state);
 65		data = malloc(item->size);
 66	}
 67	memcpy(data, &state, sizeof(state));
 68	item->data = data;
 69	item->clean = free;
 70}
 71
 72static bool _rtcGenericDeserialize(struct mRTCSource* source, const struct mStateExtdataItem* item) {
 73	struct mRTCGenericSource* rtc = (struct mRTCGenericSource*) source;
 74	struct mRTCGenericState* state = item->data;
 75	if (!state || item->size < (ssize_t) sizeof(*state)) {
 76		return false;
 77	}
 78	if (state->type >= RTC_CUSTOM_START) {
 79		if (!rtc->custom) {
 80			return false;
 81		}
 82		if (rtc->custom->deserialize) {
 83			uint8_t* oldData = item->data;
 84			oldData += sizeof(state);
 85			struct mStateExtdataItem fakeItem = {
 86				.size = item->size - sizeof(*state),
 87				.data = oldData,
 88				.clean = NULL
 89			};
 90			if (!rtc->custom->deserialize(rtc->custom, &fakeItem)) {
 91				return false;
 92			}
 93		}
 94	}
 95	rtc->value = state->value;
 96	rtc->override = state->type;
 97	return true;
 98}
 99
100void mRTCGenericSourceInit(struct mRTCGenericSource* rtc, struct mCore* core) {
101	rtc->p = core;
102	rtc->override = RTC_NO_OVERRIDE;
103	rtc->value = 0;
104	rtc->d.sample = _rtcGenericSample;
105	rtc->d.unixTime = _rtcGenericCallback;
106	rtc->d.serialize = _rtcGenericSerialize;
107	rtc->d.deserialize = _rtcGenericDeserialize;
108}