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