ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/C64_Acorn.h
Revision: 1.3
Committed: 2003-07-01T17:51:17Z (19 years, 7 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
updated copyright date

File Contents

# User Rev Content
1 cebix 1.1 /*
2 cebix 1.2 * C64_Acorn.h - Put the pieces together, RISC OS specific stuff
3 cebix 1.1 *
4 cebix 1.3 * 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 "Prefs.h"
22     #include "ROlib.h"
23     #include "AcornGUI.h"
24    
25    
26     void C64::LoadSystemConfig(const char *filename)
27     {
28     FILE *fp;
29    
30     if ((fp = fopen(filename, "r")) != NULL)
31     {
32     int i;
33     Joy_Keys *jk;
34     int args[10];
35     char line[256];
36    
37     while (fgets(line, 255, fp) != 0)
38     {
39     char *b = line;
40     register char c;
41    
42     do {c = *b++;} while (c > 32);
43     if (c == 32) // keyword mustn't contain spaces
44     {
45     *(b-1) = '\0';
46     do {c = *b++;} while ((c >= 32) && (c != '='));
47     if (c == '=') // read in keyword's arguments
48     {
49     int i=0;
50    
51     while ((*b != '\0') && (i < 10))
52     {
53     args[i++] = strtol(b, &b, 10);
54     }
55     if (strcmp(line, "PollAfter") == 0) {PollAfter = args[0];}
56     else if (strcmp(line, "SpeedAfter") == 0) {SpeedAfter = args[0];}
57     else if (strcmp(line, "PollSoundAfter") == 0) {PollSoundAfter = args[0];}
58     else if (strcmp(line, "JoystickKeys1") == 0)
59     {
60     jk = &(TheDisplay->JoystickKeys[0]);
61     jk->up = args[0]; jk->down = args[1]; jk->left = args[2]; jk->right = args[3];
62     jk->fire = args[4];
63     }
64     else if (strcmp(line, "JoystickKeys2") == 0)
65     {
66     jk = &(TheDisplay->JoystickKeys[1]);
67     jk->up = args[0]; jk->down = args[1]; jk->left = args[2]; jk->right = args[3];
68     jk->fire = args[4];
69     }
70     else
71     {
72     _kernel_oserror err;
73    
74     err.errnum = 0;
75     sprintf(err.errmess,"Bad keyword <%s> in system configure file!",line);
76     Wimp_ReportError(&err,1,TASKNAME);
77     }
78     }
79     }
80     }
81     fclose(fp);
82     }
83     }
84    
85    
86     void C64::SaveSystemConfig(const char *filename)
87     {
88     FILE *fp;
89    
90     if ((fp = fopen(filename, "w")) != NULL)
91     {
92     int i;
93     Joy_Keys *jk;
94    
95     fprintf(fp,"PollAfter = %d\n", PollAfter);
96     fprintf(fp,"SpeedAfter = %d\n", SpeedAfter);
97     fprintf(fp,"PollSoundAfter = %d\n", PollSoundAfter);
98     for (i=0; i<2; i++)
99     {
100     jk = &(TheDisplay->JoystickKeys[i]);
101     fprintf(fp,"JoystickKeys%d",i+1);
102     fprintf(fp," = %d %d %d %d %d\n", jk->up, jk->down, jk->left, jk->right, jk->fire);
103     }
104     fclose(fp);
105     }
106     }
107    
108    
109     void C64::ReadTimings(int *poll_after, int *speed_after, int *sound_after)
110     {
111     *poll_after = PollAfter; *speed_after = SpeedAfter; *sound_after = PollSoundAfter;
112     }
113    
114    
115     void C64::WriteTimings(int poll_after, int speed_after, int sound_after)
116     {
117     PollAfter = poll_after; SpeedAfter = speed_after; PollSoundAfter = sound_after;
118     }
119    
120    
121     void C64::RequestSnapshot(void)
122     {
123     // Snapshots are only possible if the emulation progresses to the next vsync
124     if (have_a_break) Resume();
125     make_a_snapshot = true;
126     }
127    
128    
129     void C64::c64_ctor1(void)
130     {
131     TheWIMP = new WIMP(this);
132     PollAfter = 20; // poll every 20 centiseconds
133     SpeedAfter = 200; // update speedometer every 2 seconds
134     PollSoundAfter = 50; // poll DigitalRenderer every 50 lines
135     HostVolume = Sound_Volume(0);
136     // Just a precaution
137     if (HostVolume < 0) {HostVolume = 0;}
138     if (HostVolume > MaximumVolume) {HostVolume = MaximumVolume;}
139     Poll = false;
140     make_a_snapshot = false;
141     }
142    
143    
144     void C64::c64_ctor2(void)
145     {
146     LoadSystemConfig(DEFAULT_SYSCONF);
147     // was started from multitasking so pretend ScrollLock OFF no matter what
148     laststate = (ReadKeyboardStatus() & ~2); SingleTasking = false;
149     lastptr = 1;
150     }
151    
152    
153     void C64::c64_dtor(void)
154     {
155     delete TheWIMP;
156     }
157    
158    
159     void C64::open_close_joysticks(bool oldjoy1, bool oldjoy2, bool newjoy1, bool newjoy2)
160     {
161     // Check if the Joystick module is loaded. If not then write an illegal value to
162     // the joystick state.
163     if (Joystick_Read(0) == -2) {joystate[0] = 0;} else {joystate[0] = 0xff;}
164     if (Joystick_Read(1) == -2) {joystate[1] = 0;} else {joystate[1] = 0xff;}
165     }
166    
167    
168     uint8 C64::poll_joystick(int port)
169     {
170     register int state;
171     uint8 joy;
172    
173     if ((state = Joystick_Read(port)) != -2) // module present
174     {
175     if (state == -1) {joy = joystate[port];} // use old value
176     else
177     {
178     joy = 0xff;
179     if ((state & (JoyButton1 + JoyButton2)) != 0) {joy &= 0xef;} // fire
180     if ((state & 0x80) == 0) // positive direction #1
181     {
182     if ((state & 0xff) >= JoyDir_Thresh) {joy &= 0xfe;} // up
183     }
184     else
185     {
186     if ((256 - (state & 0xff)) >= JoyDir_Thresh) {joy &= 0xfd;} // down
187     }
188     if ((state & 0x8000) == 0) // positive direction #2
189     {
190     if ((state & 0xff00) >= JoyDir_Thresh<<8) {joy &= 0xf7;} // right
191     }
192     else
193     {
194     if ((0x10000 - (state & 0xff00)) >= JoyDir_Thresh<<8) {joy &= 0xfb;} // left
195     }
196     }
197     joystate[port] = joy; return(joy);
198     }
199     else
200     {
201     joystate[port] = 0; return(0xff);
202     }
203     }
204    
205    
206     void C64::VBlank(bool draw_frame)
207     {
208     int Now, KeyState;
209     bool InputFocus;
210    
211     // Poll keyboard if the window has the input focus.
212     InputFocus = TheWIMP->EmuWindow->HaveInput();
213     if (InputFocus)
214     {
215     TheDisplay->PollKeyboard(TheCIA1->KeyMatrix, TheCIA1->RevMatrix, &joykey, &joykey2);
216     }
217    
218     // Poll Joysticks
219     TheCIA1->Joystick1 = (ThePrefs.Joystick1On) ? poll_joystick(0) : 0xff;
220     TheCIA1->Joystick2 = (ThePrefs.Joystick2On) ? poll_joystick(1) : 0xff;
221    
222     // Swap joysticks?
223     if (ThePrefs.JoystickSwap)
224     {
225     register uint8 h;
226    
227     h = TheCIA1->Joystick1; TheCIA1->Joystick1 = TheCIA1->Joystick2; TheCIA1->Joystick2 = h;
228     }
229    
230     // Read keyboard state directly since we'll also need ScrollLock later!
231     KeyState = ReadKeyboardStatus();
232     if (InputFocus)
233     {
234     // Keyboard emulates which joystick? (NumLock ==> Port 2, else Port 1)
235     if ((KeyState & 4) == 0)
236     {
237     TheCIA1->Joystick2 &= joykey;
238     }
239     else // joykey2 only mapped if numLOCK is off.
240     {
241     TheCIA1->Joystick1 &= joykey; TheCIA1->Joystick2 &= joykey2;
242     }
243     }
244    
245     if (draw_frame)
246     {
247     TheDisplay->Update();
248     }
249    
250     // Make snapshot?
251     if (make_a_snapshot)
252     {
253     SaveSnapshot((TheWIMP->SnapFile)+44);
254     make_a_snapshot = false;
255     }
256    
257     Now = OS_ReadMonotonicTime();
258    
259     // Limit speed? (hahaha.... ah well...)
260     if (ThePrefs.LimitSpeed)
261     {
262     int Now;
263    
264     while ((Now - LastFrame) < 2) // 2cs per frame = 50fps (original speed)
265     {
266     Now = OS_ReadMonotonicTime();
267     }
268     LastFrame = Now;
269     }
270     FramesSince++;
271    
272     // Update speedometer (update, not force redraw!)?
273     if ((Now - LastSpeed) >= SpeedAfter)
274     {
275     char b[16];
276    
277     if ((Now - LastSpeed) <= 0) {Now = LastSpeed+1;}
278     // Speed: 100% equals 50fps (round result)
279     sprintf(b,"%d%%\0",((400*FramesSince)/(Now - LastSpeed) + 1) >> 1);
280     TheWIMP->EmuPane->WriteIconTextU(Icon_Pane_Speed,b);
281     LastSpeed = Now; FramesSince = 0;
282     }
283    
284     if (InputFocus)
285     {
286     // Scroll lock state changed?
287     if (((KeyState ^ laststate) & 2) != 0)
288     {
289     // change to single tasking: turn off mouse, else restore previous pointer
290     if ((KeyState & 2) != 0) {lastptr = SetMousePointer(0); SingleTasking = true;}
291     else {SetMousePointer(lastptr); OS_FlushBuffer(9); SingleTasking = false;}
292     }
293     if ((KeyState & 2) != 0) {lastptr = SetMousePointer(0);}
294     else {SetMousePointer(lastptr); OS_FlushBuffer(9);}
295     }
296    
297     // Poll? ScrollLock forces single tasking, i.e. overrides timings.
298     if (!SingleTasking)
299     {
300     if ((Now - LastPoll) >= PollAfter)
301     {
302     Poll = true;
303     }
304     }
305     laststate = KeyState;
306     }
307    
308    
309     void C64::Run(void)
310     {
311     // Resetting chips
312     TheCPU->Reset();
313     TheSID->Reset();
314     TheCIA1->Reset();
315     TheCIA2->Reset();
316     TheCPU1541->Reset();
317    
318     // Patch kernel IEC routines (copied from C64_Amiga.i
319     orig_kernal_1d84 = Kernal[0x1d84];
320     orig_kernal_1d85 = Kernal[0x1d85];
321     PatchKernal(ThePrefs.FastReset, ThePrefs.Emul1541Proc);
322    
323     // Start the emulation
324     thread_running = true; quit_thyself = false; have_a_break = false;
325     thread_func();
326     }
327    
328    
329     void C64::Quit(void)
330     {
331     if (thread_running)
332     {
333     quit_thyself = true; thread_running = false;
334     }
335     }
336    
337    
338     void C64::Pause(void)
339     {
340     have_a_break = true; TheSID->PauseSound();
341     }
342    
343    
344     void C64::Resume(void)
345     {
346     have_a_break = false; TheSID->ResumeSound();
347     }
348    
349    
350     void C64::thread_func(void)
351     {
352     LastPoll = LastFrame = LastSpeed = OS_ReadMonotonicTime(); FramesSince = 0;
353    
354     while (!quit_thyself)
355     {
356     #ifdef FRODO_SC
357     if (TheVIC->EmulateCycle()) {TheSID->EmulateLine();}
358     TheCIA1->EmulateCycle();
359     TheCIA2->EmulateCycle();
360     TheCPU->EmulateCycle();
361    
362     if (ThePrefs.Emul1541Proc)
363     {
364     TheCPU1541->CountVIATimers(1);
365     if (!TheCPU1541->Idle) {TheCPU1541->EmulateCycle();}
366     }
367     CycleCounter++;
368    
369     #else
370     // Emulate each device one rasterline. Order is important!
371     int cycles = TheVIC->EmulateLine();
372     TheSID->EmulateLine();
373     #if !PRECISE_CIA_CYCLES
374     TheCIA1->EmulateLine(ThePrefs.CIACycles);
375     TheCIA2->EmulateLine(ThePrefs.CIACycles);
376     #endif
377    
378     if (ThePrefs.Emul1541Proc)
379     {
380     int cycles_1541 = ThePrefs.FloppyCycles;
381     TheCPU1541->CountVIATimers(cycles_1541);
382     if (!TheCPU1541->Idle)
383     {
384     while ((cycles >= 0) || (cycles_1541 >= 0))
385     {
386     if (cycles > cycles_1541) {cycles -= TheCPU->EmulateLine(1);}
387     else {cycles_1541 -= TheCPU1541->EmulateLine(1);}
388     }
389     }
390     else {TheCPU->EmulateLine(cycles);}
391     }
392     else
393     {
394     TheCPU->EmulateLine(cycles);
395     }
396     #endif
397    
398     // Single-tasking: busy-wait 'til unpause
399     while (SingleTasking && have_a_break)
400     {
401     int KeyState;
402    
403     TheDisplay->CheckForUnpause(true); // unpause?
404     KeyState = ReadKeyboardStatus();
405     if ((KeyState & 2) == 0) // leave single tasking?
406     {
407     SetMousePointer(lastptr); OS_FlushBuffer(9); SingleTasking = false;
408     }
409     laststate = KeyState;
410     }
411     if (!SingleTasking)
412     {
413     // The system-specific part of this function
414     if (Poll || have_a_break)
415     {
416     TheWIMP->Poll(have_a_break);
417     LastPoll = LastFrame = OS_ReadMonotonicTime(); Poll = false;
418     }
419     }
420     }
421     }