all repos — mgba @ 1a0e44c014ad34bea30d237d27015d82d02cda4b

mGBA Game Boy Advance Emulator

src/ds/timer.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/internal/ds/timer.h>
  7
  8#include <mgba/internal/arm/arm.h>
  9#include <mgba/internal/ds/ds.h>
 10
 11static void DSTimerIrq(struct DSCommon* dscore, int timerId) {
 12	struct GBATimer* timer = &dscore->timers[timerId];
 13	if (GBATimerFlagsIsIrqPending(timer->flags)) {
 14		timer->flags = GBATimerFlagsClearIrqPending(timer->flags);
 15		DSRaiseIRQ(dscore->cpu, dscore->memory.io, DS_IRQ_TIMER0 + timerId);
 16	}
 17}
 18
 19static void DSTimerIrq0(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 20	UNUSED(timing);
 21	UNUSED(cyclesLate);
 22	DSTimerIrq(context, 0);
 23}
 24
 25static void DSTimerIrq1(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 26	UNUSED(timing);
 27	UNUSED(cyclesLate);
 28	DSTimerIrq(context, 1);
 29}
 30
 31static void DSTimerIrq2(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 32	UNUSED(timing);
 33	UNUSED(cyclesLate);
 34	DSTimerIrq(context, 2);
 35}
 36
 37static void DSTimerIrq3(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 38	UNUSED(timing);
 39	UNUSED(cyclesLate);
 40	DSTimerIrq(context, 3);
 41}
 42
 43static void DSTimerUpdate0(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 44	struct DSCommon* dscore = context;
 45	GBATimerUpdate(timing, &dscore->timers[0], &dscore->memory.io[DS_REG_TM0CNT_LO >> 1], cyclesLate);
 46	GBATimerUpdateCountUp(timing, &dscore->timers[1], &dscore->memory.io[DS_REG_TM1CNT_LO >> 1], cyclesLate);
 47}
 48
 49static void DSTimerUpdate1(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 50	struct DSCommon* dscore = context;
 51	GBATimerUpdate(timing, &dscore->timers[1], &dscore->memory.io[DS_REG_TM1CNT_LO >> 1], cyclesLate);
 52	GBATimerUpdateCountUp(timing, &dscore->timers[2], &dscore->memory.io[DS_REG_TM2CNT_LO >> 1], cyclesLate);
 53}
 54
 55static void DSTimerUpdate2(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 56	struct DSCommon* dscore = context;
 57	GBATimerUpdate(timing, &dscore->timers[2], &dscore->memory.io[DS_REG_TM2CNT_LO >> 1], cyclesLate);
 58	GBATimerUpdateCountUp(timing, &dscore->timers[3], &dscore->memory.io[DS_REG_TM3CNT_LO >> 1], cyclesLate);
 59}
 60
 61static void DSTimerUpdate3(struct mTiming* timing, void* context, uint32_t cyclesLate) {
 62	struct DSCommon* dscore = context;
 63	GBATimerUpdate(timing, &dscore->timers[3], &dscore->memory.io[DS_REG_TM3CNT_LO >> 1], cyclesLate);
 64}
 65
 66void DSTimerInit(struct DS* ds) {
 67	memset(ds->ds7.timers, 0, sizeof(ds->ds7.timers));
 68	ds->ds7.timers[0].event.name = "DS7 Timer 0";
 69	ds->ds7.timers[0].event.callback = DSTimerUpdate0;
 70	ds->ds7.timers[0].event.context = &ds->ds7;
 71	ds->ds7.timers[0].event.priority = 0x20;
 72	ds->ds7.timers[1].event.name = "DS7 Timer 1";
 73	ds->ds7.timers[1].event.callback = DSTimerUpdate1;
 74	ds->ds7.timers[1].event.context = &ds->ds7;
 75	ds->ds7.timers[1].event.priority = 0x21;
 76	ds->ds7.timers[2].event.name = "DS7 Timer 2";
 77	ds->ds7.timers[2].event.callback = DSTimerUpdate2;
 78	ds->ds7.timers[2].event.context = &ds->ds7;
 79	ds->ds7.timers[2].event.priority = 0x22;
 80	ds->ds7.timers[3].event.name = "DS7 Timer 3";
 81	ds->ds7.timers[3].event.callback = DSTimerUpdate3;
 82	ds->ds7.timers[3].event.context = &ds->ds7;
 83	ds->ds7.timers[3].event.priority = 0x23;
 84	ds->ds7.timers[0].irq.name = "DS7 Timer 0 IRQ";
 85	ds->ds7.timers[0].irq.callback = DSTimerIrq0;
 86	ds->ds7.timers[0].irq.context = &ds->ds7;
 87	ds->ds7.timers[0].irq.priority = 0x28;
 88	ds->ds7.timers[1].irq.name = "DS7 Timer 1 IRQ";
 89	ds->ds7.timers[1].irq.callback = DSTimerIrq1;
 90	ds->ds7.timers[1].irq.context = &ds->ds7;
 91	ds->ds7.timers[1].irq.priority = 0x29;
 92	ds->ds7.timers[2].irq.name = "DS7 Timer 2 IRQ";
 93	ds->ds7.timers[2].irq.callback = DSTimerIrq2;
 94	ds->ds7.timers[2].irq.context = &ds->ds7;
 95	ds->ds7.timers[2].irq.priority = 0x2A;
 96	ds->ds7.timers[3].irq.name = "DS7 Timer 3 IRQ";
 97	ds->ds7.timers[3].irq.callback = DSTimerIrq3;
 98	ds->ds7.timers[3].irq.context = &ds->ds7;
 99	ds->ds7.timers[3].irq.priority = 0x2B;
100
101	memset(ds->ds9.timers, 0, sizeof(ds->ds9.timers));
102	ds->ds9.timers[0].event.name = "DS9 Timer 0";
103	ds->ds9.timers[0].event.callback = DSTimerUpdate0;
104	ds->ds9.timers[0].event.context = &ds->ds9;
105	ds->ds9.timers[0].event.priority = 0x20;
106	ds->ds9.timers[0].forcedPrescale = 1;
107	ds->ds9.timers[1].event.name = "DS9 Timer 1";
108	ds->ds9.timers[1].event.callback = DSTimerUpdate1;
109	ds->ds9.timers[1].event.context = &ds->ds9;
110	ds->ds9.timers[1].event.priority = 0x21;
111	ds->ds9.timers[1].forcedPrescale = 1;
112	ds->ds9.timers[2].event.name = "DS9 Timer 2";
113	ds->ds9.timers[2].event.callback = DSTimerUpdate2;
114	ds->ds9.timers[2].event.context = &ds->ds9;
115	ds->ds9.timers[2].event.priority = 0x22;
116	ds->ds9.timers[2].forcedPrescale = 1;
117	ds->ds9.timers[3].event.name = "DS9 Timer 3";
118	ds->ds9.timers[3].event.callback = DSTimerUpdate3;
119	ds->ds9.timers[3].event.context = &ds->ds9;
120	ds->ds9.timers[3].event.priority = 0x23;
121	ds->ds9.timers[3].forcedPrescale = 1;
122	ds->ds9.timers[0].irq.name = "DS9 Timer 0 IRQ";
123	ds->ds9.timers[0].irq.callback = DSTimerIrq0;
124	ds->ds9.timers[0].irq.context = &ds->ds9;
125	ds->ds9.timers[0].irq.priority = 0x28;
126	ds->ds9.timers[1].irq.name = "DS9 Timer 1 IRQ";
127	ds->ds9.timers[1].irq.callback = DSTimerIrq1;
128	ds->ds9.timers[1].irq.context = &ds->ds9;
129	ds->ds9.timers[1].irq.priority = 0x29;
130	ds->ds9.timers[2].irq.name = "DS9 Timer 2 IRQ";
131	ds->ds9.timers[2].irq.callback = DSTimerIrq2;
132	ds->ds9.timers[2].irq.context = &ds->ds9;
133	ds->ds9.timers[2].irq.priority = 0x2A;
134	ds->ds9.timers[3].irq.name = "DS9 Timer 3 IRQ";
135	ds->ds9.timers[3].irq.callback = DSTimerIrq3;
136	ds->ds9.timers[3].irq.context = &ds->ds9;
137	ds->ds9.timers[3].irq.priority = 0x2B;
138}
139
140void DSTimerWriteTMCNT_HI(struct GBATimer* timer, struct mTiming* timing, uint16_t* io, uint16_t value) {
141	GBATimerWriteTMCNT_HI(timer, timing, io, value);
142}