1 /*
2 * pet.c
3 *
4 * Written by
5 * Ettore Perazzoli <ettore@comm2000.it>
6 * Andre Fachat <fachat@physik.tu-chemnitz.de>
7 * Andreas Boose <viceteam@t-online.de>
8 * Marco van den Heuvel <blackystardust68@yahoo.com>
9 *
10 * This file is part of VICE, the Versatile Commodore Emulator.
11 * See README for copyright notice.
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 * 02111-1307 USA.
27 *
28 */
29
30 #include "vice.h"
31
32 #include <math.h> /* modf */
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "attach.h"
37 #include "autostart.h"
38 #include "bbrtc.h"
39 #include "cartio.h"
40 #include "clkguard.h"
41 #include "crtc-mem.h"
42 #include "crtc.h"
43 #include "datasette.h"
44 #include "datasette-sound.h"
45 #include "debug.h"
46 #include "debugcart.h"
47 #include "diskimage.h"
48 #include "drive-cmdline-options.h"
49 #include "drive-resources.h"
50 #include "drive-snapshot.h"
51 #include "drive-sound.h"
52 #include "drive.h"
53 #include "fliplist.h"
54 #include "fsdevice.h"
55 #include "gfxoutput.h"
56 #include "iecdrive.h"
57 #include "init.h"
58 #include "joyport.h"
59 #include "joystick.h"
60 #include "kbdbuf.h"
61 #include "keyboard.h"
62 #include "log.h"
63 #include "machine-drive.h"
64 #include "machine-printer.h"
65 #include "machine-video.h"
66 #include "machine.h"
67 #include "maincpu.h"
68 #include "mem.h"
69 #include "monitor.h"
70 #include "network.h"
71 #include "paperclip64.h"
72 #include "parallel.h"
73 #include "pet-cmdline-options.h"
74 #include "pet-resources.h"
75 #include "pet-snapshot.h"
76 #include "pet.h"
77 #include "petcolour.h"
78 #include "petiec.h"
79 #include "petmem.h"
80 #include "petreu.h"
81 #include "petdww.h"
82 #include "pethre.h"
83 #include "pets.h"
84 #include "petsound.h"
85 #include "petui.h"
86 #include "petvia.h"
87 #include "petacia.h"
88 #include "petpia.h"
89 #include "printer.h"
90 #include "resources.h"
91 #include "rs232drv.h"
92 #include "sampler.h"
93 #include "sampler2bit.h"
94 #include "sampler4bit.h"
95 #include "screenshot.h"
96 #include "sid.h"
97 #include "sid-cmdline-options.h"
98 #include "sid-resources.h"
99 #include "sidcart.h"
100 #include "sound.h"
101 #include "tape.h"
102 #include "tapeport.h"
103 #include "traps.h"
104 #include "types.h"
105 #include "userport.h"
106 #include "userport_dac.h"
107 #include "userport_joystick.h"
108 #include "userport_rtc_58321a.h"
109 #include "userport_rtc_ds1307.h"
110 #include "util.h"
111 #include "via.h"
112 #include "vice-event.h"
113 #include "video.h"
114 #include "video-sound.h"
115 #include "vsync.h"
116
117 #ifdef HAVE_MOUSE
118 #include "mouse.h"
119 #endif
120
121 machine_context_t machine_context;
122
123 const char machine_name[] = "PET";
124 int machine_class = VICE_MACHINE_PET;
125
126 static void machine_vsync_hook(void);
127
128 /*
129 static long pet_cycles_per_rfsh = PET_PAL_CYCLES_PER_RFSH;
130 static double pet_rfsh_per_sec = PET_PAL_RFSH_PER_SEC;
131 */
132
133 static log_t pet_log = LOG_ERR;
134 static machine_timing_t machine_timing;
135
machine_get_keyboard_type(void)136 int machine_get_keyboard_type(void)
137 {
138 int type;
139 if (resources_get_int("KeyboardType", &type) < 0) {
140 return 0;
141 }
142 return type;
143 }
144
machine_get_keyboard_type_name(int type)145 char *machine_get_keyboard_type_name(int type)
146 {
147 static char names[KBD_TYPE_NUM][5] = {
148 KBD_TYPE_STR_BUSINESS_UK,
149 KBD_TYPE_STR_BUSINESS_US,
150 KBD_TYPE_STR_BUSINESS_DE,
151 KBD_TYPE_STR_BUSINESS_JP,
152 KBD_TYPE_STR_GRAPHICS_US
153 };
154 return names[type]; /* return 0 if no different types exist */
155 }
156
157 /* return number of available keyboard types for this machine */
machine_get_num_keyboard_types(void)158 int machine_get_num_keyboard_types(void)
159 {
160 return KBD_TYPE_NUM;
161 }
162
163 /* FIXME: adjust this to reality :) */
164 static kbdtype_info_t kbdinfo[KBD_TYPE_NUM + 1] = {
165 { "Business (uk)", KBD_TYPE_BUSINESS_UK, 0 },
166 { "Business (us)", KBD_TYPE_BUSINESS_US, 0 },
167 { "Business (de)", KBD_TYPE_BUSINESS_DE, 0 },
168 { "Business (jp)", KBD_TYPE_BUSINESS_JP, 0 },
169 { "Graphics (us)", KBD_TYPE_GRAPHICS_US, 0 },
170 { NULL, 0, 0 }
171 };
172
machine_get_keyboard_info_list(void)173 kbdtype_info_t *machine_get_keyboard_info_list(void)
174 {
175 return kbdinfo;
176 }
177
178 /* ------------------------------------------------------------------------ */
179
180 static joyport_port_props_t userport_joy_control_port_1 =
181 {
182 "Userport joystick adapter port 1",
183 0, /* NO potentiometer connected to this port */
184 0, /* has NO lightpen support on this port */
185 0 /* port can be switched on/off */
186 };
187
188 static joyport_port_props_t userport_joy_control_port_2 =
189 {
190 "Userport joystick adapter port 2",
191 0, /* has NO potentiometer connected to this port */
192 0, /* has NO lightpen support on this port */
193 0 /* port can be switched on/off */
194 };
195
init_joyport_ports(void)196 static int init_joyport_ports(void)
197 {
198 if (joyport_port_register(JOYPORT_3, &userport_joy_control_port_1) < 0) {
199 return -1;
200 }
201 return joyport_port_register(JOYPORT_4, &userport_joy_control_port_2);
202 }
203
204 /* PET-specific resource initialization. This is called before initializing
205 the machine itself with `machine_init()'. */
machine_resources_init(void)206 int machine_resources_init(void)
207 {
208 if (traps_resources_init() < 0) {
209 init_resource_fail("traps");
210 return -1;
211 }
212 if (pet_resources_init() < 0) {
213 init_resource_fail("pet");
214 return -1;
215 }
216 if (cartio_resources_init() < 0) {
217 init_resource_fail("cartio");
218 return -1;
219 }
220 if (petreu_resources_init() < 0) {
221 init_resource_fail("petreu");
222 return -1;
223 }
224 if (pia1_resources_init() < 0) {
225 init_resource_fail("pia1");
226 return -1;
227 }
228 if (crtc_resources_init() < 0) {
229 init_resource_fail("crtc");
230 return -1;
231 }
232 if (petdww_resources_init() < 0) {
233 init_resource_fail("petdww");
234 return -1;
235 }
236 if (pethre_resources_init() < 0) {
237 init_resource_fail("pethre");
238 return -1;
239 }
240 if (sidcart_resources_init() < 0) {
241 init_resource_fail("sidcart");
242 return -1;
243 }
244 /*
245 * This needs to be called before tapeport_resources_init(), otherwise
246 * the tapecart will fail to initialize due to the Datasette resource
247 * appearing after the Tapecart resources
248 */
249 if (drive_resources_init() < 0) {
250 init_resource_fail("drive");
251 return -1;
252 }
253 if (datasette_resources_init() < 0) {
254 init_resource_fail("datasette");
255 return -1;
256 }
257 if (tapeport_resources_init() < 0) {
258 init_resource_fail("tapeport");
259 return -1;
260 }
261 if (acia1_resources_init() < 0) {
262 init_resource_fail("acia1");
263 return -1;
264 }
265 if (rs232drv_resources_init() < 0) {
266 init_resource_fail("rs232drv");
267 return -1;
268 }
269 if (printer_resources_init() < 0) {
270 init_resource_fail("printer");
271 return -1;
272 }
273 if (printer_userport_resources_init() < 0) {
274 init_resource_fail("userport printer");
275 return -1;
276 }
277 if (init_joyport_ports() < 0) {
278 init_resource_fail("joyport ports");
279 return -1;
280 }
281 if (joyport_resources_init() < 0) {
282 init_resource_fail("joyport devices");
283 return -1;
284 }
285 if (joyport_sampler2bit_resources_init() < 0) {
286 init_resource_fail("joyport 2bit sampler");
287 return -1;
288 }
289 if (joyport_sampler4bit_resources_init() < 0) {
290 init_resource_fail("joyport 4bit sampler");
291 return -1;
292 }
293 if (joyport_bbrtc_resources_init() < 0) {
294 init_resource_fail("joyport bbrtc");
295 return -1;
296 }
297 if (joyport_paperclip64_resources_init() < 0) {
298 init_resource_fail("joyport paperclip64 dongle");
299 return -1;
300 }
301 if (joystick_resources_init() < 0) {
302 init_resource_fail("joystick");
303 return -1;
304 }
305 if (userport_resources_init() < 0) {
306 init_resource_fail("userport devices");
307 return -1;
308 }
309 if (gfxoutput_resources_init() < 0) {
310 init_resource_fail("gfxoutput");
311 return -1;
312 }
313 if (sampler_resources_init() < 0) {
314 init_resource_fail("samplerdrv");
315 return -1;
316 }
317 if (fliplist_resources_init() < 0) {
318 init_resource_fail("flip list");
319 return -1;
320 }
321 if (file_system_resources_init() < 0) {
322 init_resource_fail("file system");
323 return -1;
324 }
325 /* Initialize file system device-specific resources. */
326 if (fsdevice_resources_init() < 0) {
327 init_resource_fail("file system device");
328 return -1;
329 }
330 if (disk_image_resources_init() < 0) {
331 init_resource_fail("disk image");
332 return -1;
333 }
334 if (event_resources_init() < 0) {
335 init_resource_fail("event");
336 return -1;
337 }
338 if (kbdbuf_resources_init() < 0) {
339 init_resource_fail("Keyboard");
340 return -1;
341 }
342 if (autostart_resources_init() < 0) {
343 init_resource_fail("autostart");
344 return -1;
345 }
346 #ifdef HAVE_NETWORK
347 if (network_resources_init() < 0) {
348 init_resource_fail("network");
349 return -1;
350 }
351 #endif
352 #ifdef DEBUG
353 if (debug_resources_init() < 0) {
354 init_resource_fail("debug");
355 return -1;
356 }
357 #endif
358 #ifdef HAVE_MOUSE
359 if (mouse_resources_init() < 0) {
360 init_resource_fail("mouse");
361 return -1;
362 }
363 #endif
364 if (userport_joystick_resources_init() < 0) {
365 init_resource_fail("userport joystick");
366 return -1;
367 }
368 if (userport_dac_resources_init() < 0) {
369 init_resource_fail("userport dac");
370 return -1;
371 }
372 if (userport_rtc_58321a_resources_init() < 0) {
373 init_resource_fail("userport rtc (58321a)");
374 return -1;
375 }
376 if (userport_rtc_ds1307_resources_init() < 0) {
377 init_resource_fail("userport rtc (ds1307)");
378 return -1;
379 }
380 if (debugcart_resources_init() < 0) {
381 init_resource_fail("debug cart");
382 return -1;
383 }
384 return 0;
385 }
386
machine_resources_shutdown(void)387 void machine_resources_shutdown(void)
388 {
389 petdww_resources_shutdown();
390 pethre_resources_shutdown();
391 pet_resources_shutdown();
392 petreu_resources_shutdown();
393 rs232drv_resources_shutdown();
394 printer_resources_shutdown();
395 drive_resources_shutdown();
396 fsdevice_resources_shutdown();
397 disk_image_resources_shutdown();
398 sampler_resources_shutdown();
399 cartio_shutdown();
400 userport_rtc_58321a_resources_shutdown();
401 userport_rtc_ds1307_resources_shutdown();
402 userport_resources_shutdown();
403 joyport_bbrtc_resources_shutdown();
404 tapeport_resources_shutdown();
405 debugcart_resources_shutdown();
406 }
407
408 /* PET-specific command-line option initialization. */
machine_cmdline_options_init(void)409 int machine_cmdline_options_init(void)
410 {
411 if (traps_cmdline_options_init() < 0) {
412 init_cmdline_options_fail("traps");
413 return -1;
414 }
415 if (pet_cmdline_options_init() < 0) {
416 init_cmdline_options_fail("pet");
417 return -1;
418 }
419 if (cartio_cmdline_options_init() < 0) {
420 init_cmdline_options_fail("cartio");
421 return -1;
422 }
423 if (petreu_cmdline_options_init() < 0) {
424 init_cmdline_options_fail("petreu");
425 return -1;
426 }
427 if (crtc_cmdline_options_init() < 0) {
428 init_cmdline_options_fail("crtc");
429 return -1;
430 }
431 if (petdww_cmdline_options_init() < 0) {
432 init_cmdline_options_fail("petdww");
433 return -1;
434 }
435 if (pethre_cmdline_options_init() < 0) {
436 init_cmdline_options_fail("pethre");
437 return -1;
438 }
439 if (pia1_cmdline_options_init() < 0) {
440 init_cmdline_options_fail("pia1");
441 return -1;
442 }
443 if (sidcart_cmdline_options_init() < 0) {
444 init_cmdline_options_fail("sidcart");
445 return -1;
446 }
447 if (drive_cmdline_options_init() < 0) {
448 init_cmdline_options_fail("drive");
449 return -1;
450 }
451 if (tapeport_cmdline_options_init() < 0) {
452 init_cmdline_options_fail("tapeport");
453 return -1;
454 }
455 if (datasette_cmdline_options_init() < 0) {
456 init_cmdline_options_fail("datasette");
457 return -1;
458 }
459 if (acia1_cmdline_options_init() < 0) {
460 init_cmdline_options_fail("acia1");
461 return -1;
462 }
463 if (rs232drv_cmdline_options_init() < 0) {
464 init_cmdline_options_fail("rs232drv");
465 return -1;
466 }
467 if (printer_cmdline_options_init() < 0) {
468 init_cmdline_options_fail("printer");
469 return -1;
470 }
471 if (printer_userport_cmdline_options_init() < 0) {
472 init_cmdline_options_fail("userport printer");
473 return -1;
474 }
475 if (joyport_cmdline_options_init() < 0) {
476 init_cmdline_options_fail("joyport");
477 return -1;
478 }
479 if (joyport_bbrtc_cmdline_options_init() < 0) {
480 init_cmdline_options_fail("bbrtc");
481 return -1;
482 }
483 if (joystick_cmdline_options_init() < 0) {
484 init_cmdline_options_fail("joystick");
485 return -1;
486 }
487 if (userport_cmdline_options_init() < 0) {
488 init_cmdline_options_fail("userport");
489 return -1;
490 }
491 if (gfxoutput_cmdline_options_init() < 0) {
492 init_cmdline_options_fail("gfxoutput");
493 return -1;
494 }
495 if (sampler_cmdline_options_init() < 0) {
496 init_cmdline_options_fail("samplerdrv");
497 return -1;
498 }
499 if (fliplist_cmdline_options_init() < 0) {
500 init_cmdline_options_fail("flip list");
501 return -1;
502 }
503 if (file_system_cmdline_options_init() < 0) {
504 init_cmdline_options_fail("attach");
505 return -1;
506 }
507 if (fsdevice_cmdline_options_init() < 0) {
508 init_cmdline_options_fail("file system");
509 return -1;
510 }
511 if (disk_image_cmdline_options_init() < 0) {
512 init_cmdline_options_fail("disk image");
513 return -1;
514 }
515 if (event_cmdline_options_init() < 0) {
516 init_cmdline_options_fail("event");
517 return -1;
518 }
519 if (kbdbuf_cmdline_options_init() < 0) {
520 init_cmdline_options_fail("keyboard");
521 return -1;
522 }
523 if (autostart_cmdline_options_init() < 0) {
524 init_cmdline_options_fail("autostart");
525 return -1;
526 }
527 #ifdef HAVE_NETWORK
528 if (network_cmdline_options_init() < 0) {
529 init_cmdline_options_fail("network");
530 return -1;
531 }
532 #endif
533 #ifdef DEBUG
534 if (debug_cmdline_options_init() < 0) {
535 init_cmdline_options_fail("debug");
536 return -1;
537 }
538 #endif
539 #ifdef HAVE_MOUSE
540 if (mouse_cmdline_options_init() < 0) {
541 init_cmdline_options_fail("mouse");
542 return -1;
543 }
544 #endif
545 if (userport_joystick_cmdline_options_init() < 0) {
546 init_cmdline_options_fail("userport joystick");
547 return -1;
548 }
549 if (userport_dac_cmdline_options_init() < 0) {
550 init_cmdline_options_fail("userport dac");
551 return -1;
552 }
553 if (userport_rtc_58321a_cmdline_options_init() < 0) {
554 init_cmdline_options_fail("userport rtc (58321a)");
555 return -1;
556 }
557 if (userport_rtc_ds1307_cmdline_options_init() < 0) {
558 init_cmdline_options_fail("userport rtc (ds1307)");
559 return -1;
560 }
561 if (debugcart_cmdline_options_init() < 0) {
562 init_cmdline_options_fail("debug cart");
563 return -1;
564 }
565 return 0;
566 }
567
568 /* ------------------------------------------------------------------------- */
569
570 #define SIGNAL_VERT_BLANK_OFF pia1_signal(PIA_SIG_CB1, PIA_SIG_RISE);
571
572 #define SIGNAL_VERT_BLANK_ON pia1_signal(PIA_SIG_CB1, PIA_SIG_FALL);
573
pet_crtc_signal(unsigned int signal)574 static void pet_crtc_signal(unsigned int signal)
575 {
576 if (signal) {
577 SIGNAL_VERT_BLANK_ON
578 } else {
579 SIGNAL_VERT_BLANK_OFF
580 }
581 }
582
583 /* ------------------------------------------------------------------------- */
584
machine_handle_pending_alarms(int num_write_cycles)585 void machine_handle_pending_alarms(int num_write_cycles)
586 {
587 }
588
pet_monitor_init(void)589 static void pet_monitor_init(void)
590 {
591 unsigned int dnr;
592 monitor_cpu_type_t asm6502;
593 monitor_cpu_type_t asm6809;
594 monitor_interface_t *drive_interface_init[NUM_DISK_UNITS];
595 monitor_cpu_type_t *asmarray[3];
596
597 asmarray[0] = &asm6502;
598 asmarray[1] = &asm6809;
599 asmarray[2] = NULL;
600
601 asm6502_init(&asm6502);
602 asm6809_init(&asm6809);
603
604 for (dnr = 0; dnr < NUM_DISK_UNITS; dnr++) {
605 drive_interface_init[dnr] = drive_cpu_monitor_interface_get(dnr);
606 }
607
608 /* Initialize the monitor. */
609 monitor_init(maincpu_monitor_interface_get(), drive_interface_init,
610 asmarray);
611 }
612
machine_setup_context(void)613 void machine_setup_context(void)
614 {
615 petvia_setup_context(&machine_context);
616 machine_printer_setup_context(&machine_context);
617 }
618
619 /* PET-specific initialization. */
machine_specific_init(void)620 int machine_specific_init(void)
621 {
622 pet_log = log_open("PET");
623
624 pet_init_ok = 1; /* used in petmodel_set() */
625
626 event_init();
627
628 /* Setup trap handling - must be before mem_load() */
629 traps_init();
630
631 if (mem_load() < 0) {
632 return -1;
633 }
634
635 gfxoutput_init();
636
637 log_message(pet_log, "Initializing IEEE488 bus...");
638
639 rs232drv_init();
640
641 /* initialize print devices */
642 printer_init();
643
644 /* Pre-init PET-specific parts of the menus before crtc_init()
645 creates a canvas window with a menubar at the top. */
646 if (!console_mode) {
647 petui_init_early();
648 }
649
650 /* Initialize the CRTC emulation. */
651 if (crtc_init() == NULL) {
652 return -1;
653 }
654
655 crtc_set_retrace_type(petres.crtc);
656 crtc_set_retrace_callback(pet_crtc_signal);
657 pet_crtc_set_screen();
658 petcolour_init();
659
660 via_init(machine_context.via);
661 pia1_init();
662 pia2_init();
663 acia1_init();
664
665 /* Initialize the datasette emulation. */
666 datasette_init();
667
668 /* Fire up the hardware-level 1541 emulation. */
669 drive_init();
670
671 disk_image_init();
672
673 pet_monitor_init();
674
675 /* Initialize vsync and register our hook function. */
676 vsync_init(machine_vsync_hook);
677 vsync_set_machine_parameter(machine_timing.rfsh_per_sec,
678 machine_timing.cycles_per_sec);
679
680 /* Initialize the sidcart first */
681 sidcart_sound_chip_init();
682
683 /* Initialize native sound chip */
684 pet_sound_chip_init();
685
686 /* Initialize userport based sound chips */
687 userport_dac_sound_chip_init();
688
689 drive_sound_init();
690 datasette_sound_init();
691 video_sound_init();
692
693 /* Initialize sound. Notice that this does not really open the audio
694 device yet. */
695 sound_init((unsigned int)machine_timing.cycles_per_sec,
696 (unsigned int)machine_timing.cycles_per_rfsh);
697
698 /* Initialize keyboard buffer. FIXME: Is this correct? */
699 /* moved to mem_load() because it's model specific... AF 30jun1998
700 kbdbuf_init(631, 198, 10, PET_PAL_CYCLES_PER_RFSH * PET_PAL_RFSH_PER_SEC);
701 */
702
703 /* Initialize the PET-specific part of the UI. */
704 if (!console_mode) {
705 petui_init();
706 }
707
708 if (!video_disabled_mode) {
709 joystick_init();
710 }
711
712 /* Initialize the PET Ram and Expansion Unit. */
713 petreu_init();
714
715 /* Initialize the PET Double-W Hi-Res graphics card. */
716 petdww_init();
717
718 /* Initialize the PET Hi-Res Emulator graphics card. */
719 pethre_init();
720
721 petiec_init();
722
723 #ifdef HAVE_MOUSE
724 /* Initialize mouse support (if present). */
725 mouse_init();
726 #endif
727
728 machine_drive_stub();
729
730 return 0;
731 }
732
machine_specific_powerup(void)733 void machine_specific_powerup(void)
734 {
735 petdww_powerup();
736 pethre_powerup();
737 }
738
739 /* PET-specific initialization. */
machine_specific_reset(void)740 void machine_specific_reset(void)
741 {
742 pia1_reset();
743 pia2_reset();
744 viacore_reset(machine_context.via);
745 acia1_reset();
746 crtc_reset();
747 sid_reset();
748 petmem_reset();
749 rs232drv_reset();
750 printer_reset();
751 drive_reset();
752 datasette_reset();
753 petreu_reset();
754 petdww_reset();
755 pethre_reset();
756 sampler_reset();
757 }
758
machine_specific_shutdown(void)759 void machine_specific_shutdown(void)
760 {
761 /* and the tape */
762 tape_image_detach_internal(1);
763
764 viacore_shutdown(machine_context.via);
765
766 /* close the video chip(s) */
767 petdww_shutdown();
768 pethre_shutdown();
769 crtc_shutdown();
770
771 petreu_shutdown();
772
773 #ifdef HAVE_MOUSE
774 mouse_shutdown();
775 #endif
776
777 if (!console_mode) {
778 petui_shutdown();
779 }
780 }
781
782 /* ------------------------------------------------------------------------- */
783
784 /* This hook is called at the end of every frame. */
machine_vsync_hook(void)785 static void machine_vsync_hook(void)
786 {
787 CLOCK sub;
788
789 autostart_advance();
790
791 drive_vsync_hook();
792
793 screenshot_record();
794
795 sub = clk_guard_prevent_overflow(maincpu_clk_guard);
796
797 /* The drive has to deal both with our overflowing and its own one, so
798 it is called even when there is no overflowing in the main CPU. */
799 drive_cpu_prevent_clk_overflow_all(sub);
800 }
801
802 /* Dummy - no restore key. */
machine_set_restore_key(int v)803 void machine_set_restore_key(int v)
804 {
805 }
806
machine_has_restore_key(void)807 int machine_has_restore_key(void)
808 {
809 return 0;
810 }
811
812 /* ------------------------------------------------------------------------- */
813
machine_get_cycles_per_second(void)814 long machine_get_cycles_per_second(void)
815 {
816 return machine_timing.cycles_per_sec;
817 }
818
machine_get_cycles_per_frame(void)819 long machine_get_cycles_per_frame(void)
820 {
821 return machine_timing.cycles_per_rfsh;
822 }
823
machine_get_line_cycle(unsigned int * line,unsigned int * cycle,int * half_cycle)824 void machine_get_line_cycle(unsigned int *line, unsigned int *cycle, int *half_cycle)
825 {
826 *line = (unsigned int)((maincpu_clk) / machine_timing.cycles_per_line % machine_timing.screen_lines);
827
828 *cycle = (unsigned int)((maincpu_clk) % machine_timing.cycles_per_line);
829
830 *half_cycle = (int)-1;
831 }
832
machine_change_timing(int timeval,int border_mode)833 void machine_change_timing(int timeval, int border_mode)
834 {
835 switch (timeval) {
836 case MACHINE_SYNC_PAL:
837 machine_timing.cycles_per_sec = PET_PAL_CYCLES_PER_SEC;
838 machine_timing.cycles_per_rfsh = PET_PAL_CYCLES_PER_RFSH;
839 machine_timing.rfsh_per_sec = PET_PAL_RFSH_PER_SEC;
840 machine_timing.cycles_per_line = PET_PAL_CYCLES_PER_LINE;
841 machine_timing.screen_lines = PET_PAL_SCREEN_LINES;
842 machine_timing.power_freq = 50;
843 break;
844 case MACHINE_SYNC_NTSC:
845 machine_timing.cycles_per_sec = PET_NTSC_CYCLES_PER_SEC;
846 machine_timing.cycles_per_rfsh = PET_NTSC_CYCLES_PER_RFSH;
847 machine_timing.rfsh_per_sec = PET_NTSC_RFSH_PER_SEC;
848 machine_timing.cycles_per_line = PET_NTSC_CYCLES_PER_LINE;
849 machine_timing.screen_lines = PET_NTSC_SCREEN_LINES;
850 machine_timing.power_freq = 60;
851 break;
852 default:
853 log_error(pet_log, "Unknown machine timing.");
854 }
855
856 debug_set_machine_parameter(machine_timing.cycles_per_line, machine_timing.screen_lines);
857 drive_set_machine_parameter(machine_timing.cycles_per_sec);
858
859 /* Should these be called also? */
860 #if 0
861 vsync_set_machine_parameter(machine_timing.rfsh_per_sec, machine_timing.cycles_per_sec);
862 sound_set_machine_parameter(machine_timing.cycles_per_sec, machine_timing.cycles_per_rfsh);
863 sid_set_machine_parameter(machine_timing.cycles_per_sec);
864 clk_guard_set_clk_base(maincpu_clk_guard, machine_timing.cycles_per_rfsh);
865 #endif
866
867 machine_trigger_reset(MACHINE_RESET_MODE_HARD);
868 }
869
870 /* Set the screen refresh rate, as this is variable in the CRTC */
machine_set_cycles_per_frame(long cpf)871 void machine_set_cycles_per_frame(long cpf)
872 {
873 double i, f;
874
875 machine_timing.cycles_per_rfsh = cpf;
876 machine_timing.rfsh_per_sec = ((double)machine_timing.cycles_per_sec)
877 / ((double)cpf);
878
879 f = modf(machine_timing.rfsh_per_sec, &i) * 1000;
880
881 log_message(pet_log, "cycles per frame set to %ld, refresh to %d.%03dHz",
882 cpf, (int)i, (int)f);
883
884 vsync_set_machine_parameter(machine_timing.rfsh_per_sec,
885 machine_timing.cycles_per_sec);
886
887 /* sound_set_cycles_per_rfsh(machine_timing.cycles_per_rfsh); */
888 }
889
890 /* ------------------------------------------------------------------------- */
891
machine_write_snapshot(const char * name,int save_roms,int save_disks,int event_mode)892 int machine_write_snapshot(const char *name, int save_roms, int save_disks,
893 int event_mode)
894 {
895 return pet_snapshot_write(name, save_roms, save_disks, event_mode);
896 }
897
machine_read_snapshot(const char * name,int event_mode)898 int machine_read_snapshot(const char *name, int event_mode)
899 {
900 return pet_snapshot_read(name, event_mode);
901 }
902
903
904 /* ------------------------------------------------------------------------- */
905
machine_autodetect_psid(const char * name)906 int machine_autodetect_psid(const char *name)
907 {
908 return -1;
909 }
910
911
912 /* ------------------------------------------------------------------------- */
913
pet_crtc_set_screen(void)914 void pet_crtc_set_screen(void)
915 {
916 int cols, vmask;
917
918 cols = petres.video;
919 vmask = petres.vmask;
920
921 /* mem_initialize_memory(); */
922
923 if (!cols) {
924 cols = petres.rom_video;
925 if (!cols) {
926 cols = PET_COLS;
927 }
928 vmask = (cols == 40) ? 0x3ff : 0x7ff;
929 }
930
931 /* when switching 8296 to 40 columns, CRTC ends up at $9000 otherwise...*/
932 if (cols == 40) {
933 vmask = 0x3ff;
934 }
935 /*
936 log_message(pet_mem_log, "set_screen(vmask=%04x, cols=%d, crtc=%d)",
937 vmask, cols, petres.crtc);
938 */
939 /*
940 crtc_set_screen_mode(mem_ram + 0x8000, vmask, cols, (cols==80) ? 2 : 0);
941 */
942 crtc_set_screen_options(cols, 25 * 10);
943 crtc_set_screen_addr(mem_ram + 0x8000);
944 crtc_set_hw_options((cols == 80) ? 2 : 0, vmask, 0x2000, 512, 0x1000);
945 crtc_set_retrace_type(petres.crtc ? 1 : 0);
946
947 /* No CRTC -> assume 40 columns and 60 Hz */
948 if (!petres.crtc) {
949 static uint8_t crtc_values[14] = {
950 /*
951 * Set the CRTC to display 60 frames per second.
952 *
953 * Tuned specifically for 64 clocks (= chars) per scanline,
954 * for the Cursor #18 Hi-Res program.
955 * The exact time of the IRQ is probably not 100% right,
956 * but close enough to get a visual effect.
957 *
958 * 15625 Hz horizontal
959 * PET: cycles per frame set to 16640, refresh to 60.096Hz
960 *
961 * Additional note: new ROMs 99/9A count to 623:
962 * 0099-009A Jiffy clock correction: 623rd 1/60 sec
963 * does not increment time
964 *
965 * Presumably this should correct the frequency which is
966 * slightly over 60 Hz: 60.096 * 622 / 623 = 59.99954.
967 *
968 * Note that with the granularity of 1 scanline we cannot
969 * really get closer to the "real" freqency, assuming that
970 * the 622/623 fix is perfect: 60 * 623 / 622 = 60.096 463.
971 */
972 63, /* R0 total horizontal characters - 1 */
973 40, /* R1 displayed horizontal characters */
974 50, /* R2 horizontal sync position */
975 (0 << 4)|8, /* R3 vertical / horizontal sync width */
976 31, /* R4 total vertical characters - 1 */
977 4, /* R5 total vertical lines adjustment */
978 25, /* R6 displayed vertical characters */
979 29, /* R7 vertical sync position */
980 0, /* R8 MODECTRL */
981 7, /* R9 scanlines per character row - 1, including spacing */
982 0, /* R10 CURSORSTART */
983 0, /* R11 CURSOREND */
984 0x10, /* R12 DISPSTARTH */
985 0x00, /* R13 DISPSTARTL */
986 #if 0
987 /*
988 * Original values.
989 * PET: cycles per frame set to 17920, refresh to 55.803Hz
990 */
991 63, 40, 50, 8, 32, 16, 25, 29,
992 0, 7, 0, 0, 0x10, 0,
993 #endif
994 };
995 int r;
996
997 for (r = 13; r >= 0; r--) {
998 crtc_store(0, r);
999 crtc_store(1, crtc_values[r]);
1000 }
1001 }
1002 }
1003
machine_screenshot(screenshot_t * screenshot,struct video_canvas_s * canvas)1004 int machine_screenshot(screenshot_t *screenshot, struct video_canvas_s *canvas)
1005 {
1006 if (canvas != crtc_get_canvas()) {
1007 return -1;
1008 }
1009
1010 crtc_screenshot(screenshot);
1011 return 0;
1012 }
1013
machine_canvas_async_refresh(struct canvas_refresh_s * refresh,struct video_canvas_s * canvas)1014 int machine_canvas_async_refresh(struct canvas_refresh_s *refresh,
1015 struct video_canvas_s *canvas)
1016 {
1017 if (canvas != crtc_get_canvas()) {
1018 return -1;
1019 }
1020
1021 crtc_async_refresh(refresh);
1022 return 0;
1023 }
1024
machine_diskcontents_bus_read(unsigned int unit)1025 struct image_contents_s *machine_diskcontents_bus_read(unsigned int unit)
1026 {
1027 return NULL;
1028 }
1029
machine_tape_type_default(void)1030 uint8_t machine_tape_type_default(void)
1031 {
1032 return TAPE_CAS_TYPE_PRG;
1033 }
1034
machine_tape_behaviour(void)1035 uint8_t machine_tape_behaviour(void)
1036 {
1037 return TAPE_BEHAVIOUR_NORMAL;
1038 }
1039
machine_addr_in_ram(unsigned int addr)1040 int machine_addr_in_ram(unsigned int addr)
1041 {
1042 return addr < 0xb000;
1043 }
1044
machine_get_name(void)1045 const char *machine_get_name(void)
1046 {
1047 return machine_name;
1048 }
1049
1050 /* ------------------------------------------------------------------------- */
1051 /* native screenshot support */
1052
crtc_get_active_bitmap(void)1053 uint8_t *crtc_get_active_bitmap(void)
1054 {
1055 uint8_t *retval = NULL;
1056
1057 retval = petdww_crtc_get_active_bitmap();
1058
1059 /* left open for future expansion of boards with their own ram */
1060
1061 return retval;
1062 }
1063
1064 /* ------------------------------------------------------------------------- */
1065
pet_userport_set_flag(uint8_t b)1066 static void pet_userport_set_flag(uint8_t b)
1067 {
1068 viacore_signal(machine_context.via, VIA_SIG_CA1, b ? VIA_SIG_RISE : VIA_SIG_FALL);
1069 }
1070
1071 static userport_port_props_t userport_props = {
1072 1, /* port has the pa2 pin */
1073 0, /* port does NOT have the pa3 pin */
1074 pet_userport_set_flag, /* port has the flag pin, set flag function */
1075 0, /* port does NOT have the pc pin */
1076 0 /* port does NOT have the cnt1, cnt2 or sp pins */
1077 };
1078
machine_register_userport(void)1079 int machine_register_userport(void)
1080 {
1081 userport_port_register(&userport_props);
1082
1083 return 0;
1084 }
1085