ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/C64_x.h
Revision: 1.5
Committed: 2004-01-10T15:07:14Z (20 years, 3 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.4: +4 -85 lines
Log Message:
Unix joysticks use SDL

File Contents

# Content
1 /*
2 * C64_x.h - Put the pieces together, X specific stuff
3 *
4 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "main.h"
22
23
24 static struct timeval tv_start;
25
26 #ifndef HAVE_USLEEP
27 /*
28 * NAME:
29 * usleep -- This is the precision timer for Test Set
30 * Automation. It uses the select(2) system
31 * call to delay for the desired number of
32 * micro-seconds. This call returns ZERO
33 * (which is usually ignored) on successful
34 * completion, -1 otherwise.
35 *
36 * ALGORITHM:
37 * 1) We range check the passed in microseconds and log a
38 * warning message if appropriate. We then return without
39 * delay, flagging an error.
40 * 2) Load the Seconds and micro-seconds portion of the
41 * interval timer structure.
42 * 3) Call select(2) with no file descriptors set, just the
43 * timer, this results in either delaying the proper
44 * ammount of time or being interupted early by a signal.
45 *
46 * HISTORY:
47 * Added when the need for a subsecond timer was evident.
48 *
49 * AUTHOR:
50 * Michael J. Dyer Telephone: AT&T 414.647.4044
51 * General Electric Medical Systems GE DialComm 8 *767.4044
52 * P.O. Box 414 Mail Stop 12-27 Sect'y AT&T 414.647.4584
53 * Milwaukee, Wisconsin USA 53201 8 *767.4584
54 * internet: mike@sherlock.med.ge.com GEMS WIZARD e-mail: DYER
55 */
56
57 #include <unistd.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <errno.h>
61 #include <time.h>
62 #include <sys/time.h>
63 #include <sys/param.h>
64 #include <sys/types.h>
65
66 int usleep(unsigned long int microSeconds)
67 {
68 unsigned int Seconds, uSec;
69 int nfds, readfds, writefds, exceptfds;
70 struct timeval Timer;
71
72 nfds = readfds = writefds = exceptfds = 0;
73
74 if( (microSeconds == (unsigned long) 0)
75 || microSeconds > (unsigned long) 4000000 )
76 {
77 errno = ERANGE; /* value out of range */
78 perror( "usleep time out of range ( 0 -> 4000000 ) " );
79 return -1;
80 }
81
82 Seconds = microSeconds / (unsigned long) 1000000;
83 uSec = microSeconds % (unsigned long) 1000000;
84
85 Timer.tv_sec = Seconds;
86 Timer.tv_usec = uSec;
87
88 if( select( nfds, &readfds, &writefds, &exceptfds, &Timer ) < 0 )
89 {
90 perror( "usleep (select) failed" );
91 return -1;
92 }
93
94 return 0;
95 }
96 #endif
97
98
99 /*
100 * Constructor, system-dependent things
101 */
102
103 void C64::c64_ctor1(void)
104 {
105 // Initialize joystick variables
106 joy_minx[0] = joy_miny[0] = 32767;
107 joy_maxx[0] = joy_maxy[0] = -32768;
108 joy_minx[1] = joy_miny[1] = 32767;
109 joy_maxx[1] = joy_maxy[1] = -32768;
110
111 // we need to create a potential GUI subprocess here, because we don't want
112 // it to inherit file-descriptors (such as for the audio-device and alike..)
113 #if defined(__svgalib__)
114 gui = 0;
115 #else
116 // try to start up Tk gui.
117 gui = new CmdPipe("wish", BINDIR "Frodo_GUI.tcl");
118 if (gui) {
119 if (gui->fail) {
120 delete gui; gui = 0;
121 }
122 }
123 // wait until the GUI process responds (if it does...)
124 if (gui) {
125 if (5 != gui->ewrite("ping\n",5)) {
126 delete gui; gui = 0;
127 } else {
128 char c;
129 fd_set set;
130 FD_ZERO(&set);
131 FD_SET(gui->get_read_fd(), &set);
132 struct timeval tv;
133 tv.tv_usec = 0;
134 tv.tv_sec = 5;
135 // Use the following commented line for HP-UX < 10.20
136 // if (select(FD_SETSIZE, (int *)&set, (int *)NULL, (int *)NULL, &tv) <= 0) {
137 if (select(FD_SETSIZE, &set, NULL, NULL, &tv) <= 0) {
138 delete gui; gui = 0;
139 } else {
140 if (1 != gui->eread(&c, 1)) {
141 delete gui; gui = 0;
142 } else {
143 if (c != 'o') {
144 delete gui; gui = 0;
145 }
146 }
147 }
148 }
149 }
150 #endif // __svgalib__
151 }
152
153 void C64::c64_ctor2(void)
154 {
155 #ifndef __svgalib__
156 if (!gui) {
157 fprintf(stderr,"Alas, master, no preferences window will be available.\n"
158 "If you wish to see one, make sure the 'wish' interpreter\n"
159 "(Tk version >= 4.1) is installed in your path.\n"
160 "You can still use Frodo, though. Use F10 to quit, \n"
161 "F11 to cause an NMI and F12 to reset the C64.\n"
162 "You can change the preferences by editing ~/.frodorc\n");
163 }
164 #endif // SVGAlib
165
166 gettimeofday(&tv_start, NULL);
167 }
168
169
170 /*
171 * Destructor, system-dependent things
172 */
173
174 void C64::c64_dtor(void)
175 {
176 }
177
178
179 /*
180 * Start main emulation thread
181 */
182
183 void C64::Run(void)
184 {
185 // Reset chips
186 TheCPU->Reset();
187 TheSID->Reset();
188 TheCIA1->Reset();
189 TheCIA2->Reset();
190 TheCPU1541->Reset();
191
192 // Patch kernal IEC routines
193 orig_kernal_1d84 = Kernal[0x1d84];
194 orig_kernal_1d85 = Kernal[0x1d85];
195 PatchKernal(ThePrefs.FastReset, ThePrefs.Emul1541Proc);
196
197 quit_thyself = false;
198 thread_func();
199 }
200
201
202 /*
203 * Vertical blank: Poll keyboard and joysticks, update window
204 */
205
206 void C64::VBlank(bool draw_frame)
207 {
208 // Poll keyboard
209 TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey);
210 if (TheDisplay->quit_requested)
211 quit_thyself = true;
212
213 // Poll joysticks
214 TheCIA1->Joystick1 = poll_joystick(0);
215 TheCIA1->Joystick2 = poll_joystick(1);
216
217 if (ThePrefs.JoystickSwap) {
218 uint8 tmp = TheCIA1->Joystick1;
219 TheCIA1->Joystick1 = TheCIA1->Joystick2;
220 TheCIA1->Joystick2 = tmp;
221 }
222
223 // Joystick keyboard emulation
224 if (TheDisplay->NumLock())
225 TheCIA1->Joystick1 &= joykey;
226 else
227 TheCIA1->Joystick2 &= joykey;
228
229 // Count TOD clocks
230 TheCIA1->CountTOD();
231 TheCIA2->CountTOD();
232
233 // Update window if needed
234 if (draw_frame) {
235 TheDisplay->Update();
236
237 // Calculate time between VBlanks, display speedometer
238 struct timeval tv;
239 gettimeofday(&tv, NULL);
240 if ((tv.tv_usec -= tv_start.tv_usec) < 0) {
241 tv.tv_usec += 1000000;
242 tv.tv_sec -= 1;
243 }
244 tv.tv_sec -= tv_start.tv_sec;
245 double elapsed_time = (double)tv.tv_sec * 1000000 + tv.tv_usec;
246 speed_index = 20000 / (elapsed_time + 1) * ThePrefs.SkipFrames * 100;
247
248 // Limit speed to 100% if desired
249 if ((speed_index > 100) && ThePrefs.LimitSpeed) {
250 usleep((unsigned long)(ThePrefs.SkipFrames * 20000 - elapsed_time));
251 speed_index = 100;
252 }
253
254 gettimeofday(&tv_start, NULL);
255
256 TheDisplay->Speedometer((int)speed_index);
257 }
258 }
259
260
261 /*
262 * The emulation's main loop
263 */
264
265 void C64::thread_func(void)
266 {
267 int linecnt = 0;
268
269 #ifdef FRODO_SC
270 while (!quit_thyself) {
271
272 // The order of calls is important here
273 if (TheVIC->EmulateCycle())
274 TheSID->EmulateLine();
275 TheCIA1->CheckIRQs();
276 TheCIA2->CheckIRQs();
277 TheCIA1->EmulateCycle();
278 TheCIA2->EmulateCycle();
279 TheCPU->EmulateCycle();
280
281 if (ThePrefs.Emul1541Proc) {
282 TheCPU1541->CountVIATimers(1);
283 if (!TheCPU1541->Idle)
284 TheCPU1541->EmulateCycle();
285 }
286 CycleCounter++;
287 #else
288 while (!quit_thyself) {
289
290 // The order of calls is important here
291 int cycles = TheVIC->EmulateLine();
292 TheSID->EmulateLine();
293 #if !PRECISE_CIA_CYCLES
294 TheCIA1->EmulateLine(ThePrefs.CIACycles);
295 TheCIA2->EmulateLine(ThePrefs.CIACycles);
296 #endif
297
298 if (ThePrefs.Emul1541Proc) {
299 int cycles_1541 = ThePrefs.FloppyCycles;
300 TheCPU1541->CountVIATimers(cycles_1541);
301
302 if (!TheCPU1541->Idle) {
303 // 1541 processor active, alternately execute
304 // 6502 and 6510 instructions until both have
305 // used up their cycles
306 while (cycles >= 0 || cycles_1541 >= 0)
307 if (cycles > cycles_1541)
308 cycles -= TheCPU->EmulateLine(1);
309 else
310 cycles_1541 -= TheCPU1541->EmulateLine(1);
311 } else
312 TheCPU->EmulateLine(cycles);
313 } else
314 // 1541 processor disabled, only emulate 6510
315 TheCPU->EmulateLine(cycles);
316 #endif
317 linecnt++;
318 #if !defined(__svgalib__)
319 if ((linecnt & 0xfff) == 0 && gui) {
320
321 // check for command from GUI process
322 // fprintf(stderr,":");
323 while (gui->probe()) {
324 char c;
325 if (gui->eread(&c, 1) != 1) {
326 delete gui;
327 gui = 0;
328 fprintf(stderr,"Oops, GUI process died...\n");
329 } else {
330 // fprintf(stderr,"%c",c);
331 switch (c) {
332 case 'q':
333 quit_thyself = true;
334 break;
335 case 'r':
336 Reset();
337 break;
338 case 'p':{
339 Prefs *np = Frodo::reload_prefs();
340 NewPrefs(np);
341 ThePrefs = *np;
342 break;
343 }
344 default:
345 break;
346 }
347 }
348 }
349 }
350 #endif
351 }
352 #if !defined(__svgalib__)
353 if (gui) {
354 gui->ewrite("quit\n",5);
355 }
356 #endif
357 }