1 /*
2  * cbm5x0.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 "cbm2mem.h"
48 #include "cbm2tpi.h"
49 #include "cbm2ui.h"
50 #include "cia.h"
51 #include "clkguard.h"
52 #include "datasette.h"
53 #include "debug.h"
54 #include "debugcart.h"
55 #include "diskimage.h"
56 #include "drive-cmdline-options.h"
57 #include "drive-resources.h"
58 #include "drive-sound.h"
59 #include "drive.h"
60 #include "fliplist.h"
61 #include "fsdevice.h"
62 #include "gfxoutput.h"
63 #include "iecdrive.h"
64 #include "init.h"
65 #include "joyport.h"
66 #include "joystick.h"
67 #include "kbdbuf.h"
68 #include "keyboard.h"
69 #include "log.h"
70 #include "machine-drive.h"
71 #include "machine-printer.h"
72 #include "machine-video.h"
73 #include "machine.h"
74 #include "maincpu.h"
75 #include "mem.h"
76 #include "monitor.h"
77 #include "network.h"
78 #include "paperclip64.h"
79 #include "parallel.h"
80 #include "printer.h"
81 #include "resources.h"
82 #include "rs232drv.h"
83 #include "sampler.h"
84 #include "sampler2bit.h"
85 #include "sampler4bit.h"
86 #include "screenshot.h"
87 #include "serial.h"
88 #include "sid-cmdline-options.h"
89 #include "sid-resources.h"
90 #include "sid.h"
91 #include "snapshot.h"
92 #include "sound.h"
93 #include "tape.h"
94 #include "tapeport.h"
95 #include "tpi.h"
96 #include "traps.h"
97 #include "types.h"
98 #include "vice-event.h"
99 #include "vicii.h"
100 #include "vicii-resources.h"
101 #include "video.h"
102 #include "video-sound.h"
103 #include "vsync.h"
104 
105 #ifdef HAVE_MOUSE
106 #include "mouse.h"
107 #endif
108 
109 
110 /** \brief  Delay in seconds before pasting -keybuf argument into the buffer
111  */
112 #define KBDBUF_ALARM_DELAY   8
113 
114 
115 machine_context_t machine_context;
116 
117 const char machine_name[] = "CBM-II";
118 int machine_class = VICE_MACHINE_CBM5x0;
119 
120 static void machine_vsync_hook(void);
121 
122 #define C500_POWERLINE_CYCLES_PER_IRQ (C500_PAL_CYCLES_PER_RFSH)
123 
124 static log_t cbm2_log = LOG_ERR;
125 static machine_timing_t machine_timing;
126 
127 /* FIXME: add different keyboard types */
machine_get_keyboard_type(void)128 int machine_get_keyboard_type(void)
129 {
130 #if 0
131     int type;
132     if (resources_get_int("KeyboardType", &type) < 0) {
133         return 0;
134     }
135     return type;
136 #endif
137     return 0;
138 }
139 
machine_get_keyboard_type_name(int type)140 char *machine_get_keyboard_type_name(int type)
141 {
142     return NULL; /* return 0 if no different types exist */
143 }
144 
145 /* return number of available keyboard types for this machine */
machine_get_num_keyboard_types(void)146 int machine_get_num_keyboard_types(void)
147 {
148     return 1;
149 }
150 
machine_get_keyboard_info_list(void)151 kbdtype_info_t *machine_get_keyboard_info_list(void)
152 {
153     return NULL; /* return 0 if no different types exist */
154 }
155 
156 
157 /* ------------------------------------------------------------------------- */
158 
159 static joyport_port_props_t control_port_1 =
160 {
161     "Control port 1",
162     1,                      /* has a potentiometer connected to this port */
163     0,                      /* officially has lightpen support on this port,
164                                but no lightpen support is in the cbm5x0 code */
165     1                       /* port is always active */
166 };
167 
168 static joyport_port_props_t control_port_2 =
169 {
170     "Control port 2",
171     1,                      /* has a potentiometer connected to this port */
172     0,                      /* has NO lightpen support on this port */
173     1                       /* port is always active */
174 };
175 
init_joyport_ports(void)176 static int init_joyport_ports(void)
177 {
178     if (joyport_port_register(JOYPORT_1, &control_port_1) < 0) {
179         return -1;
180     }
181     return joyport_port_register(JOYPORT_2, &control_port_2);
182 }
183 
184 /* CBM-II-specific resource initialization.  This is called before initializing
185    the machine itself with `machine_init()'.  */
machine_resources_init(void)186 int machine_resources_init(void)
187 {
188     if (traps_resources_init() < 0) {
189         init_resource_fail("traps");
190         return -1;
191     }
192     if (cbm2_resources_init() < 0) {
193         init_resource_fail("cbm2");
194         return -1;
195     }
196     if (cartio_resources_init() < 0) {
197         init_resource_fail("cartio");
198         return -1;
199     }
200     if (cartridge_resources_init() < 0) {
201         init_resource_fail("cartridge");
202         return -1;
203     }
204     if (vicii_resources_init() < 0) {
205         init_resource_fail("vicii");
206         return -1;
207     }
208     if (sid_resources_init() < 0) {
209         init_resource_fail("sid");
210         return -1;
211     }
212     if (drive_resources_init() < 0) {
213         init_resource_fail("drive");
214         return -1;
215     }
216     /*
217      * This needs to be called before tapeport_resources_init(), otherwise
218      * the tapecart will fail to initialize due to the Datasette resource
219      * appearing after the Tapecart resources
220      */
221     if (datasette_resources_init() < 0) {
222         init_resource_fail("datasette");
223         return -1;
224     }
225     if (tapeport_resources_init() < 0) {
226         init_resource_fail("tapeport");
227         return -1;
228     }
229     if (acia1_resources_init() < 0) {
230         init_resource_fail("acia1");
231         return -1;
232     }
233     if (rs232drv_resources_init() < 0) {
234         init_resource_fail("rs232drv");
235         return -1;
236     }
237     if (printer_resources_init() < 0) {
238         init_resource_fail("printer");
239         return -1;
240     }
241     if (printer_userport_resources_init() < 0) {
242         init_resource_fail("userport printer");
243         return -1;
244     }
245     if (init_joyport_ports() < 0) {
246         init_resource_fail("joyport ports");
247         return -1;
248     }
249     if (joyport_resources_init() < 0) {
250         init_resource_fail("joyport devices");
251         return -1;
252     }
253     if (joyport_sampler2bit_resources_init() < 0) {
254         init_resource_fail("joyport 2bit sampler");
255         return -1;
256     }
257     if (joyport_sampler4bit_resources_init() < 0) {
258         init_resource_fail("joyport 4bit sampler");
259         return -1;
260     }
261     if (joyport_bbrtc_resources_init() < 0) {
262         init_resource_fail("joyport bbrtc");
263         return -1;
264     }
265     if (joyport_paperclip64_resources_init() < 0) {
266         init_resource_fail("joyport paperclip64 dongle");
267         return -1;
268     }
269     if (joystick_resources_init() < 0) {
270         init_resource_fail("joystick");
271         return -1;
272     }
273     if (gfxoutput_resources_init() < 0) {
274         init_resource_fail("gfxoutput");
275         return -1;
276     }
277     if (sampler_resources_init() < 0) {
278         init_resource_fail("samplerdrv");
279         return -1;
280     }
281     if (fliplist_resources_init() < 0) {
282         init_resource_fail("flip list");
283         return -1;
284     }
285     if (file_system_resources_init() < 0) {
286         init_resource_fail("file system");
287         return -1;
288     }
289     /* Initialize file system device-specific resources.  */
290     if (fsdevice_resources_init() < 0) {
291         init_resource_fail("file system device");
292         return -1;
293     }
294     if (disk_image_resources_init() < 0) {
295         init_resource_fail("disk image");
296         return -1;
297     }
298     if (event_resources_init() < 0) {
299         init_resource_fail("event");
300         return -1;
301     }
302     if (kbdbuf_resources_init() < 0) {
303         init_resource_fail("Keyboard");
304         return -1;
305     }
306     if (autostart_resources_init() < 0) {
307         init_resource_fail("autostart");
308         return -1;
309     }
310 #ifdef HAVE_NETWORK
311     if (network_resources_init() < 0) {
312         init_resource_fail("network");
313         return -1;
314     }
315 #endif
316 #ifdef DEBUG
317     if (debug_resources_init() < 0) {
318         init_resource_fail("debug");
319         return -1;
320     }
321 #endif
322 #ifdef HAVE_MOUSE
323     if (mouse_resources_init() < 0) {
324         init_resource_fail("mouse");
325         return -1;
326     }
327 /* FIXME: add lightpen support for xcbm5x0 */
328 #if 0
329     if (lightpen_resources_init() < 0) {
330         init_resource_fail("lightpen");
331         return -1;
332     }
333 #endif
334 #endif
335     if (debugcart_resources_init() < 0) {
336         init_resource_fail("debug cart");
337         return -1;
338     }
339     return 0;
340 }
341 
machine_resources_shutdown(void)342 void machine_resources_shutdown(void)
343 {
344     cbm2_resources_shutdown();
345     rs232drv_resources_shutdown();
346     printer_resources_shutdown();
347     drive_resources_shutdown();
348     fsdevice_resources_shutdown();
349     disk_image_resources_shutdown();
350     sampler_resources_shutdown();
351     cartio_shutdown();
352     joyport_bbrtc_resources_shutdown();
353     tapeport_resources_shutdown();
354     debugcart_resources_shutdown();
355     cartridge_resources_shutdown();
356 }
357 
358 /* CBM-II-specific command-line option initialization.  */
machine_cmdline_options_init(void)359 int machine_cmdline_options_init(void)
360 {
361     if (traps_cmdline_options_init() < 0) {
362         init_cmdline_options_fail("traps");
363         return -1;
364     }
365     if (cbm2_cmdline_options_init() < 0) {
366         init_cmdline_options_fail("cbm2");
367         return -1;
368     }
369     if (cartio_cmdline_options_init() < 0) {
370         init_cmdline_options_fail("cartio");
371         return -1;
372     }
373     if (cartridge_cmdline_options_init() < 0) {
374         init_cmdline_options_fail("cartridge");
375         return -1;
376     }
377     if (vicii_cmdline_options_init() < 0) {
378         init_cmdline_options_fail("vicii");
379         return -1;
380     }
381     if (sid_cmdline_options_init(SIDTYPE_SID) < 0) {
382         init_cmdline_options_fail("sid");
383         return -1;
384     }
385     if (drive_cmdline_options_init() < 0) {
386         init_cmdline_options_fail("drive");
387         return -1;
388     }
389     if (tapeport_cmdline_options_init() < 0) {
390         init_cmdline_options_fail("tapeport");
391         return -1;
392     }
393     if (datasette_cmdline_options_init() < 0) {
394         init_cmdline_options_fail("datasette");
395         return -1;
396     }
397     if (acia1_cmdline_options_init() < 0) {
398         init_cmdline_options_fail("acia1");
399         return -1;
400     }
401     if (rs232drv_cmdline_options_init() < 0) {
402         init_cmdline_options_fail("rs232drv");
403         return -1;
404     }
405     if (printer_cmdline_options_init() < 0) {
406         init_cmdline_options_fail("printer");
407         return -1;
408     }
409     if (printer_userport_cmdline_options_init() < 0) {
410         init_cmdline_options_fail("userport printer");
411         return -1;
412     }
413     if (joyport_cmdline_options_init() < 0) {
414         init_cmdline_options_fail("joyport");
415         return -1;
416     }
417     if (joyport_bbrtc_cmdline_options_init() < 0) {
418         init_cmdline_options_fail("bbrtc");
419         return -1;
420     }
421     if (joystick_cmdline_options_init() < 0) {
422         init_cmdline_options_fail("joystick");
423         return -1;
424     }
425     if (gfxoutput_cmdline_options_init() < 0) {
426         init_cmdline_options_fail("gfxoutput");
427         return -1;
428     }
429     if (sampler_cmdline_options_init() < 0) {
430         init_cmdline_options_fail("samplerdrv");
431         return -1;
432     }
433     if (fliplist_cmdline_options_init() < 0) {
434         init_cmdline_options_fail("flip list");
435         return -1;
436     }
437     if (file_system_cmdline_options_init() < 0) {
438         init_cmdline_options_fail("attach");
439         return -1;
440     }
441     if (fsdevice_cmdline_options_init() < 0) {
442         init_cmdline_options_fail("file system");
443         return -1;
444     }
445     if (disk_image_cmdline_options_init() < 0) {
446         init_cmdline_options_fail("disk image");
447         return -1;
448     }
449     if (event_cmdline_options_init() < 0) {
450         init_cmdline_options_fail("event");
451         return -1;
452     }
453     if (kbdbuf_cmdline_options_init() < 0) {
454         init_cmdline_options_fail("keyboard");
455         return -1;
456     }
457     if (autostart_cmdline_options_init() < 0) {
458         init_resource_fail("autostart");
459         return -1;
460     }
461 #ifdef HAVE_NETWORK
462     if (network_cmdline_options_init() < 0) {
463         init_cmdline_options_fail("network");
464         return -1;
465     }
466 #endif
467 #ifdef DEBUG
468     if (debug_cmdline_options_init() < 0) {
469         init_cmdline_options_fail("debug");
470         return -1;
471     }
472 #endif
473 #ifdef HAVE_MOUSE
474     if (mouse_cmdline_options_init() < 0) {
475         init_cmdline_options_fail("mouse");
476         return -1;
477     }
478 #endif
479     if (debugcart_cmdline_options_init() < 0) {
480         init_cmdline_options_fail("debug cart");
481         return -1;
482     }
483     return 0;
484 }
485 
486 /* ------------------------------------------------------------------------- */
487 /* provide the 50(?)Hz IRQ signal for the standard IRQ */
488 
489 #define SIGNAL_VERT_BLANK_OFF tpicore_set_int(machine_context.tpi1, 0, 1);
490 
491 #define SIGNAL_VERT_BLANK_ON  tpicore_set_int(machine_context.tpi1, 0, 0);
492 
493 /* ------------------------------------------------------------------------- */
494 /* for the C500 there is a powerline IRQ... */
495 
496 static alarm_t *c500_powerline_clk_alarm = NULL;
497 static CLOCK c500_powerline_clk = 0;
498 
c500_powerline_clk_alarm_handler(CLOCK offset,void * data)499 static void c500_powerline_clk_alarm_handler(CLOCK offset, void *data)
500 {
501     c500_powerline_clk += C500_POWERLINE_CYCLES_PER_IRQ;
502 
503     SIGNAL_VERT_BLANK_OFF
504 
505     alarm_set(c500_powerline_clk_alarm, c500_powerline_clk);
506 
507     SIGNAL_VERT_BLANK_ON
508 }
509 
c500_powerline_clk_overflow_callback(CLOCK sub,void * data)510 static void c500_powerline_clk_overflow_callback(CLOCK sub, void *data)
511 {
512     c500_powerline_clk -= sub;
513 }
514 
515 
516 /*
517  * C500 extra data (state of 50Hz clk)
518  */
519 #define C500DATA_DUMP_VER_MAJOR   0
520 #define C500DATA_DUMP_VER_MINOR   0
521 
522 /*
523  * DWORD        IRQCLK          CPU clock ticks until next 50 Hz IRQ
524  *
525  */
526 
527 static const char module_name[] = "C500DATA";
528 
cbm2_c500_snapshot_write_module(snapshot_t * p)529 int cbm2_c500_snapshot_write_module(snapshot_t *p)
530 {
531     snapshot_module_t *m;
532 
533     m = snapshot_module_create(p, module_name, C500DATA_DUMP_VER_MAJOR,
534                                C500DATA_DUMP_VER_MINOR);
535     if (m == NULL) {
536         return -1;
537     }
538 
539     SMW_DW(m, c500_powerline_clk - maincpu_clk);
540 
541     snapshot_module_close(m);
542 
543     return 0;
544 }
545 
cbm2_c500_snapshot_read_module(snapshot_t * p)546 int cbm2_c500_snapshot_read_module(snapshot_t *p)
547 {
548     uint8_t vmajor, vminor;
549     snapshot_module_t *m;
550     uint32_t dword;
551 
552     m = snapshot_module_open(p, module_name, &vmajor, &vminor);
553     if (m == NULL) {
554         return -1;
555     }
556 
557     if (vmajor != C500DATA_DUMP_VER_MAJOR) {
558         snapshot_module_close(m);
559         return -1;
560     }
561 
562     SMR_DW(m, &dword);
563     c500_powerline_clk = maincpu_clk + dword;
564     alarm_set(c500_powerline_clk_alarm, c500_powerline_clk);
565 
566     snapshot_module_close(m);
567 
568     return 0;
569 }
570 
571 /* ------------------------------------------------------------------------- */
572 
cbm2_monitor_init(void)573 static void cbm2_monitor_init(void)
574 {
575     unsigned int dnr;
576     monitor_cpu_type_t asm6502;
577     monitor_interface_t *drive_interface_init[DRIVE_NUM];
578     monitor_cpu_type_t *asmarray[2];
579 
580     asmarray[0] = &asm6502;
581     asmarray[1] = NULL;
582 
583     asm6502_init(&asm6502);
584 
585     for (dnr = 0; dnr < DRIVE_NUM; dnr++) {
586         drive_interface_init[dnr] = drive_cpu_monitor_interface_get(dnr);
587     }
588 
589     /* Initialize the monitor.  */
590     monitor_init(maincpu_monitor_interface_get(), drive_interface_init,
591                  asmarray);
592 }
593 
machine_setup_context(void)594 void machine_setup_context(void)
595 {
596     cia1_setup_context(&machine_context);
597     tpi1_setup_context(&machine_context);
598     tpi2_setup_context(&machine_context);
599     machine_printer_setup_context(&machine_context);
600 }
601 
602 /* CBM-II-specific initialization.  */
machine_specific_init(void)603 int machine_specific_init(void)
604 {
605     cbm2_log = log_open("CBM2");
606 
607     cbm2_init_ok = 1;
608 
609     event_init();
610 
611     /* Setup trap handling - must be before mem_load() */
612     traps_init();
613 
614     if (mem_load() < 0) {
615         return -1;
616     }
617 
618     gfxoutput_init();
619 
620 #ifdef HAVE_MOUSE
621     /* Initialize mouse support (if present).  */
622     mouse_init();
623 
624 #if 0
625     /* Initialize lightpen support and register VICII callbacks */
626     lightpen_init();
627     lightpen_register_timing_callback(vicii_lightpen_timing, 0);
628     lightpen_register_trigger_callback(vicii_trigger_light_pen);
629 #endif
630 #endif
631 
632     rs232drv_init();
633 
634     /* initialize print devices */
635     printer_init();
636 
637     /* Pre-init CBM-II-specific parts of the menus before vicii_init()
638        creates a canvas window with a menubar at the top. */
639     if (!console_mode) {
640         cbm5x0ui_init_early();
641     }
642 
643     if (vicii_init(VICII_STANDARD) == NULL) {
644         return -1;
645     }
646     /*
647     c500_set_phi1_bank(15);
648     c500_set_phi2_bank(15);
649     */
650 
651     c500_powerline_clk_alarm = alarm_new(maincpu_alarm_context,
652                                          "C500PowerlineClk",
653                                          c500_powerline_clk_alarm_handler,
654                                          NULL);
655     clk_guard_add_callback(maincpu_clk_guard,
656                            c500_powerline_clk_overflow_callback, NULL);
657     machine_timing.cycles_per_sec = C500_PAL_CYCLES_PER_SEC;
658     machine_timing.rfsh_per_sec = C500_PAL_RFSH_PER_SEC;
659     machine_timing.cycles_per_rfsh = C500_PAL_CYCLES_PER_RFSH;
660 
661     cia1_init(machine_context.cia1);
662     acia1_init();
663     tpi1_init(machine_context.tpi1);
664     tpi2_init(machine_context.tpi2);
665 
666     /* Initialize the datasette emulation.  */
667     datasette_init();
668 
669     /* Fire up the hardware-level 1541 emulation.  */
670     drive_init();
671 
672     disk_image_init();
673 
674     cbm2_monitor_init();
675 
676     /* Initialize vsync and register our hook function.  */
677     vsync_init(machine_vsync_hook);
678     vsync_set_machine_parameter(machine_timing.rfsh_per_sec,
679                                 machine_timing.cycles_per_sec);
680 
681     /* Initialize native sound chip */
682     sid_sound_chip_init();
683 
684     drive_sound_init();
685     video_sound_init();
686 
687     /* Initialize sound.  Notice that this does not really open the audio
688        device yet.  */
689     sound_init(machine_timing.cycles_per_sec, machine_timing.cycles_per_rfsh);
690 
691     /* Initialize the CBM-II-specific part of the UI.  */
692     if (!console_mode) {
693         cbm5x0ui_init();
694     }
695 
696     if (!video_disabled_mode) {
697         joystick_init();
698     }
699 
700     cbm2iec_init();
701 
702     machine_drive_stub();
703 
704     /* Initialize the CBM5x0-specific I/O */
705     cbm5x0io_init();
706 
707     return 0;
708 }
709 
710 /* CBM-II-specific initialization.  */
machine_specific_reset(void)711 void machine_specific_reset(void)
712 {
713     int delay;      /* delay in seconds for the kbduf_init() call */
714 
715     ciacore_reset(machine_context.cia1);
716     tpicore_reset(machine_context.tpi1);
717     tpicore_reset(machine_context.tpi2);
718     acia1_reset();
719 
720     sid_reset();
721 
722     c500_powerline_clk = maincpu_clk + C500_POWERLINE_CYCLES_PER_IRQ;
723     alarm_set(c500_powerline_clk_alarm, c500_powerline_clk);
724     vicii_reset();
725 
726     printer_reset();
727 
728     rs232drv_reset();
729 
730     drive_reset();
731     datasette_reset();
732 
733     mem_reset();
734 
735     /* Initialize keyboard buffer.
736        This appears to work but doesn't account for banking
737      */
738     switch (ramsize) {
739         case 64:
740             delay = 8;
741             break;
742         case 128:
743             delay = 12;
744             break;
745         case 256:
746             delay = 20;
747             break;
748         case 512:
749             delay = 31;
750             break;
751         case 1024:
752             delay = 58;
753             break;
754         default:
755             /* invalid ramsize */
756             delay = 1;
757             break;
758     }
759     kbdbuf_init(0x03ab, 0x00d1, 10,
760             (CLOCK)(machine_timing.rfsh_per_sec *
761                 machine_timing.cycles_per_rfsh * delay));
762 
763 
764     sampler_reset();
765 }
766 
machine_specific_powerup(void)767 void machine_specific_powerup(void)
768 {
769 }
770 
machine_specific_shutdown(void)771 void machine_specific_shutdown(void)
772 {
773     /* and the tape */
774     tape_image_detach_internal(1);
775 
776     ciacore_shutdown(machine_context.cia1);
777     tpicore_shutdown(machine_context.tpi1);
778     tpicore_shutdown(machine_context.tpi2);
779 
780 #ifdef HAVE_MOUSE
781     mouse_shutdown();
782 #endif
783 
784     /* close the video chip(s) */
785     vicii_shutdown();
786 
787     if (!console_mode) {
788         cbm5x0ui_shutdown();
789     }
790 }
791 
machine_handle_pending_alarms(int num_write_cycles)792 void machine_handle_pending_alarms(int num_write_cycles)
793 {
794 }
795 
796 /* ------------------------------------------------------------------------- */
797 
798 /* This hook is called at the end of every frame.  */
machine_vsync_hook(void)799 static void machine_vsync_hook(void)
800 {
801     CLOCK sub;
802 
803     drive_vsync_hook();
804 
805     autostart_advance();
806 
807     screenshot_record();
808 
809     sub = clk_guard_prevent_overflow(maincpu_clk_guard);
810 
811     /* The drive has to deal both with our overflowing and its own one, so
812        it is called even when there is no overflowing in the main CPU.  */
813     drive_cpu_prevent_clk_overflow_all(sub);
814 }
815 
816 /* Dummy - no restore key.  */
machine_set_restore_key(int v)817 void machine_set_restore_key(int v)
818 {
819 }
820 
machine_has_restore_key(void)821 int machine_has_restore_key(void)
822 {
823     return 0;
824 }
825 
826 /* ------------------------------------------------------------------------- */
827 
machine_get_cycles_per_second(void)828 long machine_get_cycles_per_second(void)
829 {
830     return machine_timing.cycles_per_sec;
831 }
832 
machine_get_cycles_per_frame(void)833 long machine_get_cycles_per_frame(void)
834 {
835     return machine_timing.cycles_per_rfsh;
836 }
837 
machine_get_line_cycle(unsigned int * line,unsigned int * cycle,int * half_cycle)838 void machine_get_line_cycle(unsigned int *line, unsigned int *cycle, int *half_cycle)
839 {
840     *line = (unsigned int)((maincpu_clk) / machine_timing.cycles_per_line
841                            % machine_timing.screen_lines);
842 
843     *cycle = (unsigned int)((maincpu_clk) % machine_timing.cycles_per_line);
844 
845     *half_cycle = (int)-1;
846 }
847 
machine_change_timing(int timeval,int border_mode)848 void machine_change_timing(int timeval, int border_mode)
849 {
850     /* log_message(LOG_DEFAULT, "machine_change_timing_c500 %d", timeval); */
851 
852     switch (timeval) {
853         case MACHINE_SYNC_PAL:
854             machine_timing.cycles_per_sec = C500_PAL_CYCLES_PER_SEC;
855             machine_timing.cycles_per_rfsh = C500_PAL_CYCLES_PER_RFSH;
856             machine_timing.rfsh_per_sec = C500_PAL_RFSH_PER_SEC;
857             machine_timing.cycles_per_line = C500_PAL_CYCLES_PER_LINE;
858             machine_timing.screen_lines = C500_PAL_SCREEN_LINES;
859             machine_timing.power_freq = 50;
860             break;
861         case MACHINE_SYNC_NTSC:
862             machine_timing.cycles_per_sec = C500_NTSC_CYCLES_PER_SEC;
863             machine_timing.cycles_per_rfsh = C500_NTSC_CYCLES_PER_RFSH;
864             machine_timing.rfsh_per_sec = C500_NTSC_RFSH_PER_SEC;
865             machine_timing.cycles_per_line = C500_NTSC_CYCLES_PER_LINE;
866             machine_timing.screen_lines = C500_NTSC_SCREEN_LINES;
867             machine_timing.power_freq = 60;
868             break;
869         default:
870             log_error(LOG_DEFAULT, "Unknown machine timing.");
871     }
872 
873     debug_set_machine_parameter(machine_timing.cycles_per_line,
874                                 machine_timing.screen_lines);
875     drive_set_machine_parameter(machine_timing.cycles_per_sec);
876 #ifdef HAVE_MOUSE
877     neos_mouse_set_machine_parameter(machine_timing.cycles_per_sec);
878 #endif
879     clk_guard_set_clk_base(maincpu_clk_guard, machine_timing.cycles_per_rfsh);
880 
881     vicii_change_timing(&machine_timing, border_mode);
882     cia1_set_timing(machine_context.cia1, machine_timing.cycles_per_sec, machine_timing.power_freq);
883 }
884 
885 /* Set the screen refresh rate, as this is variable in the CRTC */
machine_set_cycles_per_frame(long cpf)886 void machine_set_cycles_per_frame(long cpf)
887 {
888     double i, f;
889 
890     machine_timing.cycles_per_rfsh = cpf;
891     machine_timing.rfsh_per_sec = ((double)machine_timing.cycles_per_sec)
892                                   / ((double)cpf);
893 
894     f = modf(machine_timing.rfsh_per_sec, &i) * 1000;
895     log_message(cbm2_log, "cycles per frame set to %ld, refresh to %d.%03dHz",
896                 cpf, (int)i, (int)f);
897 
898     vsync_set_machine_parameter(machine_timing.rfsh_per_sec,
899                                 machine_timing.cycles_per_sec);
900 }
901 
902 /* ------------------------------------------------------------------------- */
903 
machine_write_snapshot_to_stream(snapshot_stream_t * stream,int save_roms,int save_disks,int event_mode)904 int machine_write_snapshot_to_stream(snapshot_stream_t *stream, int save_roms,
905                                      int save_disks, int event_mode)
906 {
907     return cbm2_snapshot_write_to_stream(stream, save_roms, save_disks,
908                                           event_mode);
909 }
910 
machine_read_snapshot_from_stream(snapshot_stream_t * stream,int event_mode)911 int machine_read_snapshot_from_stream(snapshot_stream_t *stream, int event_mode)
912 {
913     return cbm2_snapshot_read_from_stream(stream, event_mode);
914 }
915 
machine_write_snapshot(const char * name,int save_roms,int save_disks,int event_mode)916 int machine_write_snapshot(const char *name, int save_roms, int save_disks,
917                            int event_mode)
918 {
919     return cbm2_snapshot_write(name, save_roms, save_disks, event_mode);
920 }
921 
machine_read_snapshot(const char * name,int event_mode)922 int machine_read_snapshot(const char *name, int event_mode)
923 {
924     return cbm2_snapshot_read(name, event_mode);
925 }
926 
927 /* ------------------------------------------------------------------------- */
928 
machine_autodetect_psid(const char * name)929 int machine_autodetect_psid(const char *name)
930 {
931     return -1;
932 }
933 
machine_screenshot(screenshot_t * screenshot,struct video_canvas_s * canvas)934 int machine_screenshot(screenshot_t *screenshot, struct video_canvas_s *canvas)
935 {
936     if (canvas == vicii_get_canvas()) {
937         vicii_screenshot(screenshot);
938         return 0;
939     }
940     return -1;
941 }
942 
machine_canvas_async_refresh(struct canvas_refresh_s * refresh,struct video_canvas_s * canvas)943 int machine_canvas_async_refresh(struct canvas_refresh_s *refresh,
944                                  struct video_canvas_s *canvas)
945 {
946     if (canvas == vicii_get_canvas()) {
947         vicii_async_refresh(refresh);
948         return 0;
949     }
950     return -1;
951 }
952 
953 /*-----------------------------------------------------------------------*/
954 
machine_diskcontents_bus_read(unsigned int unit)955 struct image_contents_s *machine_diskcontents_bus_read(unsigned int unit)
956 {
957     return NULL;
958 }
959 
machine_tape_type_default(void)960 uint8_t machine_tape_type_default(void)
961 {
962     return TAPE_CAS_TYPE_BAS;
963 }
964 
machine_tape_behaviour(void)965 uint8_t machine_tape_behaviour(void)
966 {
967     return TAPE_BEHAVIOUR_NORMAL;
968 }
969 
machine_addr_in_ram(unsigned int addr)970 int machine_addr_in_ram(unsigned int addr)
971 {
972     /* FIXME are these correct? */
973     return (addr < 0xe000 && !(addr >= 0xa000 && addr < 0xc000)) ? 1 : 0;
974 }
975 
machine_get_name(void)976 const char *machine_get_name(void)
977 {
978     return "CBM-II-5x0";
979 }
980