fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 409 lines 8.1 kB view raw
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}