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, 10 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

# User Rev Content
1 cebix 1.1 /*
2     * C64_x.h - Put the pieces together, X specific stuff
3     *
4 cebix 1.2 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
5 cebix 1.1 *
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 cebix 1.5 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 cebix 1.1
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 cebix 1.3 gui = new CmdPipe("wish", BINDIR "Frodo_GUI.tcl");
118 cebix 1.1 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     }