fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/arch/macplus/main.c *
7 * Created: 2007-04-15 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2007-2022 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 "cmd_68k.h"
25#include "macplus.h"
26#include "msg.h"
27#include "sony.h"
28
29#include <stdarg.h>
30#include <time.h>
31
32#include <unistd.h>
33#include <signal.h>
34
35#include <lib/cfg.h>
36#include <lib/cmd.h>
37#include <lib/console.h>
38#include <lib/getopt.h>
39#include <lib/log.h>
40#include <lib/monitor.h>
41#include <lib/path.h>
42#include <lib/sysdep.h>
43
44#include <libini/libini.h>
45
46#ifdef PCE_ENABLE_SDL
47#include <SDL.h>
48#endif
49
50
51const char *par_terminal = NULL;
52
53unsigned par_disk_boot = 0;
54
55macplus_t *par_sim = NULL;
56
57unsigned par_sig_int = 0;
58
59monitor_t par_mon;
60
61ini_sct_t *par_cfg = NULL;
62
63static ini_strings_t par_ini_str;
64
65
66static pce_option_t opts[] = {
67 { '?', 0, "help", NULL, "Print usage information" },
68 { 'b', 1, "boot-disk", "int", "Set the boot disk [none]" },
69 { 'c', 1, "config", "string", "Set the config file name [none]" },
70 { 'd', 1, "path", "string", "Add a directory to the search path" },
71 { 'i', 1, "ini-prefix", "string", "Add an ini string before the config file" },
72 { 'I', 1, "ini-append", "string", "Add an ini string after the config file" },
73 { 'l', 1, "log", "string", "Set the log file name [none]" },
74 { 'p', 1, "cpu", "string", "Set the CPU model" },
75 { 'q', 0, "quiet", NULL, "Set the log level to error [no]" },
76 { 'r', 0, "run", NULL, "Start running immediately [no]" },
77 { 'R', 0, "no-monitor", NULL, "Never stop running [no]" },
78 { 's', 1, "speed", "int", "Set the CPU speed" },
79 { 't', 1, "terminal", "string", "Set the terminal device" },
80 { 'v', 0, "verbose", NULL, "Set the log level to debug [no]" },
81 { 'V', 0, "version", NULL, "Print version information" },
82 { -1, 0, NULL, NULL, NULL }
83};
84
85
86static
87void print_help (void)
88{
89 pce_getopt_help (
90 "pce-macplus: Macintosh Plus emulator",
91 "usage: pce-macplus [options]",
92 opts
93 );
94
95 fflush (stdout);
96}
97
98static
99void print_version (void)
100{
101 fputs (
102 "pce-macplus version " PCE_VERSION_STR
103 "\n\n"
104 "Copyright (C) 2007-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n",
105 stdout
106 );
107
108 fflush (stdout);
109}
110
111static
112void mac_log_banner (void)
113{
114 pce_log_inf (
115 "pce-macplus version " PCE_VERSION_STR "\n"
116 "Copyright (C) 2007-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n"
117 );
118}
119
120void sig_int (int s)
121{
122 par_sig_int = 1;
123}
124
125void sig_segv (int s)
126{
127 pce_set_fd_interactive (0, 1);
128
129 fprintf (stderr, "pce-macplus: segmentation fault\n");
130 fflush (stderr);
131
132 if ((par_sim != NULL) && (par_sim->cpu != NULL)) {
133 mac_prt_state (par_sim, "cpu");
134 }
135
136 exit (1);
137}
138
139void sig_term (int s)
140{
141 pce_set_fd_interactive (0, 1);
142
143 fprintf (stderr, "pce-macplus: signal %d\n", s);
144 fflush (stderr);
145
146 exit (1);
147}
148
149static
150void mac_atexit (void)
151{
152 pce_set_fd_interactive (0, 1);
153}
154
155static
156int cmd_get_sym (macplus_t *sim, const char *sym, unsigned long *val)
157{
158 if (e68_get_reg (sim->cpu, sym, val) == 0) {
159 return (0);
160 }
161
162 return (1);
163}
164
165static
166int cmd_set_sym (macplus_t *sim, const char *sym, unsigned long val)
167{
168 if (e68_set_reg (sim->cpu, sym, val) == 0) {
169 return (0);
170 }
171
172 return (1);
173}
174
175void sim_stop (void)
176{
177 macplus_t *sim = par_sim;
178
179 pce_prt_sep ("BREAK");
180 mac_prt_state (sim, "cpu");
181
182 mac_set_msg (sim, "emu.stop", NULL);
183}
184
185void mac_stop (macplus_t *sim)
186{
187 if (sim == NULL) {
188 sim = par_sim;
189 }
190
191 mac_set_msg (sim, "emu.stop", NULL);
192}
193
194void mac_log_deb (const char *msg, ...)
195{
196 va_list va;
197 unsigned long pc;
198
199 if (par_sim != NULL) {
200 pc = e68_get_last_pc (par_sim->cpu, 0);
201 }
202 else {
203 pc = 0;
204 }
205
206 pce_log (MSG_DEB, "[%06lX] ", pc & 0xffffff);
207
208 va_start (va, msg);
209 pce_log_va (MSG_DEB, msg, va);
210 va_end (va);
211}
212
213int main (int argc, char *argv[])
214{
215 int r;
216 char **optarg;
217 int run, nomon;
218 unsigned drive;
219 char *cfg;
220 ini_sct_t *sct;
221
222 cfg = NULL;
223 run = 0;
224 nomon = 0;
225
226 pce_log_init();
227 pce_log_add_fp (stderr, 0, MSG_INF);
228
229 par_cfg = ini_sct_new (NULL);
230
231 if (par_cfg == NULL) {
232 return (1);
233 }
234
235 ini_str_init (&par_ini_str);
236
237 while (1) {
238 r = pce_getopt (argc, argv, &optarg, opts);
239
240 if (r == GETOPT_DONE) {
241 break;
242 }
243
244 if (r < 0) {
245 return (1);
246 }
247
248 switch (r) {
249 case '?':
250 print_help();
251 return (0);
252
253 case 'V':
254 print_version();
255 return (0);
256
257 case 'b':
258 drive = (unsigned) strtoul (optarg[0], NULL, 0);
259
260 if ((drive >= 1) && (drive <= 8)) {
261 par_disk_boot |= 1U << (drive - 1);
262 }
263 break;
264
265 case 'c':
266 cfg = optarg[0];
267 break;
268
269 case 'd':
270 pce_path_set (optarg[0]);
271 break;
272
273 case 'i':
274 if (ini_read_str (par_cfg, optarg[0])) {
275 fprintf (stderr,
276 "%s: error parsing ini string (%s)\n",
277 argv[0], optarg[0]
278 );
279 return (1);
280 }
281 break;
282
283 case 'I':
284 ini_str_add (&par_ini_str, optarg[0], "\n", NULL);
285 break;
286
287 case 'l':
288 pce_log_add_fname (optarg[0], MSG_DEB);
289 break;
290
291 case 'p':
292 ini_str_add (&par_ini_str, "cpu.model = \"",
293 optarg[0], "\"\n"
294 );
295 break;
296
297 case 'q':
298 pce_log_set_level (stderr, MSG_ERR);
299 break;
300
301 case 'r':
302 run = 1;
303 break;
304
305 case 'R':
306 nomon = 1;
307 break;
308
309 case 's':
310 ini_str_add (&par_ini_str, "cpu.speed = ",
311 optarg[0], "\n"
312 );
313 break;
314
315 case 't':
316 par_terminal = optarg[0];
317 break;
318
319 case 'v':
320 pce_log_set_level (stderr, MSG_DEB);
321 break;
322
323 case 0:
324 fprintf (stderr, "%s: unknown option (%s)\n",
325 argv[0], optarg[0]
326 );
327 return (1);
328
329 default:
330 return (1);
331 }
332 }
333
334 mac_log_banner();
335
336 if (pce_load_config (par_cfg, cfg)) {
337 return (1);
338 }
339
340 sct = ini_next_sct (par_cfg, NULL, "macplus");
341
342 if (sct == NULL) {
343 sct = par_cfg;
344 }
345
346 if (ini_str_eval (&par_ini_str, sct, 1)) {
347 return (1);
348 }
349
350 atexit (mac_atexit);
351
352#ifdef PCE_ENABLE_SDL
353 SDL_Init (0);
354#endif
355
356 pce_path_ini (sct);
357
358 signal (SIGINT, &sig_int);
359 signal (SIGSEGV, &sig_segv);
360 signal (SIGTERM, &sig_term);
361
362 pce_console_init (stdin, stdout);
363
364 par_sim = mac_new (sct);
365
366 mon_init (&par_mon);
367 mon_set_cmd_fct (&par_mon, mac_cmd, par_sim);
368 mon_set_msg_fct (&par_mon, mac_set_msg, par_sim);
369 mon_set_get_mem_fct (&par_mon, par_sim->mem, mem_get_uint8);
370 mon_set_set_mem_fct (&par_mon, par_sim->mem, mem_set_uint8);
371 mon_set_set_memrw_fct (&par_mon, par_sim->mem, mem_set_uint8_rw);
372 mon_set_memory_mode (&par_mon, 0);
373
374 cmd_init (par_sim, cmd_get_sym, cmd_set_sym);
375 mac_cmd_init (par_sim, &par_mon);
376
377 mac_reset (par_sim);
378
379 if (nomon) {
380 while (par_sim->brk != PCE_BRK_ABORT) {
381 mac_run (par_sim);
382 }
383 }
384 else if (run) {
385 mac_run (par_sim);
386 if (par_sim->brk != PCE_BRK_ABORT) {
387 pce_puts ("\n");
388 }
389 }
390 else {
391 pce_puts ("type 'h' for help\n");
392 }
393
394 if (par_sim->brk != PCE_BRK_ABORT) {
395 mon_run (&par_mon);
396 }
397
398 mac_del (par_sim);
399
400#ifdef PCE_ENABLE_SDL
401 SDL_Quit();
402#endif
403
404 mon_free (&par_mon);
405 pce_console_done();
406 pce_log_done();
407
408 return (0);
409}