fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 276 lines 5.5 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/arch/dos/main.c * 7 * Created: 2012-12-30 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2012-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 "dos.h" 25#include "exec.h" 26#include "path.h" 27 28#include <stdio.h> 29#include <stdlib.h> 30#include <string.h> 31 32#include <signal.h> 33 34#include <lib/getopt.h> 35#include <lib/sysdep.h> 36 37 38static pce_option_t opts[] = { 39 { '?', 0, "help", NULL, "Print usage information" }, 40 { 'c', 0, "command", NULL, "Set the DOS command" }, 41 { 'd', 2, "drive", "char string", "Attach a host path to a DOS drive" }, 42 { 'e', 1, "setenv", "string", "Add a string to the environment" }, 43 { 'l', 0, "log-int", NULL, "Log interrupts [no]" }, 44 { 'm', 1, "memory", "int", "Set the memory size in KiB [640]" }, 45 { 'V', 0, "version", NULL, "Print version information" }, 46 { -1, 0, NULL, NULL, NULL } 47}; 48 49 50const char *arg0 = NULL; 51 52static const char *par_drives[26]; 53 54static unsigned par_env_cnt = 0; 55static unsigned char *par_env = NULL; 56 57 58static 59void print_help (void) 60{ 61 pce_getopt_help ( 62 "pce-dos: Run DOS applications", 63 "usage: pce-dos [options] [program [options]]", 64 opts 65 ); 66 67 fflush (stdout); 68} 69 70static 71void print_version (void) 72{ 73 fputs ( 74 "pce-dos version " PCE_VERSION_STR 75 "\n\n" 76 "Copyright (C) 2012-" PCE_YEAR " Hampa Hug <hampa@hampa.ch>\n", 77 stdout 78 ); 79 80 fflush (stdout); 81} 82 83static 84void sig_int (int s) 85{ 86 fprintf (stderr, "pce-dos: sigint\n"); 87 fflush (stderr); 88 exit (1); 89} 90 91static 92void sig_term (int s) 93{ 94 fprintf (stderr, "pce-dos: sigterm\n"); 95 fflush (stderr); 96 exit (1); 97} 98 99static 100void sig_segv (int s) 101{ 102 fprintf (stderr, "pce-dos: segmentation fault\n"); 103 fflush (stderr); 104 exit (1); 105} 106 107static 108int set_drive (const char *drv, const char *name) 109{ 110 unsigned d; 111 112 if ((drv[0] != 0) && (drv[1] == 0)) { 113 if ((drv[0] >= 'a') && (drv[0] <= 'z')) { 114 d = drv[0] - 'a'; 115 } 116 else if ((drv[0] >= 'A') && (drv[0] <= 'Z')) { 117 d = drv[0] - 'Z'; 118 } 119 else { 120 return (1); 121 } 122 } 123 else { 124 d = strtoul (drv, NULL, 0); 125 } 126 127 if (d > sizeof (par_drives)) { 128 return (1); 129 } 130 131 par_drives[d] = name; 132 133 return (0); 134} 135 136static 137int env_add (const char *str) 138{ 139 unsigned cnt, max; 140 unsigned char *tmp; 141 142 cnt = strlen (str); 143 max = par_env_cnt + cnt + (par_env_cnt > 0); 144 145 if ((tmp = realloc (par_env, max)) == NULL) { 146 return (1); 147 } 148 149 if (par_env_cnt > 0) { 150 tmp[par_env_cnt++] = 0; 151 } 152 153 memcpy (tmp + par_env_cnt, str, cnt); 154 155 par_env = tmp; 156 par_env_cnt = max; 157 158 return (0); 159} 160 161int main (int argc, char **argv) 162{ 163 int r; 164 unsigned i; 165 char **optarg; 166 char *prog_dos, *prog_host; 167 char log_int; 168 unsigned mem; 169 dos_t sim; 170 171 arg0 = argv[0]; 172 173 mem = 640; 174 log_int = 0; 175 176 while (1) { 177 r = pce_getopt (argc, argv, &optarg, opts); 178 179 if (r == GETOPT_DONE) { 180 return (1); 181 } 182 183 if (r < 0) { 184 return (1); 185 } 186 187 if ((r == 0) || (r == 'c')) { 188 break; 189 } 190 191 switch (r) { 192 case '?': 193 print_help(); 194 return (0); 195 196 case 'V': 197 print_version(); 198 return (0); 199 200 case 'd': 201 if (set_drive (optarg[0], optarg[1])) { 202 return (1); 203 } 204 break; 205 206 case 'e': 207 if (env_add (optarg[0])) { 208 return (1); 209 } 210 break; 211 212 case 'l': 213 log_int = 1; 214 break; 215 216 case 'm': 217 mem = strtoul (optarg[0], NULL, 0); 218 break; 219 220 default: 221 return (1); 222 } 223 } 224 225 signal (SIGINT, sig_int); 226 signal (SIGTERM, sig_term); 227 signal (SIGSEGV, sig_segv); 228 229 if (sim_init (&sim, mem)) { 230 return (1); 231 } 232 233 sim.log_int = log_int || 0; 234 235 for (i = 0; i < 26; i++) { 236 if (par_drives[i] != NULL) { 237 if (sim_set_drive (&sim, i, par_drives[i])) { 238 return (1); 239 } 240 } 241 } 242 243 if ((prog_dos = sim_get_dos_full_name (&sim, optarg[0])) == NULL) { 244 return (1); 245 } 246 247 if ((prog_host = sim_get_host_name (&sim, prog_dos)) == NULL) { 248 return (1); 249 } 250 251 if (par_env_cnt == 0) { 252 if (env_add ("PATH=C:\\")) { 253 return (1); 254 } 255 } 256 257 if (sim_init_env (&sim, prog_dos, par_env, par_env_cnt)) { 258 return (1); 259 } 260 261 if (sim_exec (&sim, prog_host)) { 262 fprintf (stderr, "%s: loading exe file failed (%s)\n", arg0, optarg[0]); 263 return (1); 264 } 265 266 if (sim_init_args (&sim, (const char **) optarg + 1)) { 267 fprintf (stderr, "%s: argument list too long\n", arg0); 268 return (1); 269 } 270 271 sim_run (&sim); 272 273 sim_free (&sim); 274 275 return (0); 276}