ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/C64_Acorn.h
Revision: 1.6
Committed: 2005-06-27T19:55:48Z (17 years, 5 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: VERSION_4_2, HEAD
Changes since 1.5: +1 -1 lines
Log Message:
updated copyright dates

File Contents

# Content
1 /*
2 * C64_Acorn.h - Put the pieces together, RISC OS specific stuff
3 *
4 * Frodo (C) 1994-1997,2002-2005 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 "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(int oldjoy1, int oldjoy2, int newjoy1, int 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 }