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