|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * ami-rexx.c ! 5: * ! 6: * Copyright 1996 Samuel Devulder. ! 7: * ! 8: * History: ! 9: * 05/09/97: Added UAEEXE support. ! 10: */ ! 11: ! 12: #include <proto/exec.h> ! 13: #include <proto/rexxsyslib.h> ! 14: #include <proto/dos.h> ! 15: #ifndef __SASC ! 16: #include <proto/alib.h> ! 17: #endif ! 18: ! 19: #include <rexx/storage.h> ! 20: #include <rexx/errors.h> ! 21: ! 22: /* this prevent a conflict between <rexx/rexxio.h> and <sys/dirent.h> */ ! 23: #undef DT_DIR ! 24: ! 25: /****************************************************************************/ ! 26: ! 27: #include "sysconfig.h" ! 28: #include "sysdeps.h" ! 29: ! 30: #include "uae.h" ! 31: #include "config.h" ! 32: #include "options.h" ! 33: #ifdef __GNUC__ ! 34: #include "../include/memory.h" /* or else gcc includes machdep/memory.h */ ! 35: #endif ! 36: #include "custom.h" ! 37: #include "readcpu.h" ! 38: #include "newcpu.h" ! 39: #include "disk.h" ! 40: #include "gui.h" ! 41: #include "sound.h" ! 42: #include "gensound.h" ! 43: #include "uaeexe.h" ! 44: #include "threaddep/penguin.h" ! 45: #include "xwin.h" ! 46: ! 47: #include <ctype.h> ! 48: ! 49: /****************************************************************************/ ! 50: ! 51: #define UAE_PORTNAME "UAE" ! 52: #define RESULT_LEN 1024 ! 53: #define PORT_LEN 80 ! 54: #define CMD_LEN 1024 ! 55: ! 56: typedef struct ! 57: { ! 58: char port[PORT_LEN]; ! 59: char cmd_on[CMD_LEN]; ! 60: char cmd_off[CMD_LEN]; ! 61: } gui_rexx_s; ! 62: ! 63: enum {LED_POW, LED_DF0, LED_DF1, LED_DF2, LED_DF3, ! 64: NAME_DF0, NAME_DF1, NAME_DF2, NAME_DF3, ! 65: ON_EXIT, ! 66: GUI_REXX_MAX}; ! 67: ! 68: /****************************************************************************/ ! 69: ! 70: int rexx_init(void); ! 71: void rexx_exit(void); ! 72: void rexx_led(int led, int on); ! 73: void rexx_filename(int num, char *name); ! 74: void rexx_handle_events(void); ! 75: ! 76: /****************************************************************************/ ! 77: ! 78: #ifdef __GNUC__ ! 79: struct RxsLib ! 80: #else ! 81: struct Library ! 82: #endif ! 83: *RexxSysBase; ! 84: static struct MsgPort *ARexxPort; ! 85: static gui_rexx_s gui_rexx[GUI_REXX_MAX]; ! 86: static char RESULT[RESULT_LEN]; ! 87: static int led_state[5]; ! 88: ! 89: static int ADDRESS(char *hostname, char *cmd); ! 90: static int matchstr(char **line,char *pat); ! 91: static void extractstr(char **line, char *result, int len); ! 92: static int matchnum(char **line); ! 93: ! 94: /****************************************************************************/ ! 95: ! 96: extern int quit_program; /* ami-gui.c */ ! 97: extern void activate_debugger(void); /* debug.c */ ! 98: extern char *to_unix_path(char *s); /* ami-disk.c */ ! 99: extern char *from_unix_path(char *s); /* ami-disk.c */ ! 100: ! 101: /****************************************************************************/ ! 102: ! 103: int rexx_init(void) ! 104: { ! 105: quit_program = 0; ! 106: RexxSysBase = (void*)OpenLibrary("rexxsyslib.library",0L); ! 107: if(!RexxSysBase) { ! 108: fprintf(stderr, "Can't find rexxsyslib.library!\n"); ! 109: return 1; ! 110: } ! 111: if(FindPort(UAE_PORTNAME)) { ! 112: fprintf(stderr, "Port \"%s\" already exists!\n",UAE_PORTNAME); ! 113: return 1; ! 114: } ! 115: ARexxPort = CreatePort(UAE_PORTNAME,0); ! 116: if(!ARexxPort) { ! 117: fprintf(stderr, "Failed to open AREXX port \"%s\"!\n",UAE_PORTNAME); ! 118: return 1; ! 119: } ! 120: fprintf(stderr,"Rexx port \"%s\" installed.\n", UAE_PORTNAME); ! 121: rexx_handle_events(); ! 122: return 0; ! 123: } ! 124: ! 125: /****************************************************************************/ ! 126: ! 127: void rexx_exit(void) ! 128: { ! 129: if(ARexxPort) { ! 130: struct RexxMsg *msg; ! 131: gui_rexx_s *gui = &gui_rexx[ON_EXIT]; ! 132: ! 133: if(gui->port[0] && gui->cmd_on[0]) { ! 134: if(ADDRESS(gui->port, gui->cmd_on) != RC_OK) { ! 135: fprintf(stderr,"%s:%s:%s\n", gui->port, ! 136: gui->cmd_on, ! 137: RESULT); ! 138: } ! 139: gui->port[0] = '\0'; ! 140: } ! 141: Forbid(); ! 142: while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) { ! 143: msg->rm_Result1 = RC_ERROR; ! 144: msg->rm_Result2 = NULL; ! 145: ReplyMsg((void*)msg); ! 146: } ! 147: DeletePort(ARexxPort); ! 148: Permit(); ! 149: ARexxPort = NULL; ! 150: } ! 151: if(RexxSysBase) { ! 152: CloseLibrary((void*)RexxSysBase); ! 153: RexxSysBase = NULL; ! 154: } ! 155: } ! 156: ! 157: /****************************************************************************/ ! 158: ! 159: static int EJECT(char *line) ! 160: { ! 161: int drive = matchnum(&line); ! 162: if(drive<0 || drive>3) return RC_WARN; ! 163: disk_eject(drive); ! 164: sprintf(RESULT,"Drive %d ejected",drive); ! 165: return RC_OK; ! 166: } ! 167: ! 168: /****************************************************************************/ ! 169: ! 170: static int INSERT(char *line) ! 171: { ! 172: int drive = matchnum(&line); ! 173: if(drive<0 || drive>3) return RC_WARN; ! 174: if(disk_empty(drive)) { ! 175: char buff[256]; ! 176: char *name; ! 177: extractstr(&line, buff, 256); ! 178: name = to_unix_path(buff); ! 179: disk_insert(drive, name); ! 180: free(name); ! 181: } else { ! 182: sprintf(RESULT,"Drive %d not empty!",drive); ! 183: return RC_WARN; ! 184: } ! 185: return RC_OK; ! 186: } ! 187: ! 188: /****************************************************************************/ ! 189: ! 190: static void QUIT(void) ! 191: { ! 192: broken_in = 1; ! 193: regs.spcflags |= SPCFLAG_BRK; ! 194: quit_program = 1; ! 195: } ! 196: ! 197: /****************************************************************************/ ! 198: ! 199: static int QUERY(char *line) ! 200: { ! 201: char *res = NULL; ! 202: int alc = 0; ! 203: ! 204: if (matchstr(&line, "LED_POW")) res = led_state[0]?"1":"0"; ! 205: else if(matchstr(&line, "LED_DF0")) res = led_state[1]?"1":"0"; ! 206: else if(matchstr(&line, "LED_DF1")) res = led_state[2]?"1":"0"; ! 207: else if(matchstr(&line, "LED_DF2")) res = led_state[3]?"1":"0"; ! 208: else if(matchstr(&line, "LED_DF3")) res = led_state[4]?"1":"0"; ! 209: else if(matchstr(&line, "NAME_DF0")) res = from_unix_path(currprefs.df[0]), alc = 1; ! 210: else if(matchstr(&line, "NAME_DF1")) res = from_unix_path(currprefs.df[1]), alc = 1; ! 211: else if(matchstr(&line, "NAME_DF2")) res = from_unix_path(currprefs.df[2]), alc = 1; ! 212: else if(matchstr(&line, "NAME_DF3")) res = from_unix_path(currprefs.df[3]), alc = 1; ! 213: else if(matchstr(&line, "FAKEJOYSTICK")) res = currprefs.fake_joystick?"1":"0"; ! 214: else if(matchstr(&line, "DISPLAY")) res = inhibit_frame?"0":"1"; ! 215: else if(matchstr(&line, "FRAMERATE")) { ! 216: sprintf(RESULT,"%d",currprefs.framerate); ! 217: return RC_OK; ! 218: } else if(matchstr(&line, "SOUND")) { ! 219: sprintf(RESULT,"%d",sound_available?currprefs.produce_sound:-1); ! 220: return RC_OK; ! 221: } ! 222: else return RC_ERROR; ! 223: ! 224: if(res) { ! 225: strncpy(RESULT, res, RESULT_LEN); ! 226: if(alc) free(res); ! 227: } ! 228: return RC_OK; ! 229: } ! 230: ! 231: /****************************************************************************/ ! 232: ! 233: static int FEEDBACK(char *line) ! 234: { ! 235: gui_rexx_s *gui = NULL; ! 236: ! 237: if (matchstr(&line,"LED_POW")) gui = &gui_rexx[LED_POW]; ! 238: else if(matchstr(&line,"LED_DF0")) gui = &gui_rexx[LED_DF0]; ! 239: else if(matchstr(&line,"LED_DF1")) gui = &gui_rexx[LED_DF1]; ! 240: else if(matchstr(&line,"LED_DF2")) gui = &gui_rexx[LED_DF2]; ! 241: else if(matchstr(&line,"LED_DF3")) gui = &gui_rexx[LED_DF3]; ! 242: else if(matchstr(&line,"NAME_DF0")) gui = &gui_rexx[NAME_DF0]; ! 243: else if(matchstr(&line,"NAME_DF1")) gui = &gui_rexx[NAME_DF1]; ! 244: else if(matchstr(&line,"NAME_DF2")) gui = &gui_rexx[NAME_DF2]; ! 245: else if(matchstr(&line,"NAME_DF3")) gui = &gui_rexx[NAME_DF3]; ! 246: else if(matchstr(&line,"ON_EXIT")) gui = &gui_rexx[ON_EXIT]; ! 247: else return RC_ERROR; ! 248: ! 249: while(1) { ! 250: if(matchstr(&line, "ADDRESS") || ! 251: matchstr(&line, "PORT")) { ! 252: extractstr(&line, gui->port, PORT_LEN); ! 253: } else if(matchstr(&line,"COMMAND") || ! 254: matchstr(&line,"CMD") || ! 255: matchstr(&line,"CMD_ON")) { ! 256: extractstr(&line, gui->cmd_on, CMD_LEN); ! 257: } else if(matchstr(&line,"CMD_OFF")) { ! 258: extractstr(&line, gui->cmd_off, CMD_LEN); ! 259: } else break; ! 260: } ! 261: return RC_OK; ! 262: } ! 263: ! 264: /****************************************************************************/ ! 265: ! 266: static int VERSION(char *line) ! 267: { ! 268: if(matchstr(&line,"STRING")) { ! 269: sprintf(RESULT, ! 270: "UAE-%d.%d.%d � by Bernd Schmidt & contributors, " ! 271: "Amiga Port by Samuel Devulder.", ! 272: (version / 100) % 10, (version / 10) % 10, version % 10); ! 273: } else if(matchstr(&line,"NUM")) { ! 274: sprintf(RESULT,"%d",version); ! 275: } else if(matchstr(&line,"AUTHOR")) { ! 276: sprintf(RESULT,"� by Bernd Schmidt & contributors"); ! 277: } else if(matchstr(&line,"PORT")) { ! 278: sprintf(RESULT,"Amiga Port by Samuel Devulder"); ! 279: } else return RC_ERROR; ! 280: return RC_OK; ! 281: } ! 282: ! 283: /****************************************************************************/ ! 284: ! 285: static int FRAMERATE(char *line) ! 286: { ! 287: int num; ! 288: num = matchnum(&line); ! 289: if(num>=1 && num<=20) { ! 290: currprefs.framerate = num; ! 291: } else { ! 292: sprintf(RESULT,"Invalid frame rate: %d\n", num); ! 293: return RC_WARN; ! 294: } ! 295: return RC_OK; ! 296: } ! 297: ! 298: /****************************************************************************/ ! 299: ! 300: static int FAKEJOYSTICK(char *line) ! 301: { ! 302: if (matchstr(&line,"ON")) currprefs.fake_joystick = 2; ! 303: else if(matchstr(&line,"OFF")) currprefs.fake_joystick = 0; ! 304: else if(matchstr(&line,"TOGGLE")) currprefs.fake_joystick = ! 305: currprefs.fake_joystick?0:2; ! 306: else return RC_ERROR; ! 307: return RC_OK; ! 308: } ! 309: ! 310: /****************************************************************************/ ! 311: ! 312: static int DISPLAY(char *line) ! 313: { ! 314: if (matchstr(&line,"ON")) inhibit_frame = 0; ! 315: else if(matchstr(&line,"OFF")) inhibit_frame = 1; ! 316: else if(matchstr(&line,"TOGGLE")) inhibit_frame = inhibit_frame?0:1; ! 317: else return RC_ERROR; ! 318: return RC_OK; ! 319: } ! 320: ! 321: /****************************************************************************/ ! 322: ! 323: static int SOUND(char *line) ! 324: { ! 325: if(!sound_available) { ! 326: sprintf(RESULT,"Sound not available!"); ! 327: return RC_WARN; ! 328: } ! 329: ! 330: if (matchstr(&line,"ON")) currprefs.produce_sound = 2; ! 331: else if(matchstr(&line,"OFF")) currprefs.produce_sound = 1; ! 332: else if(matchstr(&line,"BEST")) currprefs.produce_sound = 3; ! 333: else if(matchstr(&line,"TOGGLE")) currprefs.produce_sound = ! 334: currprefs.produce_sound<=1?2:1; ! 335: else return RC_ERROR; ! 336: return RC_OK; ! 337: } ! 338: ! 339: /****************************************************************************/ ! 340: ! 341: static int UAEEXE(char *line) ! 342: { ! 343: if(uaeexe(line)) { ! 344: sprintf(RESULT,"Remote CLI failed!"); ! 345: return RC_WARN; ! 346: } ! 347: return RC_OK; ! 348: } ! 349: ! 350: /****************************************************************************/ ! 351: ! 352: static int process_cmd(char *line) ! 353: { ! 354: RESULT[0] = '\0'; ! 355: if (matchstr(&line, "EJECT")) return EJECT(line); ! 356: else if(matchstr(&line, "INSERT")) return INSERT(line); ! 357: else if(matchstr(&line, "QUERY")) return QUERY(line); ! 358: else if(matchstr(&line, "FEEDBACK")) return FEEDBACK(line); ! 359: else if(matchstr(&line, "VERSION")) return VERSION(line); ! 360: else if(matchstr(&line, "BYE")) QUIT(); ! 361: else if(matchstr(&line, "QUIT")) QUIT(); ! 362: else if(matchstr(&line, "DEBUG")) activate_debugger(); ! 363: else if(matchstr(&line, "RESET")) m68k_reset(); ! 364: else if(matchstr(&line, "DISPLAY")) return DISPLAY(line); ! 365: else if(matchstr(&line, "FRAMERATE")) return FRAMERATE(line); ! 366: else if(matchstr(&line, "FAKEJOYSTICK")) return FAKEJOYSTICK(line); ! 367: else if(matchstr(&line, "SOUND")) return SOUND(line); ! 368: else if(matchstr(&line, "UAEEXE")) return UAEEXE(line); ! 369: else return RC_ERROR; ! 370: return RC_OK; ! 371: } ! 372: ! 373: /****************************************************************************/ ! 374: ! 375: void rexx_handle_events(void) ! 376: { ! 377: struct RexxMsg *msg; ! 378: while((msg = (struct RexxMsg*)GetMsg(ARexxPort))) { ! 379: if(!(msg->rm_Action & RXCOMM)) { ! 380: fprintf(stderr,"Unknown action '%08X' recieved!\n", ! 381: msg->rm_Action); ! 382: continue; ! 383: } ! 384: msg->rm_Result1 = process_cmd(msg->rm_Args[0]); ! 385: msg->rm_Result2 = NULL; ! 386: if(msg->rm_Action & RXFF_RESULT) { ! 387: msg->rm_Result2 = (LONG)CreateArgstring(RESULT,strlen(RESULT)); ! 388: } ! 389: ReplyMsg((void*)msg); ! 390: } ! 391: } ! 392: ! 393: /****************************************************************************/ ! 394: ! 395: void rexx_led(int led, int on) ! 396: { ! 397: gui_rexx_s *gui = NULL; ! 398: ! 399: if(led < 0 || led > 4) return; ! 400: led_state[led] = on; ! 401: ! 402: if(led == 0) gui = &gui_rexx[LED_POW]; ! 403: if(led == 1) gui = &gui_rexx[LED_DF0]; ! 404: if(led == 2) gui = &gui_rexx[LED_DF1]; ! 405: if(led == 3) gui = &gui_rexx[LED_DF2]; ! 406: if(led == 4) gui = &gui_rexx[LED_DF3]; ! 407: ! 408: if(gui->port[0] && gui->cmd_on[0] && gui->cmd_off[0]) { ! 409: if(ADDRESS(gui->port, on ? gui->cmd_on : gui->cmd_off) != RC_OK) { ! 410: fprintf(stderr,"%s:%s:%s\n", gui->port, ! 411: on ? gui->cmd_on : gui->cmd_off, ! 412: RESULT); ! 413: } ! 414: } ! 415: } ! 416: ! 417: /****************************************************************************/ ! 418: ! 419: void rexx_filename(int num, char *filename) ! 420: { ! 421: gui_rexx_s *gui = NULL; ! 422: if(num < 0 || num > 3) return; ! 423: gui = &gui_rexx[NAME_DF0 + num]; ! 424: if(gui->port[0] && gui->cmd_on[0]) { ! 425: char buf[CMD_LEN]; ! 426: if(!(filename = from_unix_path(filename))) return; ! 427: sprintf(buf, gui->cmd_on, filename); ! 428: free(filename); ! 429: if(ADDRESS(gui->port, buf) != RC_OK) { ! 430: fprintf(stderr,"%s:%s:%s\n", gui->port, buf, RESULT); ! 431: } ! 432: } ! 433: } ! 434: ! 435: /****************************************************************************/ ! 436: /* send a message to an AREXX port. ! 437: */ ! 438: static int ADDRESS(char *hostname, char *cmd) ! 439: { ! 440: struct MsgPort *RexxPort, ! 441: *ReplyPort; ! 442: struct RexxMsg *HostMsg, ! 443: *answer; ! 444: int result = RC_WARN; ! 445: ! 446: if(!stricmp(hostname, "COMMAND")) { ! 447: return SystemTagList(cmd,NULL); ! 448: } ! 449: ! 450: if((RexxPort = (void *)FindPort(hostname))) { ! 451: if((ReplyPort = (void *)CreateMsgPort())) { ! 452: if((HostMsg = CreateRexxMsg(ReplyPort, NULL, hostname))) { ! 453: if((HostMsg->rm_Args[0] = CreateArgstring(cmd,strlen(cmd)))) { ! 454: HostMsg->rm_Action = RXCOMM | RXFF_RESULT; ! 455: PutMsg(RexxPort, (void*)HostMsg); ! 456: WaitPort(ReplyPort); ! 457: while(!(answer = (void *)GetMsg(ReplyPort))); ! 458: result = answer->rm_Result1; ! 459: if(result == RC_OK) { ! 460: if(answer->rm_Result2) { ! 461: strncpy(RESULT,(char *)answer->rm_Result2,RESULT_LEN); ! 462: DeleteArgstring((char *)answer->rm_Result2); ! 463: } else RESULT[0] = '\0'; ! 464: } ! 465: DeleteArgstring(HostMsg->rm_Args[0]); ! 466: } else strcpy(RESULT, "Can't create argstring!"); ! 467: DeleteRexxMsg(HostMsg); ! 468: } else strcpy(RESULT, "Can't create rexx message!"); ! 469: DeleteMsgPort(ReplyPort); ! 470: } else strcpy(RESULT, "Can't alloc reply port!"); ! 471: } else sprintf(RESULT, "Port \"%s\" not found!",hostname); ! 472: return result; ! 473: } ! 474: ! 475: /****************************************************************************/ ! 476: /* argument parsing routines ! 477: */ ! 478: static int matchstr(char **line,char *pat) ! 479: { ! 480: char *s = *line; ! 481: char match = 0; ! 482: while(isspace(*s)) ++s; ! 483: if(*s=='\"' || *s== '\'') match = *s++; ! 484: while(*s && (tolower(*s)==tolower(*pat)) && (!match || *s!=match)) {++s;++pat;} ! 485: if(match && *s==match && s[1]) ++s; ! 486: if(!*pat && (!*s || isspace(*s))) { ! 487: while(isspace(*s)) ++s; ! 488: *line = s; ! 489: return 1; ! 490: } ! 491: return 0; ! 492: } ! 493: ! 494: /****************************************************************************/ ! 495: ! 496: static void extractstr(char **line, char *result, int len) ! 497: { ! 498: char *s = *line; ! 499: char match = 0; ! 500: ! 501: while(isspace(*s)) ++s; ! 502: ! 503: if(*s=='\"' || *s=='\'') match = *s++; ! 504: while(*s && *s != match) { ! 505: if(*s == '\\' && (s[1] == '\'' || s[1] == '\"')) ++s; ! 506: if(len > 1) {*result++ = *s;--len;} ! 507: ++s; ! 508: if(!match && isspace(*s)) break; ! 509: } ! 510: if(match && *s == match) ++s; ! 511: while(isspace(*s)) ++s; ! 512: ! 513: *result = '\0'; ! 514: *line = s; ! 515: } ! 516: ! 517: /****************************************************************************/ ! 518: ! 519: static int matchnum(char **line) ! 520: { ! 521: char *s = *line, match = 0; ! 522: int sign = 1, num = 0; ! 523: ! 524: while(isspace(*s)) ++s; ! 525: if(*s=='\"' || *s=='\'') match = *s++; ! 526: if(*s=='-') {sign = -1;++s;} ! 527: if(*s=='+') ++s; ! 528: while(isspace(*s)) ++s; ! 529: while(*s>='0' && *s<='9') num = num*10 + (*s++ - '0'); ! 530: if(match && *s==match && s[1]) ++s; ! 531: while(isspace(*s)) ++s; ! 532: *line = s; ! 533: return sign>0?num:-num; ! 534: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.