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}