fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/macplus/macplus.c *
7 * Created: 2007-04-15 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2007-2024 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "main.h"
24#include "hook.h"
25#include "hotkey.h"
26#include "iwm.h"
27#include "keyboard.h"
28#include "macplus.h"
29#include "mem.h"
30#include "msg.h"
31#include "rtc.h"
32#include "scsi.h"
33#include "serial.h"
34#include "sony.h"
35#include "sound.h"
36#include "video.h"
37
38#include <string.h>
39
40#include <chipset/e6522.h>
41#include <chipset/e8530.h>
42
43#include <cpu/e68000/e68000.h>
44
45#include <devices/memory.h>
46#include <devices/nvram.h>
47
48#include <drivers/block/block.h>
49
50#include <drivers/video/terminal.h>
51
52#include <lib/brkpt.h>
53#include <lib/inidsk.h>
54#include <lib/iniram.h>
55#include <lib/initerm.h>
56#include <lib/load.h>
57#include <lib/log.h>
58#include <lib/sysdep.h>
59
60#include <libini/libini.h>
61
62
63/* The CPU is synchronized with real time MAC_CPU_SYNC times per seconds */
64#define MAC_CPU_SYNC 250
65
66#ifdef PCE_HOST_WINDOWS
67#define MAC_CPU_SLEEP 20000
68#else
69#define MAC_CPU_SLEEP 10000
70#endif
71
72
73static
74unsigned char par_classic_pwm[64] = {
75 0x00, 0x01, 0x3b, 0x02, 0x3c, 0x28, 0x36, 0x03,
76 0x3d, 0x20, 0x31, 0x29, 0x37, 0x13, 0x23, 0x04,
77 0x3e, 0x34, 0x1e, 0x21, 0x32, 0x0c, 0x0e, 0x2a,
78 0x38, 0x10, 0x1b, 0x14, 0x24, 0x17, 0x2c, 0x05,
79 0x3f, 0x3a, 0x27, 0x35, 0x1f, 0x30, 0x12, 0x22,
80 0x33, 0x1d, 0x0b, 0x0d, 0x0f, 0x1a, 0x16, 0x2b,
81 0x39, 0x26, 0x2f, 0x11, 0x1c, 0x0a, 0x19, 0x15,
82 0x25, 0x2e, 0x09, 0x18, 0x2d, 0x08, 0x07, 0x06
83};
84
85static
86void mac_classic_set_pwm (macplus_t *sim, const unsigned char *buf, unsigned cnt)
87{
88 unsigned i, v;
89
90 v = 0;
91
92 for (i = 0; i < cnt; i++) {
93 v += par_classic_pwm[buf[0] & 0x3f];
94 }
95
96 v = v / cnt;
97
98 if (v < 1) {
99 v = 1;
100 }
101 else if (v > 31) {
102 v = 31;
103 }
104
105 v = 32 + (223 * (30 - (v - 1)) + 15) / 30;
106
107 if ((sim->video != NULL) && (sim->video->brightness != v)) {
108 mac_video_set_brightness (sim->video, v);
109 }
110}
111
112static
113void mac_interrupt_check (macplus_t *sim)
114{
115 unsigned i;
116 unsigned val;
117
118 val = sim->intr >> 1;
119
120 i = 0;
121 while (val != 0) {
122 i += 1;
123 val = val >> 1;
124 }
125
126#ifdef DEBUG_INT
127 mac_log_deb ("interrupt level %u\n", i);
128#endif
129
130 e68_interrupt (sim->cpu, i);
131}
132
133void mac_interrupt (macplus_t *sim, unsigned level, int val)
134{
135 if (val) {
136 sim->intr |= (1U << level);
137 }
138 else {
139 sim->intr &= ~(1U << level);
140 }
141
142 mac_interrupt_check (sim);
143}
144
145static
146void mac_interrupt_via (void *ext, unsigned char val)
147{
148 macplus_t *sim = ext;
149
150 if (val) {
151 sim->intr_scsi_via |= 1;
152 }
153 else {
154 sim->intr_scsi_via &= ~1;
155 }
156
157 mac_interrupt (ext, 1, sim->intr_scsi_via);
158}
159
160static
161void mac_interrupt_scsi (void *ext, unsigned char val)
162{
163 macplus_t *sim = ext;
164
165 if (sim->via_port_b & 0x40) {
166 val = 0;
167 }
168 else {
169 val = (val != 0);
170 }
171
172 if (val) {
173 sim->intr_scsi_via |= 2;
174 }
175 else {
176 sim->intr_scsi_via &= ~2;
177 }
178
179 mac_interrupt (sim, 1, sim->intr_scsi_via);
180}
181
182static
183void mac_interrupt_scc (void *ext, unsigned char val)
184{
185 mac_interrupt (ext, 2, val);
186}
187
188static
189void mac_interrupt_vbi (void *ext, unsigned char val)
190{
191 unsigned i;
192 unsigned char pbuf[370];
193 macplus_t *sim = ext;
194
195 if (val) {
196 e6522_set_ca1_inp (&sim->via, 0);
197 e6522_set_ca1_inp (&sim->via, 1);
198
199 mac_sound_vbl (&sim->sound);
200
201 for (i = 0; i < 370; i++) {
202 pbuf[i] = mem_get_uint8 (sim->mem, sim->sbuf1 + i + 1);
203 }
204
205 if (sim->model & PCE_MAC_CLASSIC) {
206 mac_classic_set_pwm (sim, pbuf, 370);
207 }
208 else {
209 mac_iwm_set_pwm (&sim->iwm, pbuf, 370);
210 }
211 }
212}
213
214static
215void mac_interrupt_sony_check (macplus_t *sim)
216{
217 unsigned long a7;
218
219#ifdef DEBUG_SONY
220 mac_log_deb ("sony: check\n");
221#endif
222 if (e68_get_iml (sim->cpu) == 7) {
223#ifdef DEBUG_SONY
224 mac_log_deb ("sony: check aborted (iml=7)\n");
225#endif
226 return;
227 }
228
229 a7 = e68_get_areg32 (sim->cpu, 7);
230 e68_set_mem32 (sim->cpu, a7 - 4, e68_get_pc (sim->cpu));
231 e68_set_areg32 (sim->cpu, 7, a7 - 4);
232
233 e68_set_pc_prefetch (sim->cpu, sim->sony.check_addr);
234}
235
236void mac_interrupt_osi (void *ext, unsigned char val)
237{
238 macplus_t *sim = ext;
239
240 if (val) {
241 if (mac_sony_check (&sim->sony)) {
242 mac_interrupt_sony_check (sim);
243 }
244
245 e6522_set_ca2_inp (&sim->via, 0);
246 e6522_set_ca2_inp (&sim->via, 1);
247 }
248}
249
250static
251void mac_set_reset (void *ext, unsigned char val)
252{
253 if (val == 0) {
254 return;
255 }
256
257 mac_reset (ext);
258}
259
260static
261void mac_ram_write (void *ext, uint32_t addr, unsigned size)
262{
263 macplus_t *sim = ext;
264
265 if (sim->video == NULL) {
266 return;
267 }
268
269 if ((addr + size) > sim->video->vbuf_addr &&
270 addr < (sim->video->vbuf_addr + sim->video->vbuf_size)) {
271 mac_video_set_dirty (sim->video);
272 }
273}
274
275static
276void mac_set_vbuf (macplus_t *sim, unsigned long addr)
277{
278 unsigned char *vbuf;
279 unsigned long vbuf_size;
280 mem_blk_t *blk;
281
282 vbuf_size = ((unsigned long)(sim->video->w + 7) / 8) * sim->video->h;
283
284 if (addr < mem_blk_get_size (sim->ram)) {
285 vbuf = mem_blk_get_data (sim->ram) + addr;
286 }
287 else {
288 blk = mem_get_blk (sim->mem, addr);
289
290 if (blk == NULL) {
291 mac_video_set_vbuf (sim->video, NULL);
292 mac_video_set_vbuf_addr (sim->video, 0, 0);
293 return;
294 }
295
296 vbuf = mem_blk_get_data (blk);
297 vbuf += mem_blk_get_addr (blk) - sim->vbuf1;
298 }
299
300 mac_video_set_vbuf (sim->video, vbuf);
301 mac_video_set_vbuf_addr (sim->video, addr, vbuf_size);
302}
303
304static
305void mac_check_mouse (macplus_t *sim)
306{
307 if (sim->adb != NULL) {
308 return;
309 }
310
311 if ((sim->mouse_delta_x <= -2) || (sim->mouse_delta_x >= 2)) {
312 if (sim->dcd_a) {
313 sim->via_port_b &= ~0x10;
314 }
315 else {
316 sim->via_port_b |= 0x10;
317 }
318
319 if (sim->mouse_delta_x > 0) {
320 sim->via_port_b ^= 0x10;
321 sim->mouse_delta_x -= 2;
322 }
323 else {
324 sim->mouse_delta_x += 2;
325 }
326
327 e6522_set_irb_inp (&sim->via, sim->via_port_b);
328 e8530_set_dcd_a (&sim->scc, sim->dcd_a);
329
330 sim->dcd_a = !sim->dcd_a;
331 }
332
333 if ((sim->mouse_delta_y <= -2) || (sim->mouse_delta_y >= 2)) {
334 if (sim->dcd_b) {
335 sim->via_port_b &= ~0x20;
336 }
337 else {
338 sim->via_port_b |= 0x20;
339 }
340
341 if (sim->mouse_delta_y > 0) {
342 sim->mouse_delta_y -= 2;
343 }
344 else {
345 sim->via_port_b ^= 0x20;
346 sim->mouse_delta_y += 2;
347 }
348
349 e6522_set_irb_inp (&sim->via, sim->via_port_b);
350 e8530_set_dcd_b (&sim->scc, sim->dcd_b);
351
352 sim->dcd_b = !sim->dcd_b;
353 }
354}
355
356static
357void mac_set_mouse (void *ext, int dx, int dy, unsigned but)
358{
359 macplus_t *sim = ext;
360 unsigned char old;
361
362 if (sim->pause) {
363 if (but) {
364 mac_set_pause (sim, 0);
365 }
366
367 return;
368 }
369
370 if ((sim->mouse_button ^ but) & ~but & 4) {
371 mac_set_msg (sim, "term.release", "1");
372 }
373
374 sim->mouse_button = but;
375
376 if (sim->adb_mouse != NULL) {
377 adb_mouse_move (sim->adb_mouse, but, dx, dy);
378 return;
379 }
380
381 old = sim->via_port_b;
382
383 if (but & 1) {
384 sim->via_port_b &= 0xf7;
385 }
386 else {
387 sim->via_port_b |= 0x08;
388 }
389
390 if (sim->via_port_b != old) {
391 e6522_set_irb_inp (&sim->via, sim->via_port_b);
392 }
393
394 sim->mouse_delta_x += dx;
395 sim->mouse_delta_y += dy;
396}
397
398static
399void mac_get_mouse (void *ext, int *x, int *y)
400{
401 macplus_t *sim = ext;
402
403 /* RawMouse low-memory global at 0x82c */
404 *y = (int) mem_get_uint16_be (sim->mem, 0x82c);
405 *x = (int) mem_get_uint16_be (sim->mem, 0x82e);
406}
407
408static
409void mac_set_key (void *ext, unsigned event, pce_key_t key)
410{
411 macplus_t *sim = ext;
412
413 if (event == PCE_KEY_EVENT_MAGIC) {
414 mac_set_hotkey (sim, key);
415 return;
416 }
417
418 if (sim->kbd != NULL) {
419 mac_kbd_set_key (sim->kbd, event, key);
420 }
421
422 if (sim->adb_kbd != NULL) {
423 adb_kbd_set_key (sim->adb_kbd, event, key);
424 }
425}
426
427static
428void mac_set_adb_int (void *ext, unsigned char val)
429{
430 macplus_t *sim = ext;
431
432 if (val) {
433 sim->via_port_b &= ~0x08;
434 }
435 else {
436 sim->via_port_b |= 0x08;
437 }
438
439 e6522_set_irb_inp (&sim->via, sim->via_port_b);
440}
441
442static
443void mac_set_iwm_motor (void *ext, unsigned char val)
444{
445 macplus_t *sim = ext;
446
447 mac_set_speed (sim, PCE_MAC_SPEED_IWM, val ? 4 : 0);
448}
449
450static
451void mac_set_rtc_data (void *ext, unsigned char val)
452{
453 macplus_t *sim = ext;
454
455 if (val) {
456 sim->via_port_b |= 0x01;
457 }
458 else {
459 sim->via_port_b &= ~0x01;
460 }
461
462 e6522_set_irb_inp (&sim->via, sim->via_port_b);
463}
464
465static
466void mac_set_via_port_a (void *ext, unsigned char val)
467{
468 macplus_t *sim = ext;
469 unsigned char old;
470
471 if (sim->via_port_a == val) {
472 return;
473 }
474
475#ifdef DEBUG_VIA
476 mac_log_deb ("via: set port a: %02X\n", val);
477#endif
478
479 old = sim->via_port_a;
480 sim->via_port_a = val;
481
482 if ((old ^ val) & 0x10) {
483 if (sim->model & PCE_MAC_PLUS) {
484 mac_set_overlay (sim, (val & 0x10) != 0);
485 }
486 else if (sim->model & (PCE_MAC_SE | PCE_MAC_CLASSIC)) {
487 mac_iwm_set_drive_sel (&sim->iwm, (val & 0x10) != 0);
488 }
489 }
490
491 if ((old ^ val) & 0x20) {
492 mac_iwm_set_head_sel (&sim->iwm, (val & 0x20) != 0);
493 }
494
495 if ((old ^ val) & 0x40) {
496 unsigned long addr;
497
498 if (val & 0x40) {
499 mac_log_deb ("main video buffer\n");
500 addr = sim->vbuf1;
501 }
502 else {
503 mac_log_deb ("alternate video buffer\n");
504 addr = sim->vbuf2;
505 }
506
507 mac_set_vbuf (sim, addr);
508 }
509
510 if ((old ^ val) & 0x08) {
511 if (sim->model & PCE_MAC_PLUS) {
512 unsigned char *sbuf;
513
514 sbuf = mem_blk_get_data (sim->ram);
515
516 if (val & 0x08) {
517 mac_log_deb ("main sound buffer\n");
518 sbuf += sim->sbuf1;
519 }
520 else {
521 mac_log_deb ("alternate sound buffer\n");
522 sbuf += sim->sbuf2;
523 }
524
525 mac_sound_set_sbuf (&sim->sound, sbuf);
526 }
527 }
528
529 if ((old ^ val) & 0x07) {
530 mac_sound_set_volume (&sim->sound, val & 7);
531 }
532}
533
534static
535void mac_set_via_port_b (void *ext, unsigned char val)
536{
537 macplus_t *sim = ext;
538 unsigned char old;
539
540 if (sim->via_port_b == val) {
541 return;
542 }
543
544#ifdef DEBUG_VIA
545 mac_log_deb ("via: set port b: %02X\n", val);
546#endif
547
548 old = sim->via_port_b;
549 sim->via_port_b = val;
550
551 mac_rtc_set_uint8 (&sim->rtc, val);
552
553 if ((old ^ val) & 0x80) {
554 mac_sound_set_enable (&sim->sound, (val & 0x80) == 0);
555 }
556
557 if (sim->adb != NULL) {
558 mac_adb_set_state (sim->adb, (val >> 4) & 3);
559 }
560}
561
562static
563unsigned char mac_scc_get_uint8 (void *ext, unsigned long addr)
564{
565 unsigned char val;
566 macplus_t *sim = ext;
567
568 val = 0xff;
569
570 switch (addr) {
571 case 0x1ffff8:
572 val = e8530_get_ctl_b (&sim->scc);
573 break;
574
575 case 0x1ffffa:
576 val = e8530_get_ctl_a (&sim->scc);
577 break;
578
579 case 0x1ffffc:
580 val = e8530_get_data_b (&sim->scc);
581 break;
582
583 case 0x1ffffe:
584 val = e8530_get_data_a (&sim->scc);
585 break;
586 }
587
588#ifdef DEBUG_SCC
589 mac_log_deb ("scc: get 8: %06lX -> %02X\n", addr, val);
590#endif
591
592 return (val);
593}
594
595static
596void mac_scc_set_uint8 (void *ext, unsigned long addr, unsigned char val)
597{
598 macplus_t *sim = ext;
599
600#ifdef DEBUG_SCC
601 mac_log_deb ("scc: set 8: %06lX <- %02X\n", addr, val);
602#endif
603
604 switch (addr) {
605 case 0x3ffff9:
606 e8530_set_ctl_b (&sim->scc, val);
607 break;
608
609 case 0x3ffffb:
610 e8530_set_ctl_a (&sim->scc, val);
611 break;
612
613 case 0x3ffffd:
614 e8530_set_data_b (&sim->scc, val);
615 break;
616
617 case 0x3fffff:
618 e8530_set_data_a (&sim->scc, val);
619 break;
620 }
621}
622
623
624static
625void mac_setup_system (macplus_t *sim, ini_sct_t *ini)
626{
627 int memtest;
628 const char *model;
629 ini_sct_t *sct;
630
631 if ((sct = ini_next_sct (ini, NULL, "system")) == NULL) {
632 sct = ini;
633 }
634
635 ini_get_string (sct, "model", &model, "mac-plus");
636
637 if (ini_get_bool (sct, "memtest", &memtest, 1)) {
638 ini_get_bool (ini, "memtest", &memtest, 1);
639 }
640
641 pce_log_tag (MSG_INF, "SYSTEM:", "model=%s memtest=%d\n",
642 model, memtest
643 );
644
645 if (strcmp (model, "mac-128k") == 0) {
646 sim->model = PCE_MAC_PLUS;
647 }
648 else if (strcmp (model, "mac-512k") == 0) {
649 sim->model = PCE_MAC_PLUS;
650 }
651 else if (strcmp (model, "mac-plus") == 0) {
652 sim->model = PCE_MAC_PLUS;
653 }
654 else if (strcmp (model, "mac-se") == 0) {
655 sim->model = PCE_MAC_SE;
656 }
657 else if (strcmp (model, "mac-classic") == 0) {
658 sim->model = PCE_MAC_CLASSIC;
659 }
660 else {
661 pce_log (MSG_ERR, "*** unknown model (%s)\n", model);
662 sim->model = PCE_MAC_PLUS;
663 }
664
665 sim->memtest = (memtest != 0);
666}
667
668static
669void mac_setup_mem (macplus_t *sim, ini_sct_t *ini)
670{
671 sim->mem = mem_new();
672
673 mem_set_fct (sim->mem, sim,
674 mac_mem_get_uint8, mac_mem_get_uint16, mac_mem_get_uint32,
675 mac_mem_set_uint8, mac_mem_set_uint16, mac_mem_set_uint32
676 );
677
678 ini_get_ram (sim->mem, ini, &sim->ram);
679 ini_get_rom (sim->mem, ini);
680
681 sim->ram = mem_get_blk (sim->mem, 0x00000000);
682 sim->rom = mem_get_blk (sim->mem, 0x00400000);
683
684 sim->ram_ovl = NULL;
685 sim->rom_ovl = NULL;
686
687 if (sim->ram == NULL) {
688 pce_log (MSG_ERR, "*** RAM not found at 000000\n");
689 return;
690 }
691
692 if (sim->rom == NULL) {
693 pce_log (MSG_ERR, "*** ROM not found at 400000\n");
694 return;
695 }
696
697 sim->ram_ovl = mem_blk_clone (sim->ram);
698 mem_blk_set_addr (sim->ram_ovl, 0x00600000);
699
700 if (mem_blk_get_size (sim->ram_ovl) > 0x00200000) {
701 mem_blk_set_size (sim->ram_ovl, 0x00200000);
702 }
703
704 sim->rom_ovl = mem_blk_clone (sim->rom);
705 mem_blk_set_addr (sim->rom_ovl, 0);
706
707 sim->overlay = 0;
708
709 if (sim->memtest == 0) {
710 pce_log_tag (MSG_INF, "RAM:", "disabling memory test\n");
711
712 if (sim->model & PCE_MAC_PLUS) {
713 mem_set_uint32_be (sim->mem, 0x02ae, 0x00400000);
714 }
715 else if (sim->model & (PCE_MAC_SE | PCE_MAC_CLASSIC)) {
716 mem_set_uint32_be (sim->mem, 0x0cfc, 0x574c5343);
717 }
718 }
719}
720
721static
722void mac_setup_cpu (macplus_t *sim, ini_sct_t *ini)
723{
724 ini_sct_t *sct;
725 const char *model;
726 unsigned speed;
727
728 sct = ini_next_sct (ini, NULL, "cpu");
729
730 ini_get_string (sct, "model", &model, "68000");
731 ini_get_uint16 (sct, "speed", &speed, 0);
732
733 pce_log_tag (MSG_INF, "CPU:", "model=%s speed=%d\n", model, speed);
734
735 sim->cpu = e68_new();
736 if (sim->cpu == NULL) {
737 return;
738 }
739
740 if (mac_set_cpu_model (sim, model)) {
741 pce_log (MSG_ERR, "*** unknown cpu model (%s)\n", model);
742 }
743
744 e68_set_mem_fct (sim->cpu, sim->mem,
745 &mem_get_uint8,
746 &mem_get_uint16_be,
747 &mem_get_uint32_be,
748 &mem_set_uint8,
749 &mem_set_uint16_be,
750 &mem_set_uint32_be
751 );
752
753 e68_set_reset_fct (sim->cpu, sim, mac_set_reset);
754
755 e68_set_hook_fct (sim->cpu, sim, mac_hook);
756
757 e68_set_address_check (sim->cpu, 0);
758
759 sim->speed_factor = speed;
760 sim->speed_limit[PCE_MAC_SPEED_USER] = speed;
761}
762
763static
764void mac_setup_via (macplus_t *sim, ini_sct_t *ini)
765{
766 ini_sct_t *sct;
767 mem_blk_t *blk;
768 unsigned long addr, size;
769
770 sct = ini_next_sct (ini, NULL, "via");
771
772 ini_get_uint32 (sct, "address", &addr, 0x00efe000);
773 ini_get_uint32 (sct, "size", &size, 16 * 512);
774
775 pce_log_tag (MSG_INF, "VIA:", "addr=0x%06lx size=0x%lx\n", addr, size);
776
777 e6522_init (&sim->via, 9);
778
779 e6522_set_irq_fct (&sim->via, sim, mac_interrupt_via);
780
781 e6522_set_ora_fct (&sim->via, sim, mac_set_via_port_a);
782 e6522_set_orb_fct (&sim->via, sim, mac_set_via_port_b);
783
784 blk = mem_blk_new (addr, size, 0);
785
786 if (blk == NULL) {
787 return;
788 }
789
790 mem_blk_set_fct (blk, &sim->via,
791 e6522_get_uint8, e6522_get_uint16, e6522_get_uint32,
792 e6522_set_uint8, e6522_set_uint16, e6522_set_uint32
793 );
794
795 mem_add_blk (sim->mem, blk, 1);
796}
797
798static
799void mac_setup_scc (macplus_t *sim, ini_sct_t *ini)
800{
801 ini_sct_t *sct;
802 mem_blk_t *blk;
803 unsigned long addr, size;
804
805 sct = ini_next_sct (ini, NULL, "scc");
806
807 ini_get_uint32 (sct, "address", &addr, 0x800000);
808 ini_get_uint32 (sct, "size", &size, 0x400000);
809
810 pce_log_tag (MSG_INF, "SCC:", "addr=0x%06lx size=0x%lx\n", addr, size);
811
812 e8530_init (&sim->scc);
813 e8530_set_irq_fct (&sim->scc, sim, mac_interrupt_scc);
814 e8530_set_clock (&sim->scc, 3672000, 3672000, 3672000);
815
816 blk = mem_blk_new (addr, size, 0);
817 if (blk == NULL) {
818 return;
819 }
820
821 mem_blk_set_fct (blk, sim,
822 mac_scc_get_uint8, NULL, NULL,
823 mac_scc_set_uint8, NULL, NULL
824 );
825
826 mem_add_blk (sim->mem, blk, 1);
827}
828
829static
830void mac_setup_serial (macplus_t *sim, ini_sct_t *ini)
831{
832 ini_sct_t *sct;
833 unsigned port;
834 unsigned multichar;
835 const char *driver;
836
837 mac_ser_init (&sim->ser[0]);
838 mac_ser_set_scc (&sim->ser[0], &sim->scc, 0);
839
840 mac_ser_init (&sim->ser[1]);
841 mac_ser_set_scc (&sim->ser[1], &sim->scc, 1);
842
843 sct = ini_next_sct (ini, NULL, "serial");
844
845 while (sct != NULL) {
846 ini_get_uint16 (sct, "port", &port, 0);
847 ini_get_uint16 (sct, "multichar", &multichar, 1);
848 ini_get_string (sct, "driver", &driver, NULL);
849
850 pce_log_tag (MSG_INF, "SERIAL:", "port=%u multichar=%u driver=%s\n",
851 port, multichar,
852 (driver != NULL) ? driver : "<none>"
853 );
854
855 sct = ini_next_sct (ini, sct, "serial");
856
857 if (port > 1) {
858 pce_log (MSG_ERR, "*** bad port number (%u)\n", port);
859 continue;
860 }
861
862 e8530_set_multichar (&sim->scc, port, multichar, multichar);
863
864 if (driver != NULL) {
865 if (mac_ser_set_driver (&sim->ser[port], driver)) {
866 pce_log (MSG_ERR, "*** can't open driver (%s)\n", driver);
867 }
868 }
869 }
870}
871
872static
873void mac_setup_rtc (macplus_t *sim, ini_sct_t *ini)
874{
875 ini_sct_t *sct;
876 const char *fname;
877 const char *start;
878 int localtime, realtime, romdisk, atalk;
879 unsigned volume;
880
881 sct = ini_next_sct (ini, NULL, "rtc");
882
883 ini_get_string (sct, "file", &fname, "pram.dat");
884 ini_get_bool (sct, "localtime", &localtime, 0);
885 ini_get_bool (sct, "realtime", &realtime, 1);
886 ini_get_bool (sct, "romdisk", &romdisk, 0);
887 ini_get_uint16 (sct, "volume", &volume, 0xff);
888 ini_get_string (sct, "start", &start, NULL);
889
890 if (ini_get_bool (sct, "appletalk", &atalk, 0)) {
891 atalk = -1;
892 }
893
894 pce_log_tag (MSG_INF, "RTC:",
895 "file=%s localtime=%d realtime=%d start=%s romdisk=%d "
896 "atalk=%d volume=%u\n",
897 fname, localtime, realtime, (start != NULL) ? start : "<now>",
898 romdisk, atalk, volume
899 );
900
901 sim->rtc_fname = strdup (fname);
902
903 mac_rtc_init (&sim->rtc);
904
905 mac_rtc_set_data_fct (&sim->rtc, sim, mac_set_rtc_data);
906 mac_rtc_set_osi_fct (&sim->rtc, sim, mac_interrupt_osi);
907
908 if (localtime) {
909 mac_rtc_set_time_gmtoff (&sim->rtc);
910 }
911
912 mac_rtc_set_realtime (&sim->rtc, realtime);
913
914 if (mac_rtc_load_file (&sim->rtc, fname)) {
915 pce_log (MSG_ERR, "*** reading rtc file failed\n");
916 }
917
918 if (romdisk) {
919 sim->rtc.data[0x78] = 0x00;
920 sim->rtc.data[0x79] = 0x06;
921 sim->rtc.data[0x7a] = 0xff;
922 sim->rtc.data[0x7b] = 0xcb;
923 }
924
925 if (atalk == 0) {
926 sim->rtc.data[0x13] = 0x22;
927 }
928 else if (atalk == 1) {
929 sim->rtc.data[0x13] = 0x21;
930 }
931
932 if (volume < 8) {
933 sim->rtc.data[0x08] &= 0xf8;
934 sim->rtc.data[0x08] |= (volume & 7);
935 }
936
937 if (start != NULL) {
938 mac_rtc_set_time_str (&sim->rtc, start);
939 }
940 else {
941 mac_rtc_set_time_now (&sim->rtc);
942 }
943}
944
945static
946void mac_setup_kbd (macplus_t *sim, ini_sct_t *ini)
947{
948 ini_sct_t *sct;
949 unsigned model;
950 int intl, motion;
951
952 sim->kbd = NULL;
953
954 if ((sim->model & PCE_MAC_PLUS) == 0) {
955 return;
956 }
957
958 sct = ini_next_sct (ini, NULL, "keyboard");
959
960 ini_get_uint16 (sct, "model", &model, 1);
961 ini_get_bool (sct, "intl", &intl, 0);
962 ini_get_bool (sct, "keypad_motion", &motion, 0);
963
964 pce_log_tag (MSG_INF,
965 "KEYBOARD:", "model=%u international=%d keypad=%s\n",
966 model,
967 intl,
968 motion ? "motion" : "keypad"
969 );
970
971 sim->kbd = mac_kbd_new();
972
973 if (sim->kbd == NULL) {
974 return;
975 }
976
977 mac_kbd_set_model (sim->kbd, model, intl);
978 mac_kbd_set_keypad_mode (sim->kbd, motion);
979 mac_kbd_set_data_fct (sim->kbd, &sim->via, e6522_set_shift_inp);
980 mac_kbd_set_intr_fct (sim->kbd, sim, mac_interrupt);
981
982 e6522_set_shift_out_fct (&sim->via, sim->kbd, mac_kbd_set_uint8);
983 e6522_set_cb2_fct (&sim->via, sim->kbd, mac_kbd_set_data);
984}
985
986static
987void mac_setup_adb (macplus_t *sim, ini_sct_t *ini)
988{
989 ini_sct_t *sct;
990 int mouse, keyboard, motion;
991
992 sim->adb = NULL;
993 sim->adb_mouse = NULL;
994 sim->adb_kbd = NULL;
995
996 if ((sim->model & (PCE_MAC_SE | PCE_MAC_CLASSIC)) == 0) {
997 return;
998 }
999
1000 sct = ini_next_sct (ini, NULL, "adb");
1001
1002 ini_get_bool (sct, "mouse", &mouse, 1);
1003 ini_get_bool (sct, "keyboard", &keyboard, 1);
1004 ini_get_bool (sct, "keypad_motion", &motion, 0);
1005
1006 pce_log_tag (MSG_INF, "ADB:", "enabled\n");
1007
1008 sim->adb = mac_adb_new();
1009
1010 if (sim->adb == NULL) {
1011 pce_log (MSG_ERR, "*** can't create adb\n");
1012 return;
1013 }
1014
1015 adb_set_shift_in_fct (sim->adb, &sim->via, e6522_shift_in);
1016 adb_set_shift_out_fct (sim->adb, &sim->via, e6522_shift_out);
1017
1018 adb_set_int_fct (sim->adb, sim, mac_set_adb_int);
1019
1020 if (mouse) {
1021 pce_log_tag (MSG_INF, "ADB:", "mouse\n");
1022
1023 sim->adb_mouse = adb_mouse_new();
1024
1025 if (sim->adb_mouse != NULL) {
1026 adb_add_device (sim->adb, &sim->adb_mouse->dev);
1027 }
1028 }
1029
1030 if (keyboard) {
1031 pce_log_tag (MSG_INF, "ADB:",
1032 "keyboard keypad_mode=%s\n",
1033 motion ? "motion" : "keypad"
1034 );
1035
1036 sim->adb_kbd = adb_kbd_new();
1037
1038 if (sim->adb_kbd != NULL) {
1039 adb_kbd_set_keypad_mode (sim->adb_kbd, motion);
1040 adb_add_device (sim->adb, &sim->adb_kbd->dev);
1041 }
1042 }
1043}
1044
1045static
1046void mac_setup_disks (macplus_t *sim, ini_sct_t *ini)
1047{
1048 sim->dsks = ini_get_disks (ini);
1049}
1050
1051static
1052void mac_setup_iwm (macplus_t *sim, ini_sct_t *ini)
1053{
1054 unsigned n;
1055 int single, rotate, inserted, pwm;
1056 unsigned drive, disk;
1057 ini_sct_t *sct, *sctdev;
1058
1059 sct = ini_next_sct (ini, NULL, "iwm");
1060
1061 mac_iwm_init (&sim->iwm);
1062 mac_iwm_set_motor_fct (&sim->iwm, sim, mac_set_iwm_motor);
1063 mac_iwm_set_disks (&sim->iwm, sim->dsks);
1064
1065 pce_log_tag (MSG_INF, "IWM:", "addr=0x%06lx\n", 0xd00000UL);
1066
1067 sctdev = ini_next_sct (sct, NULL, "drive");
1068
1069 n = 0;
1070
1071 while (sctdev != NULL) {
1072 ini_get_uint16 (sctdev, "drive", &drive, n);
1073 ini_get_uint16 (sctdev, "disk", &disk, drive);
1074
1075 ini_get_bool (sct, "single_sided", &single, 0);
1076 ini_get_bool (sctdev, "single_sided", &single, single);
1077
1078 ini_get_bool (sct, "pwm", &pwm, 1);
1079 ini_get_bool (sctdev, "pwm", &pwm, pwm);
1080
1081 ini_get_bool (sct, "inserted", &inserted, 0);
1082 ini_get_bool (sctdev, "inserted", &inserted, inserted);
1083
1084 if ((drive >= 1) && (drive <= 8)) {
1085 if (par_disk_boot & (1U << (drive - 1))) {
1086 inserted = 1;
1087 }
1088 }
1089
1090 ini_get_bool (sct, "auto_rotate", &rotate, 0);
1091 ini_get_bool (sctdev, "auto_rotate", &rotate, rotate);
1092
1093 pce_log_tag (MSG_INF,
1094 "IWM:", "drive=%u size=%uK pwm=%d ins=%d rotate=%d disk=%u\n",
1095 drive, single ? 400 : 800, pwm, inserted, rotate, disk
1096 );
1097
1098 mac_iwm_enable_pwm (&sim->iwm, drive - 1, pwm);
1099 mac_iwm_set_heads (&sim->iwm, drive - 1, single ? 1 : 2);
1100 mac_iwm_set_disk_id (&sim->iwm, drive - 1, disk);
1101 mac_iwm_set_auto_rotate (&sim->iwm, drive - 1, rotate);
1102
1103 if (inserted) {
1104 mac_iwm_insert (&sim->iwm, drive - 1);
1105 }
1106
1107 n = drive + 1;
1108
1109 sctdev = ini_next_sct (sct, sctdev, "drive");
1110 }
1111}
1112
1113static
1114void mac_setup_scsi (macplus_t *sim, ini_sct_t *ini)
1115{
1116 ini_sct_t *sct, *sctdev;
1117 mem_blk_t *blk;
1118 unsigned long addr, size;
1119 unsigned id, drive, daynaport;
1120 const char *vendor, *product, *mac_addr, *tap_dev, *tap_cmd, *bridged_if;
1121
1122 sct = ini_next_sct (ini, NULL, "scsi");
1123
1124 if (sct == NULL) {
1125 return;
1126 }
1127
1128 ini_get_uint32 (sct, "address", &addr, 0x580000);
1129 ini_get_uint32 (sct, "size", &size, 0x80000);
1130
1131 pce_log_tag (MSG_INF, "SCSI:", "addr=0x%06lx size=0x%lx\n", addr, size);
1132
1133 mac_scsi_init (&sim->scsi);
1134
1135 if (sim->model & PCE_MAC_SE) {
1136 mac_scsi_set_int_fct (&sim->scsi, sim, mac_interrupt_scsi);
1137 }
1138
1139 mac_scsi_set_disks (&sim->scsi, sim->dsks);
1140
1141 blk = mem_blk_new (addr, size, 0);
1142 if (blk == NULL) {
1143 return;
1144 }
1145
1146 mem_blk_set_fct (blk, &sim->scsi,
1147 mac_scsi_get_uint8, mac_scsi_get_uint16, NULL,
1148 mac_scsi_set_uint8, mac_scsi_set_uint16, NULL
1149 );
1150
1151 mem_add_blk (sim->mem, blk, 1);
1152
1153 sctdev = ini_next_sct (sct, NULL, "device");
1154 while (sctdev != NULL) {
1155 ini_get_uint16 (sctdev, "id", &id, 0);
1156 ini_get_uint16 (sctdev, "drive", &drive, 0);
1157 ini_get_uint16 (sctdev, "daynaport", &daynaport, 0);
1158
1159 if (drive) {
1160 ini_get_string (sctdev, "vendor", &vendor, "PCE");
1161 ini_get_string (sctdev, "product", &product, "PCEDISK");
1162
1163 pce_log_tag (MSG_INF,
1164 "SCSI:",
1165 "id=%u drive=%u vendor=\"%s\" product=\"%s\"\n",
1166 id, drive, vendor, product
1167 );
1168
1169 mac_scsi_set_drive (&sim->scsi, id, drive);
1170 mac_scsi_set_drive_vendor (&sim->scsi, id, vendor);
1171 mac_scsi_set_drive_product (&sim->scsi, id, product);
1172 }
1173 else if (daynaport) {
1174 ini_get_string (sctdev, "tap", &tap_dev, "/dev/tap0");
1175 ini_get_string (sctdev, "tap_cmd", &tap_cmd, "");
1176 ini_get_string (sctdev, "mac_addr", &mac_addr, "00:80:19:c0:ff:ee");
1177 ini_get_string (sctdev, "bridged_if", &bridged_if, "");
1178
1179 pce_log_tag (MSG_INF,
1180 "SCSI:",
1181#if PCE_ENABLE_VMNET
1182 "id=%u daynaport=%u bridged=%s mac_addr=%s\n",
1183 id, daynaport, bridged_if, mac_addr
1184#else
1185 "id=%u daynaport=%u tap=%s cmd=%s mac_addr=%s\n",
1186 id, daynaport, tap_dev, tap_cmd, mac_addr
1187#endif
1188 );
1189
1190 mac_scsi_set_daynaport (&sim->scsi, id, tap_dev, tap_cmd, mac_addr, bridged_if);
1191 }
1192
1193 sctdev = ini_next_sct (sct, sctdev, "device");
1194 }
1195}
1196
1197static
1198void mac_setup_sony (macplus_t *sim, ini_sct_t *ini)
1199{
1200 unsigned i;
1201 int format_hd_as_dd;
1202 char var[32];
1203 unsigned def, val;
1204 ini_sct_t *sct;
1205
1206 sct = ini_next_sct (ini, NULL, "sony");
1207
1208 ini_get_uint16 (sct, "insert_delay", &def, 0);
1209 ini_get_bool (sct, "format_hd_as_dd", &format_hd_as_dd, 0);
1210
1211 mac_sony_init (&sim->sony, sct != NULL);
1212 mac_sony_set_mem (&sim->sony, sim->mem);
1213 mac_sony_set_disks (&sim->sony, sim->dsks);
1214
1215 sim->sony.format_hd_as_dd = format_hd_as_dd;
1216
1217 if (sct == NULL) {
1218 return;
1219 }
1220
1221 for (i = 0; i < SONY_DRIVES; i++) {
1222 if (par_disk_boot & (1U << i)) {
1223 val = 1;
1224 }
1225 else {
1226 sprintf (var, "insert_delay_%u", i + 1);
1227 ini_get_uint16 (sct, var, &val, def);
1228 }
1229
1230 mac_sony_set_delay (&sim->sony, i, val);
1231
1232 pce_log_tag (MSG_INF, "SONY:", "drive=%u delay=%lu\n",
1233 i + 1, val
1234 );
1235 }
1236}
1237
1238static
1239void mac_setup_sound (macplus_t *sim, ini_sct_t *ini)
1240{
1241 unsigned long addr;
1242 unsigned long freq;
1243 const char *driver;
1244 ini_sct_t *sct;
1245
1246 mac_sound_init (&sim->sound);
1247
1248 if (sim->ram == NULL) {
1249 return;
1250 }
1251
1252 sct = ini_next_sct (ini, NULL, "sound");
1253
1254 addr = mem_blk_get_size (sim->ram);
1255 addr = (addr < 0x300) ? 0 : (addr - 0x300);
1256
1257 ini_get_uint32 (sct, "address", &addr, addr);
1258 ini_get_uint32 (sct, "lowpass", &freq, 6000);
1259 ini_get_string (sct, "driver", &driver, NULL);
1260
1261 pce_log_tag (MSG_INF, "SOUND:", "addr=0x%06lX lowpass=%lu driver=%s\n",
1262 addr, freq,
1263 (driver != NULL) ? driver : "<none>"
1264 );
1265
1266 sim->sbuf1 = addr;
1267 sim->sbuf2 = addr - 0x5c00;
1268
1269 mac_sound_set_sbuf (&sim->sound, mem_blk_get_data (sim->ram) + sim->sbuf1);
1270
1271 mac_sound_set_lowpass (&sim->sound, freq);
1272
1273 if (driver != NULL) {
1274 if (mac_sound_set_driver (&sim->sound, driver)) {
1275 pce_log (MSG_ERR,
1276 "*** setting sound driver failed (%s)\n",
1277 driver
1278 );
1279 }
1280 }
1281}
1282
1283static
1284void mac_setup_terminal (macplus_t *sim, ini_sct_t *ini)
1285{
1286 sim->trm = ini_get_terminal (ini, par_terminal);
1287
1288 if (sim->trm == NULL) {
1289 return;
1290 }
1291
1292 trm_set_msg_fct (sim->trm, sim, mac_set_msg);
1293 trm_set_key_fct (sim->trm, sim, mac_set_key);
1294 trm_set_mouse_fct (sim->trm, sim, mac_set_mouse);
1295 trm_set_get_mouse_fct (sim->trm, sim, mac_get_mouse);
1296}
1297
1298static
1299void mac_setup_video (macplus_t *sim, ini_sct_t *ini)
1300{
1301 unsigned long addr1, addr2;
1302 unsigned w, h, i;
1303 unsigned bright;
1304 unsigned long col0, col1;
1305 ini_sct_t *sct;
1306
1307 if (sim->ram == NULL) {
1308 return;
1309 }
1310
1311 sct = ini_next_sct (ini, NULL, "video");
1312
1313 ini_get_uint16 (sct, "width", &w, 512);
1314 ini_get_uint16 (sct, "height", &h, 342);
1315
1316 addr1 = mem_blk_get_size (sim->ram);
1317 addr1 = (addr1 < 0x5900) ? 0 : (addr1 - ((w * h / 8) + 0x380));
1318
1319 ini_get_uint32 (sct, "address", &addr2, addr1);
1320 ini_get_uint32 (sct, "color0", &col0, 0);
1321 ini_get_uint32 (sct, "color1", &col1, 0xffffff);
1322 ini_get_uint16 (sct, "brightness", &bright, 1000);
1323
1324 pce_log_tag (MSG_INF, "VIDEO:", "addr=0x%06lX w=%u h=%u bright=%u%%\n",
1325 addr2, w, h, bright / 10
1326 );
1327
1328 sim->vbuf1 = addr2;
1329
1330 if ((addr1 == addr2) && (addr2 >= 0x8000)) {
1331 sim->vbuf2 = addr2 - 0x8000;
1332 }
1333 else {
1334 sim->vbuf2 = addr2;
1335 }
1336
1337 sim->video = mac_video_new (w, h);
1338
1339 if (sim->video == NULL) {
1340 return;
1341 }
1342
1343 mac_video_set_vbi_fct (sim->video, sim, mac_interrupt_vbi);
1344
1345 mac_set_vbuf (sim, sim->vbuf1);
1346
1347 if (sim->trm != NULL) {
1348 mac_video_set_terminal (sim->video, sim->trm);
1349
1350 trm_open (sim->trm, w, h);
1351 }
1352
1353 mac_video_set_color (sim->video, col0, col1);
1354 mac_video_set_brightness (sim->video, (255UL * bright + 500) / 1000);
1355
1356 for (i = 0; i < (w / 8) * h; i++) {
1357 mem_set_uint8 (sim->mem, sim->vbuf1 + i, 0xff);
1358 }
1359}
1360
1361void mac_init (macplus_t *sim, ini_sct_t *ini)
1362{
1363 unsigned i;
1364
1365 sim->trm = NULL;
1366 sim->video = NULL;
1367
1368 sim->reset = 0;
1369
1370 sim->disk_id = 1;
1371
1372 sim->dcd_a = 0;
1373 sim->dcd_b = 0;
1374
1375 sim->mouse_delta_x = 0;
1376 sim->mouse_delta_y = 0;
1377 sim->mouse_button = 0;
1378
1379 sim->intr = 0;
1380
1381 sim->pause = 0;
1382 sim->brk = 0;
1383
1384 sim->speed_factor = 1;
1385 sim->speed_limit[0] = 1;
1386 sim->speed_clock_extra = 0;
1387
1388 for (i = 1; i < PCE_MAC_SPEED_CNT; i++) {
1389 sim->speed_limit[i] = 0;
1390 }
1391
1392 sim->ser_clk = 0;
1393 sim->clk_cnt = 0;
1394
1395 for (i = 0; i < 4; i++) {
1396 sim->clk_div[i] = 0;
1397 }
1398
1399 bps_init (&sim->bps);
1400
1401 mac_setup_system (sim, ini);
1402 mac_setup_mem (sim, ini);
1403 mac_setup_cpu (sim, ini);
1404 mac_setup_via (sim, ini);
1405 mac_setup_scc (sim, ini);
1406 mac_setup_serial (sim, ini);
1407 mac_setup_rtc (sim, ini);
1408 mac_setup_kbd (sim, ini);
1409 mac_setup_adb (sim, ini);
1410 mac_setup_disks (sim, ini);
1411 mac_setup_iwm (sim, ini);
1412 mac_setup_scsi (sim, ini);
1413 mac_setup_sony (sim, ini);
1414 mac_setup_sound (sim, ini);
1415 mac_setup_terminal (sim, ini);
1416 mac_setup_video (sim, ini);
1417
1418 e68_set_ram_write_fct (sim->cpu, sim, mac_ram_write);
1419
1420 pce_load_mem_ini (sim->mem, ini);
1421
1422 trm_set_msg_trm (sim->trm, "term.title", "pce-macplus");
1423
1424 mac_clock_discontinuity (sim);
1425}
1426
1427macplus_t *mac_new (ini_sct_t *ini)
1428{
1429 macplus_t *sim;
1430
1431 sim = malloc (sizeof (macplus_t));
1432 if (sim == NULL) {
1433 return (NULL);
1434 }
1435
1436 mac_init (sim, ini);
1437
1438 return (sim);
1439}
1440
1441void mac_free (macplus_t *sim)
1442{
1443 if (sim == NULL) {
1444 return;
1445 }
1446
1447 if (mac_rtc_save_file (&sim->rtc, sim->rtc_fname)) {
1448 pce_log (MSG_ERR, "*** writing rtc file failed (%s)\n",
1449 sim->rtc_fname
1450 );
1451 }
1452
1453 free (sim->rtc_fname);
1454
1455 mac_video_del (sim->video);
1456 trm_del (sim->trm);
1457 mac_sound_free (&sim->sound);
1458 mac_sony_free (&sim->sony);
1459 mac_scsi_free (&sim->scsi);
1460 mac_iwm_free (&sim->iwm);
1461 dsks_del (sim->dsks);
1462 mac_adb_del (sim->adb);
1463 mac_kbd_del (sim->kbd);
1464 mac_rtc_free (&sim->rtc);
1465 mac_ser_free (&sim->ser[1]);
1466 mac_ser_free (&sim->ser[0]);
1467 e8530_free (&sim->scc);
1468 e6522_free (&sim->via);
1469 e68_del (sim->cpu);
1470 mem_del (sim->mem);
1471
1472 mem_blk_del (sim->ram_ovl);
1473 mem_blk_del (sim->rom_ovl);
1474
1475 bps_free (&sim->bps);
1476}
1477
1478void mac_del (macplus_t *sim)
1479{
1480 if (sim != NULL) {
1481 mac_free (sim);
1482 free (sim);
1483 }
1484}
1485
1486
1487unsigned long long mac_get_clkcnt (macplus_t *sim)
1488{
1489 return (sim->clk_cnt);
1490}
1491
1492void mac_clock_discontinuity (macplus_t *sim)
1493{
1494 sim->sync_clk = 0;
1495 sim->sync_us = 0;
1496 pce_get_interval_us (&sim->sync_us);
1497
1498 sim->speed_clock_extra = 0;
1499}
1500
1501void mac_set_pause (macplus_t *sim, int pause)
1502{
1503 sim->pause = (pause != 0);
1504
1505 if (sim->pause == 0) {
1506 mac_clock_discontinuity (sim);
1507 }
1508}
1509
1510static
1511void mac_adjust_speed (macplus_t *sim)
1512{
1513 unsigned i, v;
1514
1515 v = 0;
1516
1517 for (i = 0; i < PCE_MAC_SPEED_CNT; i++) {
1518 if (sim->speed_limit[i] > 0) {
1519 if ((v == 0) || (sim->speed_limit[i] < v)) {
1520 v = sim->speed_limit[i];
1521 }
1522 }
1523 }
1524
1525 if (v == sim->speed_factor) {
1526 return;
1527 }
1528
1529 mac_log_deb ("speed: %u\n", v);
1530
1531 mac_rtc_set_realtime (&sim->rtc, (v != 1));
1532
1533 sim->speed_factor = v;
1534 sim->speed_clock_extra = 0;
1535
1536 mac_clock_discontinuity (sim);
1537}
1538
1539void mac_set_speed (macplus_t *sim, unsigned idx, unsigned factor)
1540{
1541 if (idx >= PCE_MAC_SPEED_CNT) {
1542 return;
1543 }
1544
1545 sim->speed_limit[idx] = factor;
1546
1547 mac_adjust_speed (sim);
1548}
1549
1550int mac_set_msg_trm (macplus_t *sim, const char *msg, const char *val)
1551{
1552 if (sim->trm == NULL) {
1553 return (1);
1554 }
1555
1556 return (trm_set_msg_trm (sim->trm, msg, val));
1557}
1558
1559int mac_set_cpu_model (macplus_t *sim, const char *model)
1560{
1561 if (strcmp (model, "68000") == 0) {
1562 e68_set_68000 (sim->cpu);
1563 }
1564 else if (strcmp (model, "68010") == 0) {
1565 e68_set_68010 (sim->cpu);
1566 }
1567 else if (strcmp (model, "68020") == 0) {
1568 e68_set_68020 (sim->cpu);
1569 }
1570 else {
1571 return (1);
1572 }
1573
1574 return (0);
1575}
1576
1577void mac_reset (macplus_t *sim)
1578{
1579 if (sim->reset) {
1580 return;
1581 }
1582
1583 sim->reset = 1;
1584
1585 mac_log_deb ("mac: reset\n");
1586
1587 sim->dcd_a = 0;
1588 sim->dcd_b = 0;
1589
1590 sim->mouse_delta_x = 0;
1591 sim->mouse_delta_y = 0;
1592 sim->mouse_button = 0;
1593
1594 sim->intr = 0;
1595 sim->intr_scsi_via = 0;
1596
1597 if (sim->model & PCE_MAC_PLUS) {
1598 mac_set_overlay (sim, 1);
1599 }
1600 else {
1601 mac_set_overlay (sim, 0);
1602 if ((sim->rom != NULL) && (sim->rom->size >= 8)) {
1603 e68_set_mem32 (sim->cpu, 0, mem_blk_get_uint32_be (sim->rom, 0));
1604 e68_set_mem32 (sim->cpu, 4, mem_blk_get_uint32_be (sim->rom, 4));
1605 }
1606 }
1607
1608 e6522_reset (&sim->via);
1609
1610 sim->via_port_a = 0xf7;
1611 sim->via_port_b = 0xff;
1612
1613 e6522_set_ira_inp (&sim->via, sim->via_port_a);
1614 e6522_set_irb_inp (&sim->via, sim->via_port_b);
1615
1616 mac_sony_reset (&sim->sony);
1617 mac_scsi_reset (&sim->scsi);
1618 e8530_reset (&sim->scc);
1619
1620 if (sim->adb != NULL) {
1621 adb_reset (sim->adb);
1622 }
1623
1624 e68_reset (sim->cpu);
1625
1626 mac_clock_discontinuity (sim);
1627
1628 sim->reset = 0;
1629}
1630
1631static
1632void mac_realtime_sync (macplus_t *sim, unsigned long n)
1633{
1634 unsigned long us1, us2;
1635
1636 sim->sync_clk += n;
1637
1638 if (sim->sync_clk >= (MAC_CPU_CLOCK / MAC_CPU_SYNC)) {
1639 sim->sync_clk -= (MAC_CPU_CLOCK / MAC_CPU_SYNC);
1640
1641 us1 = pce_get_interval_us (&sim->sync_us);
1642 us2 = (1000000 / MAC_CPU_SYNC);
1643
1644 if (us1 < us2) {
1645 sim->sync_sleep += us2 - us1;
1646
1647 if (sim->sync_sleep > 0) {
1648 sim->speed_clock_extra += 1;
1649 }
1650 }
1651 else {
1652 sim->sync_sleep -= us1 - us2;
1653
1654 if (sim->sync_sleep < 0) {
1655 if (sim->speed_clock_extra > 0) {
1656 sim->speed_clock_extra -= 1;
1657 }
1658 }
1659 }
1660
1661 if (sim->sync_sleep >= MAC_CPU_SLEEP) {
1662 pce_usleep (sim->sync_sleep);
1663 }
1664
1665 if (sim->sync_sleep < -1000000) {
1666 mac_log_deb ("system too slow, skipping 1 second\n");
1667 sim->sync_sleep += 1000000;
1668 }
1669 }
1670}
1671
1672void mac_clock_scc (macplus_t *sim, unsigned n)
1673{
1674 /* 3.672 MHz = (15/32 * 7.8336 MHz) */
1675 sim->ser_clk += 15 * n;
1676
1677 if (sim->ser_clk >= 32) {
1678 e8530_clock (&sim->scc, sim->ser_clk / 32);
1679 sim->ser_clk &= 31;
1680 }
1681}
1682
1683void mac_clock (macplus_t *sim, unsigned n)
1684{
1685 unsigned long viaclk, clkdiv, cpuclk;
1686
1687 if (n == 0) {
1688 n = sim->cpu->delay;
1689 if (n == 0) {
1690 n = 1;
1691 }
1692 }
1693
1694 if (sim->speed_factor == 0) {
1695 cpuclk = n + sim->speed_clock_extra;
1696 clkdiv = 1;
1697 }
1698 else {
1699 cpuclk = n;
1700 clkdiv = sim->speed_factor;
1701 }
1702
1703 e68_clock (sim->cpu, cpuclk);
1704
1705 mac_sound_clock (&sim->sound, cpuclk);
1706
1707 sim->clk_cnt += n;
1708
1709 sim->clk_div[0] += n;
1710
1711 while (sim->clk_div[0] >= clkdiv) {
1712 sim->clk_div[1] += 1;
1713 sim->clk_div[0] -= clkdiv;
1714 }
1715
1716 if (sim->clk_div[1] < 10) {
1717 return;
1718 }
1719
1720 viaclk = sim->clk_div[1] / 10;
1721
1722 e6522_clock (&sim->via, viaclk);
1723
1724 if (sim->adb != NULL) {
1725 mac_adb_clock (sim->adb, 10 * viaclk);
1726 }
1727
1728 mac_iwm_clock (&sim->iwm, viaclk);
1729
1730 mac_clock_scc (sim, 10 * viaclk);
1731
1732 sim->clk_div[1] -= 10 * viaclk;
1733 sim->clk_div[2] += 10 * viaclk;
1734
1735 if (sim->clk_div[2] < 256) {
1736 return;
1737 }
1738
1739 mac_video_clock (sim->video, sim->clk_div[2]);
1740
1741 mac_ser_process (&sim->ser[0]);
1742 mac_ser_process (&sim->ser[1]);
1743
1744 if (sim->kbd != NULL) {
1745 mac_kbd_clock (sim->kbd, sim->clk_div[2]);
1746 }
1747
1748 sim->clk_div[3] += sim->clk_div[2];
1749 sim->clk_div[2] = 0;
1750
1751 if (sim->clk_div[3] < 8192) {
1752 return;
1753 }
1754
1755 if (sim->trm != NULL) {
1756 trm_check (sim->trm);
1757 }
1758
1759 mac_check_mouse (sim);
1760
1761 mac_rtc_clock (&sim->rtc, sim->clk_div[3]);
1762
1763 mac_realtime_sync (sim, sim->clk_div[3]);
1764
1765 sim->clk_div[3] = 0;
1766}