1 /* pro_init.c: reset and exit routines
2
3 Copyright (c) 1997-2004, Tarik Isani (xhomer@isani.org)
4
5 This file is part of Xhomer.
6
7 Xhomer is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10
11 Xhomer is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Xhomer; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21
22 #ifdef PRO
23 #include "pdp11_defs.h"
24 #include <stdlib.h>
25 #include <unistd.h>
26
27 #ifdef __hpux__
28 #define seteuid(euid) setresuid(-1,(euid),-1)
29 #endif
30
31 extern t_stat ttclose (void); /* from scp_tty.c */
32 extern int PC; /* from pdp11_cpu */
33
34 #ifdef IOTRACE
35 FILE *iotfptr = NULL;
36 #endif
37
38 struct sercall *pro_la50device;
39 struct sercall *pro_kb;
40 struct sercall *pro_ptr;
41 struct sercall *pro_com;
42
43 int pro_la50device_port;
44 int pro_kb_port;
45 int pro_ptr_port;
46 int pro_com_port;
47
48
49 #ifdef TRACE
50 /* PC Trace */
51
52 LOCAL FILE *tfptr = NULL;
53
trace()54 int trace ()
55 {
56 if (tfptr)
57 {
58 fprintf(tfptr, "%o\n", PC);
59 fflush(tfptr);
60 }
61 return SCPE_OK;
62 }
63
trace_reset()64 LOCAL int trace_reset ()
65 {
66 if (!tfptr)
67 tfptr = fopen("trace","w");
68 else
69 fflush(tfptr);
70
71 return SCPE_OK;
72 }
73 #endif
74
75 #ifdef IOTRACE
76 /* I/O Access Trace */
77
iotrace_reset()78 LOCAL int iotrace_reset ()
79 {
80 if (!iotfptr)
81 iotfptr = fopen("iotrace","w");
82 else
83 fflush(iotfptr);
84
85 return SCPE_OK;
86 }
87 #endif
88
89
90 /* Text parameter comparison */
91
92 /* max = -1 for no suffix
93 0..9 for suffix */
94
95 /* returns -1 if no match
96 0 if a string without a suffix matches (i.e. "kb")
97 0..max if a string with a suffix matches (i.e. "rx2") */
98
scmp(char * s1,char * s2,int max,int p1,int p2,int numpar)99 LOCAL int scmp(char *s1, char *s2, int max, int p1, int p2, int numpar)
100 {
101 int i, s1len, s2len;
102
103
104 s1len = strlen(s1);
105 s2len = strlen(s2);
106
107 if ((strncmp(s1, s2, s2len) == 0)
108 && ((numpar == p1) || (numpar == p2)))
109 {
110 if ((max == -1) && (s1len == s2len))
111 return 0;
112 else if (s1len == (s2len+1))
113 {
114 i = (int)s1[s2len] - 48;
115 if ((i>=0) && (i<=max))
116 return i;
117 }
118 }
119 return -1;
120 }
121
122
123 /* Serial device assignments */
124
125 /* returns 0 if successful, -1 if not */
126
assign_serial(char * s1,struct sercall ** dev,int * port)127 LOCAL int assign_serial(char *s1, struct sercall **dev, int *port)
128 {
129 int i, j;
130
131
132 j = 0;
133
134 if ((i = scmp(s1, "serial\0", 3, 1, 1, 1)) > -1)
135 {
136 *dev = &pro_serial;
137 *port = i;
138 }
139 else if ((i = scmp(s1, "la50\0", -1, 1, 1, 1)) > -1)
140 {
141 *dev = &pro_la50;
142 *port = 0;
143 }
144 else if (scmp(s1, "lk201\0", -1, 1, 1, 1) > -1)
145 {
146 *dev = &pro_lk201;
147 *port = 0;
148 }
149 else if (scmp(s1, "digipad\0", -1, 1, 1, 1) > -1)
150 {
151 *dev = &pro_digipad;
152 *port = 0;
153 }
154 else if (scmp(s1, "null\0", -1, 1, 1, 1) > -1)
155 {
156 *dev = &pro_null;
157 *port = 0;
158 }
159 else
160 j = -1;
161
162 return j;
163 }
164
165
166 /* Main PRO reset routine */
167
pro_reset()168 void pro_reset ()
169 {
170 #define MAXPAR 4 /* max # of parameters */
171
172 FILE *fptr;
173 char *eofptr;
174 char str1[1024], str2[1024];
175 char filename[1024];
176 char *stra, *strv[MAXPAR];
177 unsigned char h, l;
178 int i, j, k, len, linenum, numpar, error, file_found;
179 char *strtmp;
180
181
182 printf("\n");
183 printf("XHOMER: Digital Pro/350 emulator (version %s)\n", PRO_VERSION);
184 printf("(Press ctrl-F1, while the emulator window has focus, to access the control menu)\n");
185 printf("\n");
186
187 seteuid(getuid());
188
189 pro_csr = PRO_CSR_INIT;
190
191 pro_led = 0;
192
193
194 #ifndef BUILTIN_ROMS
195 /* Load boot/diagnostic ROM */
196
197 fptr = fopen("pro350.rom","r");
198
199 if (fptr == NULL)
200 {
201 printf("Unable to open pro350.rom\n");
202 exit(0);
203 }
204
205 for(i=0 ; i<8192; i++)
206 {
207 l = getc(fptr);
208 h = getc(fptr);
209 ROM[i] = h*256+l;
210 }
211
212 fclose(fptr);
213
214
215 /* Load ID ROM */
216
217 fptr = fopen("id.rom","r");
218
219 if (fptr == NULL)
220 {
221 printf("Unable to open id.rom\n");
222 exit(0);
223 }
224
225 for(i=0 ; i<32; i++)
226 {
227 l = getc(fptr);
228 h = getc(fptr);
229 IDROM[i] = h*256+l;
230 }
231
232 fclose(fptr);
233 #endif
234
235
236 /* Initialize battery-backed RAM */
237
238 fptr = fopen("bat.ram","r");
239
240 if (fptr == NULL)
241 {
242 printf("Unable to open bat.ram - clearing battery-backed RAM\n");
243 memset(&BATRAM, 0, sizeof(BATRAM));
244 }
245 else
246 {
247 for(i=0; i<50; i++)
248 {
249 l = getc(fptr);
250 h = getc(fptr);
251 BATRAM[i] = h*256+l;
252 }
253
254 fclose(fptr);
255 }
256
257
258 #if PRO_MEM_PRESENT
259 /* Initialize memory expansion board ROM */
260
261 fptr = fopen("mem.rom","r");
262
263 if (fptr == NULL)
264 {
265 printf("Unable to open mem.rom\n");
266 exit(0);
267 }
268
269 for(i=0; i<1024; i++)
270 {
271 l = getc(fptr);
272 MEMROM[i] = l;
273 }
274
275 fclose(fptr);
276 #endif
277
278
279 /* Make default serial port assignments */
280
281 pro_la50device = &pro_null;
282 pro_la50device_port = 0;
283
284 pro_kb = &pro_lk201;
285 pro_kb_port = 0;
286
287 pro_ptr = &pro_null;
288 pro_ptr_port = 0;
289
290 pro_com = &pro_null;
291 pro_com_port = 0;
292
293
294 /* Make default rd assignments */
295
296 if (pro_rd_file != NULL)
297 free(pro_rd_file);
298 pro_rd_file = strdup("pos32.rd");
299
300 pro_rd_heads = 0;
301 pro_rd_cyls = 0;
302 pro_rd_secs = 0;
303
304 /* Make default rx assignments */
305
306 for(k=0; k<4; k++)
307 {
308 if (pro_rx_file[k] != NULL)
309 free(pro_rx_file[k]);
310 pro_rx_file[k] = strdup("");
311 }
312
313 /* Make default disk image directory assignments */
314
315 for(k=0; k<4; k++)
316 {
317 if (pro_rx_dir[k] != NULL)
318 free(pro_rx_dir[k]);
319 pro_rx_dir[k] = strdup("./");
320 }
321
322 if (pro_rd_dir != NULL)
323 free(pro_rd_dir);
324 pro_rd_dir = strdup("./");
325
326 /* Read configuration file */
327
328 file_found = 0;
329
330 /* First try home directory */
331
332 /* If $HOME is not defined, then look for /.xhomerrc */
333
334 sprintf(filename, "%.1000s/%s", getenv("HOME")?getenv("HOME"):"", ".xhomerrc");
335 fptr = fopen(filename,"r");
336
337 if (fptr != NULL)
338 file_found = 1;
339 else
340 {
341 printf("%s not found\n", filename);
342
343 /* Get current working directory. If path exceeds ~1000 characters,
344 simply use "./" */
345
346 if (getcwd(str1, 1000) == NULL)
347 sprintf(str1, ".");
348
349 sprintf(filename, "%s/%s", str1, "xhomer.cfg");
350 fptr = fopen(filename,"r");
351
352 if (fptr != NULL)
353 file_found = 1;
354 else
355 printf("%s not found\n", filename);
356 }
357
358 if (!file_found)
359 {
360 printf("Unable to open ~/.xhomerrc or xhomer.cfg - using built-in defaults\n");
361 }
362 else
363 {
364 printf("Using %s\n", filename);
365
366 linenum = 0;
367 do
368 {
369 linenum++;
370 eofptr = fgets(str1, 1024, fptr);
371 if (eofptr != 0)
372 {
373 /* Remove control characters, spaces and comments */
374
375 j = 0;
376
377 for(i=0; i<=strlen(str1); i++)
378 if (str1[i] == '#')
379 {
380 str2[j++] = 0;
381 break;
382 }
383 else if ((str1[i] > 32) || (str1[i] == 0))
384 str2[j++] = str1[i];
385
386 /* Filter blank lines */
387
388 if (strlen(str2) != 0)
389 {
390 /* Extract argument */
391
392 /* XXX should these be freed? */
393
394 stra = strtok(str2, "=");
395
396 /* Extract up to four parameters */
397
398 numpar = 0; /* # of parameters found */
399
400 do
401 {
402 strv[numpar] = strtok(NULL, ",");
403 if (strv[numpar] == NULL)
404 break;
405 numpar++;
406 }
407 while (numpar < MAXPAR);
408
409 /* Make assignments */
410
411 error = 0;
412
413 /* RD hard drive */
414
415 if ((i = scmp(stra, "rd", 0, 1, 4, numpar)) > -1)
416 {
417 if (pro_rd_file != NULL)
418 free(pro_rd_file);
419 pro_rd_file = strdup(strv[0]);
420
421 /* Check if geometry is defined */
422
423 if (numpar == 4)
424 {
425 pro_rd_heads = atoi(strv[1]);
426 pro_rd_cyls = atoi(strv[2]);
427 pro_rd_secs = atoi(strv[3]);
428 }
429 }
430
431 /* RX floppy */
432
433 else if ((i = scmp(stra, "rx", 3, 1, 1, numpar)) > -1)
434 {
435 if (pro_rx_file[i] != NULL)
436 free(pro_rx_file[i]);
437 pro_rx_file[i] = strdup(strv[0]);
438
439 /* Close drive */
440
441 pro_rx_closed[i] = 1;
442 }
443
444 /* RD image directory */
445
446 else if (scmp(stra, "rd_dir", -1, 1, 1, numpar) > -1)
447 {
448 if (pro_rd_dir != NULL)
449 free(pro_rd_dir);
450 pro_rd_dir = strdup(strv[0]);
451
452 len = strlen(pro_rd_dir);
453
454 if (pro_rd_dir[len-1] != '/')
455 {
456 strtmp = strdup(pro_rd_dir);
457 free(pro_rd_dir);
458 pro_rd_dir = malloc(len+2);
459 strcpy(pro_rd_dir, strtmp);
460 strcat(pro_rd_dir, "/");
461 free(strtmp);
462 }
463 }
464
465 /* RX image directory */
466
467 else if (scmp(stra, "rx_dir", -1, 1, 1, numpar) > -1)
468 {
469 for(k=0; k<4; k++)
470 {
471 if (pro_rx_dir[k] != NULL)
472 free(pro_rx_dir[k]);
473 pro_rx_dir[k] = strdup(strv[0]);
474
475 len = strlen(pro_rx_dir[k]);
476
477 if (pro_rx_dir[k][len-1] != '/')
478 {
479 strtmp = strdup(pro_rx_dir[k]);
480 free(pro_rx_dir[k]);
481 pro_rx_dir[k] = malloc(len+2);
482 strcpy(pro_rx_dir[k], strtmp);
483 strcat(pro_rx_dir[k], "/");
484 free(strtmp);
485 }
486 }
487 }
488
489 /* Serial device names */
490
491 else if ((i = scmp(stra, "serial", 3, 1, 1, numpar)) > -1)
492 {
493 if (pro_serial_devname[i] != NULL)
494 free(pro_serial_devname[i]);
495 pro_serial_devname[i] = strdup(strv[0]);
496 }
497
498 /* LA50 device */
499
500 else if (scmp(stra, "la50", -1, 1, 1, numpar) > -1)
501 {
502 if (assign_serial(strv[0], &pro_la50device, &pro_la50device_port) == -1)
503 error = 1;
504 }
505
506 /* Keyboard port */
507
508 else if (scmp(stra, "kb", -1, 1, 1, numpar) > -1)
509 {
510 if (assign_serial(strv[0], &pro_kb, &pro_kb_port) == -1)
511 error = 1;
512 }
513
514 /* Printer port */
515
516 else if (scmp(stra, "ptr", -1, 1, 1, numpar) > -1)
517 {
518 if (assign_serial(strv[0], &pro_ptr, &pro_ptr_port) == -1)
519 error = 1;
520 }
521
522 /* Communications port */
523
524 else if (scmp(stra, "com", -1, 1, 1, numpar) > -1)
525 {
526 if (assign_serial(strv[0], &pro_com, &pro_com_port) == -1)
527 error = 1;
528 }
529
530 /* Number of DGA framebuffers */
531
532 else if (scmp(stra, "framebuffers", -1, 1, 1, numpar) > -1)
533 {
534 i = atoi(strv[0]);
535 if ((i < 0) || (i > 3))
536 error = 1;
537 else
538 pro_screen_framebuffers = i;
539 }
540
541 /* Screen mode */
542
543 else if (scmp(stra, "screen", -1, 1, 1, numpar) > -1)
544 {
545 if (scmp(strv[0], "window", -1, 1, 1, 1) > -1)
546 pro_screen_full = 0;
547 else if (scmp(strv[0], "full", -1, 1, 1, 1) > -1)
548 pro_screen_full = 1;
549 else
550 error = 1;
551 }
552
553 /* Screen scale factors */
554
555 else if (scmp(stra, "window_scale", -1, 1, 1, numpar) > -1)
556 {
557 i = atoi(strv[0]);
558 if (i < 1)
559 error = 1;
560 else
561 pro_screen_window_scale = i;
562 }
563
564 else if (scmp(stra, "full_scale", -1, 1, 1, numpar) > -1)
565 {
566 i = atoi(strv[0]);
567 if (i < 1)
568 error = 1;
569 else
570 pro_screen_full_scale = i;
571 }
572
573 /* Window position */
574
575 else if (scmp(stra, "window_position", -1, 2, 2, numpar) > -1)
576 {
577 pro_window_x = atoi(strv[0]);
578 pro_window_y = atoi(strv[1]);
579 }
580
581 /* Screen gamma */
582
583 else if (scmp(stra, "screen_gamma", -1, 1, 1, numpar) > -1)
584 {
585 pro_screen_gamma = atoi(strv[0]);
586 }
587
588 /* la50 DPI */
589
590 else if (scmp(stra, "la50_dpi", -1, 1, 1, numpar) > -1)
591 {
592 i = atoi(strv[0]);
593
594 if ((i != 300) && (i != 600))
595 error = 1;
596 else
597 pro_la50_dpi = i;
598 }
599
600 /* Force year */
601
602 else if (scmp(stra, "force_year", -1, 1, 1, numpar) > -1)
603 {
604 i = atoi(strv[0]);
605
606 if ((i < -1) || (i > 99))
607 error = 1;
608 else
609 pro_force_year = i;
610 }
611
612 /* Printer port maintenance mode */
613
614 else if (scmp(stra, "maint_mode", -1, 1, 1, numpar) > -1)
615 {
616 if (scmp(strv[0], "off", -1, 1, 1, 1) > -1)
617 pro_maint_mode = 0;
618 else if (scmp(strv[0], "on", -1, 1, 1, 1) > -1)
619 pro_maint_mode = 1;
620 else
621 error = 1;
622 }
623
624 /* Periodic interrupt throttle mode */
625
626 else if (scmp(stra, "int_throttle", -1, 1, 1, numpar) > -1)
627 {
628 if (scmp(strv[0], "off", -1, 1, 1, 1) > -1)
629 pro_int_throttle = 0;
630 else if (scmp(strv[0], "on", -1, 1, 1, 1) > -1)
631 pro_int_throttle = 1;
632 else
633 error = 1;
634 }
635
636 else if (scmp(stra, "nine_workaround", -1, 1, 1, numpar) > -1)
637 {
638 if (scmp(strv[0], "off", -1, 1, 1, 1) > -1)
639 pro_nine_workaround = 0;
640 else if (scmp(strv[0], "on", -1, 1, 1, 1) > -1)
641 pro_nine_workaround = 1;
642 else
643 error = 1;
644 }
645
646 else if (scmp(stra, "libc_workaround", -1, 1, 1, numpar) > -1)
647 {
648 if (scmp(strv[0], "off", -1, 1, 1, 1) > -1)
649 pro_libc_workaround = 0;
650 else if (scmp(strv[0], "on", -1, 1, 1, 1) > -1)
651 pro_libc_workaround = 1;
652 else
653 error = 1;
654 }
655
656 else if (scmp(stra, "lp_workaround", -1, 1, 1, numpar) > -1)
657 {
658 if (scmp(strv[0], "off", -1, 1, 1, 1) > -1)
659 pro_lp_workaround = 0;
660 else if (scmp(strv[0], "on", -1, 1, 1, 1) > -1)
661 pro_lp_workaround = 1;
662 else
663 error = 1;
664 }
665
666 else if (scmp(stra, "pcm", -1, 1, 1, numpar) > -1)
667 {
668 if (scmp(strv[0], "off", -1, 1, 1, 1) > -1)
669 pro_screen_pcm = 0;
670 else if (scmp(strv[0], "on", -1, 1, 1, 1) > -1)
671 pro_screen_pcm = 1;
672 else
673 error = 1;
674 }
675
676 else
677 error = 1;
678
679 if (error == 1)
680 printf("Config file error line %d: %s", linenum, str1);
681 }
682 }
683 }
684 while (eofptr != 0);
685 fclose(fptr);
686 }
687
688
689 pro_eq_reset();
690
691 pro_int_reset();
692
693 pro_clk_reset();
694
695 pro_mem_reset();
696
697 pro_kb_reset();
698
699 pro_ptr_reset();
700
701 pro_com_reset();
702
703 pro_rx_reset();
704
705 pro_rd_reset();
706
707 pro_menu_reset();
708
709 pro_vid_reset();
710
711 #ifdef TRACE
712 trace_reset();
713 #endif
714
715 #ifdef IOTRACE
716 iotrace_reset();
717 #endif
718 }
719
720
721 /* Exit routine */
722
pro_exit()723 void pro_exit ()
724 {
725 FILE *fptr;
726 unsigned char h, l;
727 int i;
728
729
730 /* Write battery-backed RAM data back to file */
731
732 fptr = fopen("bat.ram","w");
733
734 if (fptr == NULL)
735 {
736 printf("Unable to write to bat.ram\n");
737 }
738 else
739 {
740 for(i=0; i<50; i++)
741 {
742 l = BATRAM[i] & 0xff;
743 h = (BATRAM[i] >> 8) & 0xff;
744 putc(l, fptr);
745 putc(h, fptr);
746 }
747
748 fclose(fptr);
749 }
750
751 pro_mem_exit();
752
753 pro_rx_exit();
754
755 pro_rd_exit();
756
757 pro_kb_exit();
758
759 pro_ptr_exit();
760
761 pro_com_exit();
762
763 pro_vid_exit();
764
765 /* Call scp_tty to restore terminal settings */
766
767 ttclose();
768
769 exit(0);
770 }
771 #endif
772