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