1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_TIMER_MINT
25
26/*
27 *	TOS/MiNT timer driver
28 *	based on vbl vector
29 *
30 *	Patrice Mandin
31 */
32
33#include <stdio.h>
34#include <sys/time.h>
35#include <signal.h>
36#include <unistd.h>
37#include <string.h>
38#include <errno.h>
39
40#include <mint/cookie.h>
41#include <mint/sysvars.h>
42#include <mint/osbind.h>
43#include <mint/mintbind.h>
44
45#include "SDL_timer.h"
46#include "../SDL_timer_c.h"
47#include "SDL_thread.h"
48
49#include "../../video/ataricommon/SDL_atarisuper.h"
50
51#include "SDL_vbltimer_s.h"
52
53/* from audio/mint */
54void SDL_MintAudio_CheckFpu(void);
55
56/* The first ticks value of the application */
57static Uint32 start;
58static SDL_bool read_hz200_from_vbl = SDL_FALSE;
59static int mint_present; /* can we use Syield() ? */
60
61void SDL_StartTicks(void)
62{
63	void *old_stack;
64	long dummy;
65
66	/* Set first ticks value */
67	old_stack = (void *)Super(0);
68	start = *((volatile long *)_hz_200);
69	SuperToUser(old_stack);
70
71	start *= 5;	/* One _hz_200 tic is 5ms */
72
73	mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
74}
75
76Uint32 SDL_GetTicks (void)
77{
78	Uint32 now = start;
79
80	if (read_hz200_from_vbl) {
81		now = SDL_Atari_hz200;
82	} else {
83		void *old_stack = (void *)Super(0);
84		now = *((volatile long *)_hz_200);
85		SuperToUser(old_stack);
86	}
87
88	return((now*5)-start);
89}
90
91void SDL_Delay (Uint32 ms)
92{
93	Uint32 now;
94
95	now = SDL_GetTicks();
96	while ((SDL_GetTicks()-now)<ms){
97		if (mint_present) {
98			Syield();
99		}
100	}
101}
102
103/* Data to handle a single periodic alarm */
104static SDL_bool timer_installed=SDL_FALSE;
105
106/* This is only called if the event thread is not running */
107int SDL_SYS_TimerInit(void)
108{
109	void *old_stack;
110
111	SDL_MintAudio_CheckFpu();
112
113	/* Install RunTimer in vbl vector */
114	old_stack = (void *)Super(0);
115	timer_installed = !SDL_AtariVblInstall(SDL_ThreadedTimerCheck);
116	SuperToUser(old_stack);
117
118	if (!timer_installed) {
119		return(-1);
120	}
121
122	read_hz200_from_vbl = SDL_TRUE;
123	return(SDL_SetTimerThreaded(0));
124}
125
126void SDL_SYS_TimerQuit(void)
127{
128	/* Uninstall RunTimer vbl vector */
129	if (timer_installed) {
130		void *old_stack = (void *)Super(0);
131		SDL_AtariVblUninstall(SDL_ThreadedTimerCheck);
132		SuperToUser(old_stack);
133		timer_installed = SDL_FALSE;
134	}
135	read_hz200_from_vbl = SDL_FALSE;
136}
137
138int SDL_SYS_StartTimer(void)
139{
140	SDL_SetError("Internal logic error: MiNT uses vbl timer");
141	return(-1);
142}
143
144void SDL_SYS_StopTimer(void)
145{
146	return;
147}
148
149#endif /* SDL_TIMER_MINT */
150