1 /*
2  * cbm2.c
3  *
4  * Written by
5  *  Andre Fachat <fachat@physik.tu-chemnitz.de>
6  *  Andreas Boose <viceteam@t-online.de>
7  *  Marco van den Heuvel <blackystardust68@yahoo.com>
8  *
9  * This file is part of VICE, the Versatile Commodore Emulator.
10  * See README for copyright notice.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25  *  02111-1307  USA.
26  *
27  */
28 
29 #include "vice.h"
30 
31 #include <math.h>   /* modf */
32 #include <stdio.h>
33 
34 #include "alarm.h"
35 #include "attach.h"
36 #include "autostart.h"
37 #include "bbrtc.h"
38 #include "cartio.h"
39 #include "cartridge.h"
40 #include "cbm2-cmdline-options.h"
41 #include "cbm2-resources.h"
42 #include "cbm2-snapshot.h"
43 #include "cbm2.h"
44 #include "cbm2acia.h"
45 #include "cbm2cia.h"
46 #include "cbm2iec.h"
47 #include "cbm2model.h"
48 #include "cbm2mem.h"
49 #include "cbm2tpi.h"
50 #include "cbm2ui.h"
51 #include "cia.h"
52 #include "clkguard.h"
53 #include "crtc.h"
54 #include "datasette.h"
55 #include "datasette-sound.h"
56 #include "debug.h"
57 #include "debugcart.h"
58 #include "diskimage.h"
59 #include "drive-cmdline-options.h"
60 #include "drive-resources.h"
61 #include "drive-sound.h"
62 #include "drive.h"
63 #include "fliplist.h"
64 #include "fsdevice.h"
65 #include "gfxoutput.h"
66 #include "iecdrive.h"
67 #include "init.h"
68 #include "joyport.h"
69 #include "joystick.h"
70 #include "kbdbuf.h"
71 #include "keyboard.h"
72 #include "log.h"
73 #include "machine-drive.h"
74 #include "machine-printer.h"
75 #include "machine-video.h"
76 #include "machine.h"
77 #include "maincpu.h"
78 #include "mem.h"
79 #include "monitor.h"
80 #include "network.h"
81 #include "paperclip64.h"
82 #include "parallel.h"
83 #include "printer.h"
84 #include "resources.h"
85 #include "rs232drv.h"
86 #include "sampler.h"
87 #include "sampler2bit.h"
88 #include "sampler4bit.h"
89 #include "screenshot.h"
90 #include "serial.h"
91 #include "sid-cmdline-options.h"
92 #include "sid-resources.h"
93 #include "sid.h"
94 #include "snapshot.h"
95 #include "sound.h"
96 #include "tape.h"
97 #include "tapeport.h"
98 #include "tpi.h"
99 #include "traps.h"
100 #include "types.h"
101 #include "userport.h"
102 #include "userport_4bit_sampler.h"
103 #include "userport_8bss.h"
104 #include "userport_dac.h"
105 #include "userport_digimax.h"
106 #include "userport_joystick.h"
107 #include "userport_rtc_58321a.h"
108 #include "userport_rtc_ds1307.h"
109 #include "vice-event.h"
110 #include "video.h"
111 #include "video-sound.h"
112 #include "vsync.h"
113 
114 #ifdef HAVE_MOUSE
115 #include "mouse.h"
116 #endif
117 
118 /** \brief  Delay in seconds before pasting -keybuf argument into the buffer
119  */
120 #define KBDBUF_ALARM_DELAY   5
121 
122 
123 machine_context_t machine_context;
124 
125 const char machine_name[] = "CBM-II";
126 int machine_class = VICE_MACHINE_CBM6x0;
127 
128 static void machine_vsync_hook(void);
129 
130 /*
131 static long cbm2_cycles_per_sec = C610_PAL_CYCLES_PER_SEC;
132 static double cbm2_rfsh_per_sec = C610_PAL_RFSH_PER_SEC;
133 static long cbm2_cycles_per_rfsh = C610_PAL_CYCLES_PER_RFSH;
134 */
135 
136 static log_t cbm2_log = LOG_ERR;
137 static machine_timing_t machine_timing;
138 
139 /* FIXME: add different keyboard types */
machine_get_keyboard_type(void)140 int machine_get_keyboard_type(void)
141 {
142 #if 0
143     int type;
144     if (resources_get_int("KeyboardType", &type) < 0) {
145         return 0;
146     }
147     return type;
148 #endif
149     return 0;
150 }
151 
machine_get_keyboard_type_name(int type)152 char *machine_get_keyboard_type_name(int type)
153 {
154     return NULL; /* 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 1;
161 }
162 
machine_get_keyboard_info_list(void)163 kbdtype_info_t *machine_get_keyboard_info_list(void)
164 {
165     return NULL; /* return 0 if no different types exist */
166 }
167 
168 
169 /* ------------------------------------------------------------------------- */
170 
171 static joyport_port_props_t userport_joy_control_port_1 =
172 {
173     "Userport joystick adapter port 1",
174     0,                      /* has NO potentiometer connected to this port */
175     0,                      /* has NO lightpen support on this port */
176     0                       /* port can be switched on/off */
177 };
178 
179 static joyport_port_props_t userport_joy_control_port_2 =
180 {
181     "Userport joystick adapter port 2",
182     0,                      /* has NO potentiometer connected to this port */
183     0,                      /* has NO lightpen support on this port */
184     0                       /* port can be switched on/off */
185 };
186 
init_joyport_ports(void)187 static int init_joyport_ports(void)
188 {
189     if (joyport_port_register(JOYPORT_3, &userport_joy_control_port_1) < 0) {
190         return -1;
191     }
192     return joyport_port_register(JOYPORT_4, &userport_joy_control_port_2);
193 }
194 
195 /* CBM-II-specific resource initialization.  This is called before initializing
196    the machine itself with `machine_init()'.  */
machine_resources_init(void)197 int machine_resources_init(void)
198 {
199     if (traps_resources_init() < 0) {
200         init_resource_fail("traps");
201         return -1;
202     }
203     if (cbm2_resources_init() < 0) {
204         init_resource_fail("cbm2");
205         return -1;
206     }
207     if (cartio_resources_init() < 0) {
208         init_resource_fail("cartio");
209         return -1;
210     }
211     if (cartridge_resources_init() < 0) {
212         init_resource_fail("cartridge");
213         return -1;
214     }
215     if (crtc_resources_init() < 0) {
216         init_resource_fail("crtc");
217         return -1;
218     }
219     if (sid_resources_init() < 0) {
220         init_resource_fail("sid");
221         return -1;
222     }
223     if (drive_resources_init() < 0) {
224         init_resource_fail("drive");
225         return -1;
226     }
227     /*
228      * This needs to be called before tapeport_resources_init(), otherwise
229      * the tapecart will fail to initialize due to the Datasette resource
230      * appearing after the Tapecart resources
231      */
232     if (datasette_resources_init() < 0) {
233         init_resource_fail("datasette");
234         return -1;
235     }
236     if (tapeport_resources_init() < 0) {
237         init_resource_fail("tapeport");
238         return -1;
239     }
240     if (acia1_resources_init() < 0) {
241         init_resource_fail("acia1");
242         return -1;
243     }
244     if (rs232drv_resources_init() < 0) {
245         init_resource_fail("rs232drv");
246         return -1;
247     }
248     if (printer_resources_init() < 0) {
249         init_resource_fail("printer");
250         return -1;
251     }
252     if (printer_userport_resources_init() < 0) {
253         init_resource_fail("userport printer");
254         return -1;
255     }
256     if (init_joyport_ports() < 0) {
257         init_resource_fail("joyport ports");
258         return -1;
259     }
260     if (joyport_resources_init() < 0) {
261         init_resource_fail("joyport devices");
262         return -1;
263     }
264     if (joyport_sampler2bit_resources_init() < 0) {
265         init_resource_fail("joyport 2bit sampler");
266         return -1;
267     }
268     if (joyport_sampler4bit_resources_init() < 0) {
269         init_resource_fail("joyport 4bit sampler");
270         return -1;
271     }
272     if (joyport_bbrtc_resources_init() < 0) {
273         init_resource_fail("joyport bbrtc");
274         return -1;
275     }
276     if (joyport_paperclip64_resources_init() < 0) {
277         init_resource_fail("joyport paperclip64 dongle");
278         return -1;
279     }
280     if (joystick_resources_init() < 0) {
281         init_resource_fail("joystick");
282         return -1;
283     }
284     if (sampler_resources_init() < 0) {
285         init_resource_fail("samplerdrv");
286         return -1;
287     }
288     if (userport_resources_init() < 0) {
289         init_resource_fail("userport devices");
290         return -1;
291     }
292     if (gfxoutput_resources_init() < 0) {
293         init_resource_fail("gfxoutput");
294         return -1;
295     }
296     if (fliplist_resources_init() < 0) {
297         init_resource_fail("flip list");
298         return -1;
299     }
300     if (file_system_resources_init() < 0) {
301         init_resource_fail("file system");
302         return -1;
303     }
304     /* Initialize file system device-specific resources.  */
305     if (fsdevice_resources_init() < 0) {
306         init_resource_fail("file system device");
307         return -1;
308     }
309     if (disk_image_resources_init() < 0) {
310         init_resource_fail("disk image");
311         return -1;
312     }
313     if (event_resources_init() < 0) {
314         init_resource_fail("event");
315         return -1;
316     }
317     if (kbdbuf_resources_init() < 0) {
318         init_resource_fail("Keyboard");
319         return -1;
320     }
321     if (autostart_resources_init() < 0) {
322         init_resource_fail("autostart");
323         return -1;
324     }
325 #ifdef HAVE_NETWORK
326     if (network_resources_init() < 0) {
327         init_resource_fail("network");
328         return -1;
329     }
330 #endif
331 #ifdef DEBUG
332     if (debug_resources_init() < 0) {
333         init_resource_fail("debug");
334         return -1;
335     }
336 #endif
337 #ifdef HAVE_MOUSE
338     if (mouse_resources_init() < 0) {
339         init_resource_fail("mouse");
340         return -1;
341     }
342 #endif
343     if (userport_joystick_resources_init() < 0) {
344         init_resource_fail("userport joystick");
345         return -1;
346     }
347     if (userport_dac_resources_init() < 0) {
348         init_resource_fail("userport dac");
349         return -1;
350     }
351     if (userport_digimax_resources_init() < 0) {
352         init_resource_fail("userport digimax");
353         return -1;
354     }
355     if (userport_rtc_58321a_resources_init() < 0) {
356         init_resource_fail("userport rtc (58321a)");
357         return -1;
358     }
359     if (userport_rtc_ds1307_resources_init() < 0) {
360         init_resource_fail("userport rtc (ds1307)");
361         return -1;
362     }
363     if (userport_4bit_sampler_resources_init() < 0) {
364         init_resource_fail("userport 4bit sampler");
365         return -1;
366     }
367     if (userport_8bss_resources_init() < 0) {
368         init_resource_fail("userport 8bit stereo sampler");
369         return -1;
370     }
371     if (debugcart_resources_init() < 0) {
372         init_resource_fail("debug cart");
373         return -1;
374     }
375     return 0;
376 }
377 
machine_resources_shutdown(void)378 void machine_resources_shutdown(void)
379 {
380     serial_shutdown();
381     cbm2_resources_shutdown();
382     rs232drv_resources_shutdown();
383     printer_resources_shutdown();
384     drive_resources_shutdown();
385     fsdevice_resources_shutdown();
386     disk_image_resources_shutdown();
387     sampler_resources_shutdown();
388     cartio_shutdown();
389     userport_rtc_58321a_resources_shutdown();
390     userport_rtc_ds1307_resources_shutdown();
391     userport_resources_shutdown();
392     joyport_bbrtc_resources_shutdown();
393     tapeport_resources_shutdown();
394     debugcart_resources_shutdown();
395     cartridge_resources_shutdown();
396 }
397 
398 /* CBM-II-specific command-line option initialization.  */
machine_cmdline_options_init(void)399 int machine_cmdline_options_init(void)
400 {
401     if (traps_cmdline_options_init() < 0) {
402         init_cmdline_options_fail("traps");
403         return -1;
404     }
405     if (cbm2_cmdline_options_init() < 0) {
406         init_cmdline_options_fail("cbm2");
407         return -1;
408     }
409     if (cartio_cmdline_options_init() < 0) {
410         init_cmdline_options_fail("cartio");
411         return -1;
412     }
413     if (cartridge_cmdline_options_init() < 0) {
414         init_cmdline_options_fail("cartridge");
415         return -1;
416     }
417     if (crtc_cmdline_options_init() < 0) {
418         init_cmdline_options_fail("crtc");
419         return -1;
420     }
421     if (sid_cmdline_options_init(SIDTYPE_SID) < 0) {
422         init_cmdline_options_fail("sid");
423         return -1;
424     }
425     if (drive_cmdline_options_init() < 0) {
426         init_cmdline_options_fail("drive");
427         return -1;
428     }
429     if (tapeport_cmdline_options_init() < 0) {
430         init_cmdline_options_fail("tapeport");
431         return -1;
432     }
433     if (datasette_cmdline_options_init() < 0) {
434         init_cmdline_options_fail("datasette");
435         return -1;
436     }
437     if (acia1_cmdline_options_init() < 0) {
438         init_cmdline_options_fail("acia1");
439         return -1;
440     }
441     if (rs232drv_cmdline_options_init() < 0) {
442         init_cmdline_options_fail("rs232drv");
443         return -1;
444     }
445     if (printer_cmdline_options_init() < 0) {
446         init_cmdline_options_fail("printer");
447         return -1;
448     }
449     if (printer_userport_cmdline_options_init() < 0) {
450         init_cmdline_options_fail("userport printer");
451         return -1;
452     }
453     if (joyport_cmdline_options_init() < 0) {
454         init_cmdline_options_fail("joyport");
455         return -1;
456     }
457     if (joyport_bbrtc_cmdline_options_init() < 0) {
458         init_cmdline_options_fail("bbrtc");
459         return -1;
460     }
461     if (joystick_cmdline_options_init() < 0) {
462         init_cmdline_options_fail("joystick");
463         return -1;
464     }
465     if (userport_cmdline_options_init() < 0) {
466         init_cmdline_options_fail("userport");
467         return -1;
468     }
469     if (gfxoutput_cmdline_options_init() < 0) {
470         init_cmdline_options_fail("gfxoutput");
471         return -1;
472     }
473     if (sampler_cmdline_options_init() < 0) {
474         init_cmdline_options_fail("samplerdrv");
475         return -1;
476     }
477     if (fliplist_cmdline_options_init() < 0) {
478         init_cmdline_options_fail("flip list");
479         return -1;
480     }
481     if (file_system_cmdline_options_init() < 0) {
482         init_cmdline_options_fail("attach");
483         return -1;
484     }
485     if (fsdevice_cmdline_options_init() < 0) {
486         init_cmdline_options_fail("file system");
487         return -1;
488     }
489     if (disk_image_cmdline_options_init() < 0) {
490         init_cmdline_options_fail("disk image");
491         return -1;
492     }
493     if (event_cmdline_options_init() < 0) {
494         init_cmdline_options_fail("event");
495         return -1;
496     }
497     if (kbdbuf_cmdline_options_init() < 0) {
498         init_cmdline_options_fail("keyboard");
499         return -1;
500     }
501     if (autostart_cmdline_options_init() < 0) {
502         init_cmdline_options_fail("autostart");
503         return -1;
504     }
505 #ifdef HAVE_NETWORK
506     if (network_cmdline_options_init() < 0) {
507         init_cmdline_options_fail("network");
508         return -1;
509     }
510 #endif
511 #ifdef DEBUG
512     if (debug_cmdline_options_init() < 0) {
513         init_cmdline_options_fail("debug");
514         return -1;
515     }
516 #endif
517 #ifdef HAVE_MOUSE
518     if (mouse_cmdline_options_init() < 0) {
519         init_cmdline_options_fail("mouse");
520         return -1;
521     }
522 #endif
523     if (userport_joystick_cmdline_options_init() < 0) {
524         init_cmdline_options_fail("userport joystick");
525         return -1;
526     }
527     if (userport_dac_cmdline_options_init() < 0) {
528         init_cmdline_options_fail("userport dac");
529         return -1;
530     }
531     if (userport_digimax_cmdline_options_init() < 0) {
532         init_cmdline_options_fail("userport digimax");
533         return -1;
534     }
535     if (userport_rtc_58321a_cmdline_options_init() < 0) {
536         init_cmdline_options_fail("userport rtc (58321a)");
537         return -1;
538     }
539     if (userport_rtc_ds1307_cmdline_options_init() < 0) {
540         init_cmdline_options_fail("userport rtc (ds1307)");
541         return -1;
542     }
543     if (userport_4bit_sampler_cmdline_options_init() < 0) {
544         init_cmdline_options_fail("userport 4bit sampler");
545         return -1;
546     }
547     if (userport_8bss_cmdline_options_init() < 0) {
548         init_cmdline_options_fail("userport 8bit stereo sampler");
549         return -1;
550     }
551     if (debugcart_cmdline_options_init() < 0) {
552         init_cmdline_options_fail("debug cart");
553         return -1;
554     }
555     return 0;
556 }
557 
558 /* ------------------------------------------------------------------------- */
559 /* provide the 50(?)Hz IRQ signal for the standard IRQ */
560 
561 #define SIGNAL_VERT_BLANK_OFF tpicore_set_int(machine_context.tpi1, 0, 1);
562 
563 #define SIGNAL_VERT_BLANK_ON  tpicore_set_int(machine_context.tpi1, 0, 0);
564 
565 /* ------------------------------------------------------------------------- */
566 /* ... while the other CBM-II use the CRTC retrace signal. */
567 
cbm2_crtc_signal(unsigned int signal)568 static void cbm2_crtc_signal(unsigned int signal)
569 {
570     if (signal) {
571         SIGNAL_VERT_BLANK_ON
572     } else {
573         SIGNAL_VERT_BLANK_OFF
574     }
575 }
576 
577 /* ------------------------------------------------------------------------- */
578 
cbm2_monitor_init(void)579 static void cbm2_monitor_init(void)
580 {
581     unsigned int dnr;
582     monitor_cpu_type_t asm6502;
583     monitor_interface_t *drive_interface_init[NUM_DISK_UNITS];
584     monitor_cpu_type_t *asmarray[2];
585 
586     asmarray[0] = &asm6502;
587     asmarray[1] = NULL;
588 
589     asm6502_init(&asm6502);
590 
591     for (dnr = 0; dnr < NUM_DISK_UNITS; dnr++) {
592         drive_interface_init[dnr] = drive_cpu_monitor_interface_get(dnr);
593     }
594 
595     /* Initialize the monitor.  */
596     monitor_init(maincpu_monitor_interface_get(), drive_interface_init,
597                  asmarray);
598 }
599 
machine_setup_context(void)600 void machine_setup_context(void)
601 {
602     cia1_setup_context(&machine_context);
603     tpi1_setup_context(&machine_context);
604     tpi2_setup_context(&machine_context);
605     machine_printer_setup_context(&machine_context);
606 }
607 
608 /* CBM-II-specific initialization.  */
machine_specific_init(void)609 int machine_specific_init(void)
610 {
611     cbm2_log = log_open("CBM2");
612 
613     cbm2_init_ok = 1;
614 
615     event_init();
616 
617     /* Setup trap handling - must be before mem_load() */
618     traps_init();
619 
620     if (mem_load() < 0) {
621         return -1;
622     }
623 
624     gfxoutput_init();
625 
626     rs232drv_init();
627 
628     /* initialize print devices */
629     printer_init();
630 
631     /* Pre-init CBM-II-specific parts of the menus before crtc_init()
632        creates a canvas window with a menubar at the top. */
633     if (!console_mode) {
634         cbm2ui_init_early();
635     }
636 
637     if (crtc_init() == NULL) {
638         return -1;
639     }
640     crtc_set_retrace_callback(cbm2_crtc_signal);
641     crtc_set_retrace_type(0);
642     crtc_set_hw_options(1, 0x7ff, 0x1000, 512, -0x2000);
643 
644     cia1_init(machine_context.cia1);
645     acia1_init();
646     tpi1_init(machine_context.tpi1);
647     tpi2_init(machine_context.tpi2);
648 
649     /* Initialize the datasette emulation.  */
650     datasette_init();
651 
652     /* Fire up the hardware-level 1541 emulation.  */
653     drive_init();
654 
655     disk_image_init();
656 
657     cbm2_monitor_init();
658 
659     /* Initialize vsync and register our hook function.  */
660     vsync_init(machine_vsync_hook);
661     vsync_set_machine_parameter(machine_timing.rfsh_per_sec,
662                                 machine_timing.cycles_per_sec);
663 
664     /* Initialize native sound chip */
665     sid_sound_chip_init();
666 
667     /* Initialize userport based sound chips */
668     userport_dac_sound_chip_init();
669     userport_digimax_sound_chip_init();
670 
671     drive_sound_init();
672     datasette_sound_init();
673     video_sound_init();
674 
675     /* Initialize sound.  Notice that this does not really open the audio
676        device yet.  */
677     sound_init((unsigned int)machine_timing.cycles_per_sec,
678                (unsigned int)machine_timing.cycles_per_rfsh);
679 
680     /* Initialize the CBM-II-specific part of the UI.  */
681     if (!console_mode) {
682         cbm2ui_init();
683     }
684 
685     if (!video_disabled_mode) {
686         joystick_init();
687     }
688 
689     cbm2iec_init();
690 
691 #ifdef HAVE_MOUSE
692     /* Initialize mouse support (if present).  */
693     mouse_init();
694 #endif
695 
696     machine_drive_stub();
697 
698     /* Initialize the CBM2-specific I/O */
699     cbm2io_init();
700 
701     return 0;
702 }
703 
704 /* CBM-II-specific initialization.  */
machine_specific_reset(void)705 void machine_specific_reset(void)
706 {
707     int delay = KBDBUF_ALARM_DELAY;
708     int model = cbm2model_get();
709 
710     ciacore_reset(machine_context.cia1);
711     tpicore_reset(machine_context.tpi1);
712     tpicore_reset(machine_context.tpi2);
713     acia1_reset();
714 
715     sid_reset();
716 
717     crtc_reset();
718 
719     printer_reset();
720 
721     rs232drv_reset();
722 
723     drive_reset();
724     datasette_reset();
725 
726     mem_reset();
727 
728     /* delays figured out by running each model */
729     /* printf("cbm2model: %d\n", model); */
730     switch (model) {
731         /* Most likely unneeded, since cbm5x0 should handle these. But should
732          * someone be clever enough to turn the #define's in cmb2model.h into
733          * an enum, a compiler could catch missing cases.
734          */
735         case CBM2MODEL_510_PAL:     /* fallthrough */
736         case CBM2MODEL_510_NTSC:
737             delay = 7;  /* only valid for the default 64KB RAM */
738             break;
739 
740         /* 610: default RAM: 128KB */
741         case CBM2MODEL_610_PAL:     /* fallthrough */
742         case CBM2MODEL_610_NTSC:
743             delay = 4;
744             break;
745 
746         /* 620: default RAM: 256KB */
747         case CBM2MODEL_620_PAL:     /* fallthrough */
748         case CBM2MODEL_620_NTSC:
749             delay = 8;
750             break;
751 
752         case CBM2MODEL_620PLUS_PAL: /* fallthrough */
753         case CBM2MODEL_620PLUS_NTSC:
754             delay = 25;
755             break;
756         case CBM2MODEL_710_NTSC:
757             delay = 4;
758             break;
759         case CBM2MODEL_720_NTSC:
760             delay = 25;
761             break;
762         case CBM2MODEL_720PLUS_NTSC:
763             delay = 25;
764             break;
765 
766         /* When the RAM set via -ramsize doesn't match the RAM size for the
767          * selected model in the table in cbm2model.h, the model is set
768          * to CBM2MODEL_UNKNOWN (99) */
769         default:
770            switch (ramsize) {
771                 case 128:
772                     delay = 4;
773                     break;
774                 case 256:
775                     delay = 8;
776                     break;
777                 case 512:
778                     delay = 13;
779                     break;
780                 case 1024:
781                     delay = 30;
782                     break;
783                 default:
784                     delay = 30;     /* shouldn't get here */
785             }
786             break;
787     }
788 
789     /* Initialize keyboard buffer.
790        This appears to work but doesn't account for banking. */
791     /* printf("init kbdbuf with %d seconds delay\n", delay); */
792     kbdbuf_init(0x03ab, 0x00d1, 10,
793             (CLOCK)(machine_timing.rfsh_per_sec *
794                 machine_timing.cycles_per_rfsh * delay));
795 
796     sampler_reset();
797 }
798 
machine_specific_powerup(void)799 void machine_specific_powerup(void)
800 {
801 }
802 
machine_specific_shutdown(void)803 void machine_specific_shutdown(void)
804 {
805     /* and the tape */
806     tape_image_detach_internal(1);
807 
808     ciacore_shutdown(machine_context.cia1);
809     tpicore_shutdown(machine_context.tpi1);
810     tpicore_shutdown(machine_context.tpi2);
811 
812     /* close the video chip(s) */
813     crtc_shutdown();
814 
815 #ifdef HAVE_MOUSE
816     mouse_shutdown();
817 #endif
818 
819     if (!console_mode) {
820         cbm2ui_shutdown();
821     }
822 }
823 
machine_handle_pending_alarms(int num_write_cycles)824 void machine_handle_pending_alarms(int num_write_cycles)
825 {
826 }
827 
828 /* ------------------------------------------------------------------------- */
829 
830 /* This hook is called at the end of every frame.  */
machine_vsync_hook(void)831 static void machine_vsync_hook(void)
832 {
833     CLOCK sub;
834 
835     drive_vsync_hook();
836 
837     autostart_advance();
838 
839     screenshot_record();
840 
841     sub = clk_guard_prevent_overflow(maincpu_clk_guard);
842 
843     /* The drive has to deal both with our overflowing and its own one, so
844        it is called even when there is no overflowing in the main CPU.  */
845     drive_cpu_prevent_clk_overflow_all(sub);
846 }
847 
848 /* Dummy - no restore key.  */
machine_set_restore_key(int v)849 void machine_set_restore_key(int v)
850 {
851 }
852 
machine_has_restore_key(void)853 int machine_has_restore_key(void)
854 {
855     return 0;
856 }
857 
858 /* ------------------------------------------------------------------------- */
859 
machine_get_cycles_per_second(void)860 long machine_get_cycles_per_second(void)
861 {
862     return machine_timing.cycles_per_sec;
863 }
864 
machine_get_cycles_per_frame(void)865 long machine_get_cycles_per_frame(void)
866 {
867     return machine_timing.cycles_per_rfsh;
868 }
869 
machine_get_line_cycle(unsigned int * line,unsigned int * cycle,int * half_cycle)870 void machine_get_line_cycle(unsigned int *line, unsigned int *cycle, int *half_cycle)
871 {
872     *line = (unsigned int)((maincpu_clk) / machine_timing.cycles_per_line % machine_timing.screen_lines);
873 
874     *cycle = (unsigned int)((maincpu_clk) % machine_timing.cycles_per_line);
875 
876     *half_cycle = (int)-1;
877 }
878 
machine_change_timing(int timeval,int border_mode)879 void machine_change_timing(int timeval, int border_mode)
880 {
881     /* log_message(LOG_DEFAULT, "machine_change_timing_c610 %d", timeval); */
882 
883     switch (timeval) {
884         case MACHINE_SYNC_PAL:
885             machine_timing.cycles_per_sec = C610_PAL_CYCLES_PER_SEC;
886             machine_timing.cycles_per_rfsh = C610_PAL_CYCLES_PER_RFSH;
887             machine_timing.rfsh_per_sec = C610_PAL_RFSH_PER_SEC;
888             machine_timing.cycles_per_line = C610_PAL_CYCLES_PER_LINE;
889             machine_timing.screen_lines = C610_PAL_SCREEN_LINES;
890             machine_timing.power_freq = 50;
891             break;
892         case MACHINE_SYNC_NTSC:
893             machine_timing.cycles_per_sec = C610_NTSC_CYCLES_PER_SEC;
894             machine_timing.cycles_per_rfsh = C610_NTSC_CYCLES_PER_RFSH;
895             machine_timing.rfsh_per_sec = C610_NTSC_RFSH_PER_SEC;
896             machine_timing.cycles_per_line = C610_NTSC_CYCLES_PER_LINE;
897             machine_timing.screen_lines = C610_NTSC_SCREEN_LINES;
898             machine_timing.power_freq = 60;
899             break;
900         default:
901             log_error(LOG_DEFAULT, "Unknown machine timing.");
902     }
903 
904     debug_set_machine_parameter(machine_timing.cycles_per_line,
905                                 machine_timing.screen_lines);
906     drive_set_machine_parameter(machine_timing.cycles_per_sec);
907     clk_guard_set_clk_base(maincpu_clk_guard, (CLOCK)machine_timing.cycles_per_rfsh);
908 
909     cia1_set_timing(machine_context.cia1,
910                     (int)machine_timing.cycles_per_sec,
911                     machine_timing.power_freq);
912 }
913 
914 /* Set the screen refresh rate, as this is variable in the CRTC */
machine_set_cycles_per_frame(long cpf)915 void machine_set_cycles_per_frame(long cpf)
916 {
917     double i, f;
918 
919     machine_timing.cycles_per_rfsh = cpf;
920     machine_timing.rfsh_per_sec = ((double)machine_timing.cycles_per_sec)
921                                   / ((double)cpf);
922 
923     f = modf(machine_timing.rfsh_per_sec, &i) * 1000;
924     log_message(cbm2_log, "cycles per frame set to %ld, refresh to %d.%03dHz",
925                 cpf, (int)i, (int)f);
926 
927     vsync_set_machine_parameter(machine_timing.rfsh_per_sec,
928                                 machine_timing.cycles_per_sec);
929 }
930 
931 /* ------------------------------------------------------------------------- */
932 
machine_write_snapshot(const char * name,int save_roms,int save_disks,int event_mode)933 int machine_write_snapshot(const char *name, int save_roms, int save_disks,
934                            int event_mode)
935 {
936     int err = cbm2_snapshot_write(name, save_roms, save_disks, event_mode);
937     if ((err < 0) && (snapshot_get_error() == SNAPSHOT_NO_ERROR)) {
938         snapshot_set_error(SNAPSHOT_CANNOT_WRITE_SNAPSHOT);
939     }
940     return err;
941 }
942 
machine_read_snapshot(const char * name,int event_mode)943 int machine_read_snapshot(const char *name, int event_mode)
944 {
945     int err = cbm2_snapshot_read(name, event_mode);
946     if ((err < 0) && (snapshot_get_error() == SNAPSHOT_NO_ERROR)) {
947         snapshot_set_error(SNAPSHOT_CANNOT_READ_SNAPSHOT);
948     }
949     return err;
950 }
951 
952 /* ------------------------------------------------------------------------- */
953 
machine_autodetect_psid(const char * name)954 int machine_autodetect_psid(const char *name)
955 {
956     return -1;
957 }
958 
machine_screenshot(screenshot_t * screenshot,struct video_canvas_s * canvas)959 int machine_screenshot(screenshot_t *screenshot, struct video_canvas_s *canvas)
960 {
961     if (canvas == crtc_get_canvas()) {
962         crtc_screenshot(screenshot);
963         return 0;
964     }
965 
966     return -1;
967 }
968 
machine_canvas_async_refresh(struct canvas_refresh_s * refresh,struct video_canvas_s * canvas)969 int machine_canvas_async_refresh(struct canvas_refresh_s *refresh,
970                                  struct video_canvas_s *canvas)
971 {
972     if (canvas == crtc_get_canvas()) {
973         crtc_async_refresh(refresh);
974         return 0;
975     }
976     return -1;
977 }
978 
979 /*-----------------------------------------------------------------------*/
980 
machine_diskcontents_bus_read(unsigned int unit)981 struct image_contents_s *machine_diskcontents_bus_read(unsigned int unit)
982 {
983     return NULL;
984 }
985 
machine_tape_type_default(void)986 uint8_t machine_tape_type_default(void)
987 {
988     return TAPE_CAS_TYPE_BAS;
989 }
990 
machine_tape_behaviour(void)991 uint8_t machine_tape_behaviour(void)
992 {
993     return TAPE_BEHAVIOUR_NORMAL;
994 }
995 
machine_addr_in_ram(unsigned int addr)996 int machine_addr_in_ram(unsigned int addr)
997 {
998     /* FIXME: handle the banking */
999     return (addr < 0xe000 && !(addr >= 0x8000 && addr < 0xc000)) ? 1 : 0;
1000 }
1001 
machine_get_name(void)1002 const char *machine_get_name(void)
1003 {
1004     return machine_name;
1005 }
1006 
1007 /* ------------------------------------------------------------------------- */
1008 
1009 /* native screenshot support */
1010 
crtc_get_active_bitmap(void)1011 uint8_t *crtc_get_active_bitmap(void)
1012 {
1013     return NULL;
1014 }
1015 
1016 /* ------------------------------------------------------------------------- */
1017 
cbm2_userport_set_flag(uint8_t b)1018 static void cbm2_userport_set_flag(uint8_t b)
1019 {
1020     if (b != 0) {
1021         ciacore_set_flag(machine_context.cia1);
1022     }
1023 }
1024 
1025 static userport_port_props_t userport_props = {
1026     1,                      /* port has the pa2 pin */
1027     1,                      /* port has the pa3 pin */
1028     cbm2_userport_set_flag, /* port has the flag pin, set flag function */
1029     1,                      /* port has the pc pin */
1030     0                       /* port does NOT have the cnt1, cnt2 or sp pins */
1031 };
1032 
machine_register_userport(void)1033 int machine_register_userport(void)
1034 {
1035     userport_port_register(&userport_props);
1036 
1037     return 0;
1038 }
1039