|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * [n]curses output. May be usefull for people with very poor configuration. ! 5: * [ Hardly think so (800x600 is faster on my machine), but this is good fun. ! 6: * You should get locked up for this, though. FIXME: this file wants color ! 7: * support added to it. -- Bernd ] ! 8: * ! 9: * Copyright 1997, Samuel Devulder. ! 10: */ ! 11: ! 12: /****************************************************************************/ ! 13: ! 14: #include "sysconfig.h" ! 15: #include "sysdeps.h" ! 16: ! 17: #include <ctype.h> ! 18: #include <signal.h> ! 19: ! 20: /****************************************************************************/ ! 21: ! 22: #include "uae.h" ! 23: #include "config.h" ! 24: #include "options.h" ! 25: #include "memory.h" ! 26: #include "custom.h" ! 27: #include "readcpu.h" ! 28: #include "newcpu.h" ! 29: #include "xwin.h" ! 30: #include "keyboard.h" ! 31: #include "keybuf.h" ! 32: #include "disk.h" ! 33: #include "debug.h" ! 34: #include "gui.h" ! 35: ! 36: #ifdef HAVE_NCURSES_H ! 37: #include <ncurses.h> ! 38: #else ! 39: #include <curses.h> ! 40: #endif ! 41: ! 42: /****************************************************************************/ ! 43: ! 44: #define MAXGRAYCHAR 128 ! 45: ! 46: static chtype graychar[MAXGRAYCHAR]; ! 47: static int maxc,max_graychar; ! 48: static int curses_on; ! 49: ! 50: xcolnr xcolors[4096]; ! 51: ! 52: /* Keyboard and mouse */ ! 53: ! 54: static int keystate[256]; ! 55: static int keydelay = 20; ! 56: ! 57: int buttonstate[3]; ! 58: int lastmx, lastmy; ! 59: int newmousecounters; ! 60: ! 61: struct vidbuf_description gfxvidinfo; ! 62: ! 63: /****************************************************************************/ ! 64: ! 65: static void curses_init(void); ! 66: static void curses_exit(void); ! 67: static void init_colors(void); ! 68: static void curses_insert_disk(int); ! 69: ! 70: /****************************************************************************/ ! 71: ! 72: static RETSIGTYPE sigbrkhandler(int foo) ! 73: { ! 74: curses_exit(); ! 75: activate_debugger(); ! 76: } ! 77: ! 78: void setup_brkhandler(void) ! 79: { ! 80: struct sigaction sa; ! 81: sa.sa_handler = sigbrkhandler; ! 82: sa.sa_flags = 0; ! 83: sa.sa_flags = SA_RESTART; ! 84: sigemptyset(&sa.sa_mask); ! 85: sigaction(SIGINT, &sa, NULL); ! 86: } ! 87: ! 88: /****************************************************************************/ ! 89: ! 90: static void init_graychar(void) ! 91: { ! 92: chtype *p = graychar; ! 93: chtype attrs; ! 94: int i,j; ! 95: char *fmt; ! 96: ! 97: attrs = termattrs(); ! 98: if(attrs & A_REVERSE) fmt = " .:=obIXMB^v^#MXIbo=:. "; ! 99: else fmt = " .`'^^\",:;i!1Il+=tfjxznuvyZYXHUOQ0MWB"; ! 100: /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ ! 101: /* One could find a better pattern.. */ ! 102: attrs = A_NORMAL; ! 103: while(*fmt) { ! 104: if(*fmt == '^') { ! 105: ++fmt; ! 106: switch(*fmt) { ! 107: case 'v': case 'V': attrs ^= A_REVERSE; break; ! 108: case 'b': case 'B': attrs ^= A_BOLD; break; ! 109: case 'd': case 'D': attrs ^= A_DIM; break; ! 110: case 'u': case 'U': attrs ^= A_UNDERLINE; break; ! 111: case 'p': case 'P': attrs = A_NORMAL; break; ! 112: case '#': if(ACS_CKBOARD == ':') ! 113: *p++ = (attrs | '#'); ! 114: else *p++ = (attrs | ACS_CKBOARD); break; ! 115: default: *p++ = (attrs | *fmt); break; ! 116: } ! 117: ++fmt; ! 118: } else *p++ = (attrs | *fmt++); ! 119: if(p >= graychar + MAXGRAYCHAR) break; ! 120: } ! 121: max_graychar = (p - graychar) - 1; ! 122: #if 0 ! 123: for(j=0;j<LINES;++j) { ! 124: move(j,0); ! 125: for(i=0;i<COLS;++i) addch(graychar[i % (max_graychar+1)]); ! 126: } ! 127: refresh(); ! 128: sleep(3); ! 129: #endif ! 130: } ! 131: ! 132: /****************************************************************************/ ! 133: ! 134: static int getcol(int x, int y) ! 135: { ! 136: int xs, xe, ys, ye, c, cm; ! 137: cm = c = 0; ! 138: xs = ((x+0)*gfx_requested_width)/COLS; ! 139: xe = ((x+1)*gfx_requested_width)/COLS; ! 140: ys = ((y+0)*gfx_requested_height)/LINES; ! 141: ye = ((y+1)*gfx_requested_height)/LINES; ! 142: for(y = ys; y < ye; ++y) ! 143: for(x = xs; x < xe; ++x) ! 144: { ! 145: c += (UBYTE)gfxvidinfo.bufmem[x + y*gfx_requested_width]; ! 146: ++cm; ! 147: } ! 148: return cm?c/cm:0; ! 149: } ! 150: ! 151: /****************************************************************************/ ! 152: ! 153: static void flush_line_txt(int y) ! 154: { ! 155: int x; ! 156: move(y,0); ! 157: for(x=0;x<COLS;++x) ! 158: { ! 159: int c; ! 160: c = getcol(x,y); ! 161: if(!no_xhair) c = maxc - c; ! 162: addch(graychar[(c*max_graychar)/maxc]); ! 163: } ! 164: } ! 165: ! 166: /****************************************************************************/ ! 167: ! 168: __inline__ void flush_line(int y) ! 169: { ! 170: if(y<0 || y>=gfx_requested_height) { ! 171: /* printf("flush_line out of window: %d\n", y); */ ! 172: return; ! 173: } ! 174: if(!curses_on) return; ! 175: flush_line_txt((y*LINES)/gfx_requested_height); ! 176: } ! 177: ! 178: /****************************************************************************/ ! 179: ! 180: void flush_block (int ystart, int ystop) ! 181: { ! 182: int y; ! 183: if(!curses_on) return; ! 184: ystart = (ystart * LINES)/gfx_requested_height; ! 185: ystop = (ystop * LINES)/gfx_requested_height; ! 186: for(y=ystart; y<=ystop; ++y) flush_line_txt(y); ! 187: } ! 188: ! 189: /****************************************************************************/ ! 190: ! 191: void flush_screen (int ystart, int ystop) ! 192: { ! 193: if(!debugging && !curses_on) { ! 194: curses_init(); ! 195: flush_block(0, gfx_requested_height - 1); ! 196: } ! 197: refresh(); ! 198: } ! 199: ! 200: /****************************************************************************/ ! 201: ! 202: static void init_colors(void) ! 203: { ! 204: int i; ! 205: for(i=0;i<4096;++i) { ! 206: int r,g,b; ! 207: r = i>>8; ! 208: g = (i>>4)&15; ! 209: b = i&15; ! 210: xcolors[i] = (77 * r + 151 * g + 28 * b)/16; ! 211: if(xcolors[i] > maxc) maxc = xcolors[i]; ! 212: } ! 213: } ! 214: ! 215: /****************************************************************************/ ! 216: ! 217: static void curses_init() ! 218: { ! 219: initscr();cbreak();noecho(); ! 220: nonl();intrflush(stdscr, FALSE); keypad(stdscr, TRUE); ! 221: nodelay(stdscr, TRUE); ! 222: leaveok(stdscr, TRUE); ! 223: ! 224: #ifdef NCURSES_MOUSE_VERSION ! 225: mousemask(BUTTON1_PRESSED | BUTTON1_RELEASED | ! 226: BUTTON2_PRESSED | BUTTON2_RELEASED | ! 227: BUTTON3_PRESSED | BUTTON3_RELEASED | ! 228: REPORT_MOUSE_POSITION, NULL); ! 229: #endif ! 230: ! 231: init_graychar(); ! 232: curses_on = 1; ! 233: } ! 234: ! 235: /****************************************************************************/ ! 236: ! 237: static void curses_exit() ! 238: { ! 239: #ifdef NCURSES_MOUSE_VERSION ! 240: mousemask(0, NULL); ! 241: #endif ! 242: ! 243: nocbreak(); echo(); nl(); intrflush(stdscr, TRUE); ! 244: keypad(stdscr, FALSE); nodelay(stdscr, FALSE); leaveok(stdscr, FALSE); ! 245: endwin(); ! 246: curses_on = 0; ! 247: } ! 248: ! 249: /****************************************************************************/ ! 250: ! 251: int graphics_init(void) ! 252: { ! 253: int i; ! 254: ! 255: if(!debugging) { ! 256: curses_init(); ! 257: fprintf(stderr,"Using %s.\n",longname()); ! 258: } ! 259: ! 260: /* we have a 320x256x8 pseudo screen */ ! 261: ! 262: gfx_requested_width = 320; ! 263: gfx_requested_height = 256; ! 264: gfx_requested_lores = 1; ! 265: ! 266: gfxvidinfo.maxlinetoscr = gfx_requested_width; ! 267: gfxvidinfo.maxline = gfx_requested_height; ! 268: gfxvidinfo.maxblocklines = 100; /* whatever */ ! 269: gfxvidinfo.pixbytes = 1; ! 270: gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * gfx_requested_width; ! 271: gfxvidinfo.bufmem = (char *)calloc(gfxvidinfo.rowbytes, gfx_requested_height+1); ! 272: ! 273: if(!gfxvidinfo.bufmem) { ! 274: fprintf(stderr,"Not enough memory.\n"); ! 275: return 0; ! 276: } ! 277: ! 278: init_colors(); ! 279: ! 280: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; ! 281: for(i=0; i<256; i++) ! 282: keystate[i] = 0; ! 283: ! 284: lastmx = lastmy = 0; ! 285: newmousecounters = 0; ! 286: ! 287: return 1; ! 288: } ! 289: ! 290: /****************************************************************************/ ! 291: ! 292: void graphics_leave(void) ! 293: { ! 294: curses_exit(); ! 295: } ! 296: ! 297: /****************************************************************************/ ! 298: ! 299: static int keycode2amiga(int ch) ! 300: { ! 301: switch(ch) { ! 302: case KEY_A1: return AK_NP7; ! 303: case KEY_UP: return AK_NP8; ! 304: case KEY_A3: return AK_NP9; ! 305: case KEY_LEFT: return AK_NP4; ! 306: case KEY_B2: return AK_NP5; ! 307: case KEY_RIGHT: return AK_NP6; ! 308: case KEY_C1: return AK_NP1; ! 309: case KEY_DOWN: return AK_NP2; ! 310: case KEY_C3: return AK_NP3; ! 311: case KEY_ENTER: return AK_ENT; ! 312: case 13: return AK_RET; ! 313: case ' ': return AK_SPC; ! 314: case 27: return AK_ESC; ! 315: default: return -1; ! 316: } ! 317: } ! 318: ! 319: /***************************************************************************/ ! 320: ! 321: void handle_events(void) ! 322: { ! 323: int ch; ! 324: int kc; ! 325: ! 326: /* Hack to simulate key release */ ! 327: for(kc = 0; kc < 256; ++kc) { ! 328: if(keystate[kc]) if(!--keystate[kc]) record_key((kc << 1) | 1); ! 329: } ! 330: if(buttonstate[0]) --buttonstate[0]; ! 331: if(buttonstate[1]) --buttonstate[1]; ! 332: if(buttonstate[2]) --buttonstate[2]; ! 333: ! 334: newmousecounters = 0; ! 335: if(!curses_on) return; ! 336: ! 337: while((ch = getch())!=ERR) { ! 338: if(ch == 12) {clearok(stdscr,TRUE);refresh();} ! 339: #ifdef NCURSES_MOUSE_VERSION ! 340: if(ch == KEY_MOUSE) { ! 341: MEVENT ev; ! 342: if(getmouse(&ev) == OK) { ! 343: lastmx = (ev.x*gfx_requested_width)/COLS; ! 344: lastmy = (ev.y*gfx_requested_height)/LINES; ! 345: if(ev.bstate & BUTTON1_PRESSED) buttonstate[0] = keydelay; ! 346: if(ev.bstate & BUTTON1_RELEASED) buttonstate[0] = 0; ! 347: if(ev.bstate & BUTTON2_PRESSED) buttonstate[1] = keydelay; ! 348: if(ev.bstate & BUTTON2_RELEASED) buttonstate[1] = 0; ! 349: if(ev.bstate & BUTTON3_PRESSED) buttonstate[2] = keydelay; ! 350: if(ev.bstate & BUTTON3_RELEASED) buttonstate[2] = 0; ! 351: } ! 352: } ! 353: #endif ! 354: if(ch == 6) ++lastmx; /* ^F */ ! 355: if(ch == 2) --lastmx; /* ^B */ ! 356: if(ch == 14) ++lastmy; /* ^N */ ! 357: if(ch == 16) --lastmy; /* ^P */ ! 358: if(ch == 11) {buttonstate[0] = keydelay;ch = 0;} /* ^K */ ! 359: if(ch == 25) {buttonstate[2] = keydelay;ch = 0;} /* ^Y */ ! 360: ! 361: if(ch >= KEY_F(1) && ch<=KEY_F(4)) { ! 362: curses_insert_disk(ch - KEY_F(1)); ! 363: ch = 0; ! 364: } ! 365: ! 366: if(isupper(ch)) { ! 367: keystate[AK_LSH] = ! 368: keystate[AK_RSH] = keydelay; ! 369: record_key(AK_LSH << 1); ! 370: record_key(AK_RSH << 1); ! 371: kc = keycode2amiga(tolower(ch)); ! 372: keystate[kc] = keydelay; ! 373: record_key(kc << 1); ! 374: } else if((kc = keycode2amiga(ch)) >= 0) { ! 375: keystate[kc] = keydelay; ! 376: record_key(kc << 1); ! 377: } ! 378: } ! 379: gui_handle_events(); ! 380: } ! 381: ! 382: /***************************************************************************/ ! 383: ! 384: void target_specific_usage(void) ! 385: { ! 386: printf("----------------------------------------------------------------------------\n"); ! 387: printf("[n]curses specific usage:\n"); ! 388: printf(" -x : Display reverse video.\n"); ! 389: printf("By default uae will assume a black on white display. If yours\n"); ! 390: printf("is light on dark, use -x. In case of graphics garbage, ^L will\n"); ! 391: printf("redisplay the screen. ^K simulate left mouse button, ^Y RMB.\n"); ! 392: printf("If you are using a xterm UAE can use the mouse. Else use ^F ^B\n"); ! 393: printf("^P ^N to emulate mouse mouvements.\n"); ! 394: printf("----------------------------------------------------------------------------\n"); ! 395: } ! 396: ! 397: /***************************************************************************/ ! 398: ! 399: int debuggable(void) ! 400: { ! 401: return 1; ! 402: } ! 403: ! 404: /***************************************************************************/ ! 405: ! 406: int needmousehack(void) ! 407: { ! 408: return 1; ! 409: } ! 410: ! 411: /***************************************************************************/ ! 412: ! 413: void LED(int on) ! 414: { ! 415: } ! 416: ! 417: /***************************************************************************/ ! 418: ! 419: static void curses_insert_disk(int dsk) ! 420: { ! 421: char buff[256]; ! 422: char *s = buff; ! 423: curses_exit(); ! 424: fprintf(stderr, "Old DF%d filename: %s\n", dsk, dsk==0?df0:dsk==1?df1: ! 425: dsk==2?df2:df3); ! 426: fprintf(stderr,"Please type filename for drive %d: ", dsk); ! 427: fflush(stderr); ! 428: fgets(buff, 255, stdin); ! 429: while(*s) if(*s == '\n') *s='\0'; else ++s; ! 430: if(*buff) disk_insert(dsk, buff); ! 431: flush_screen(0,0); ! 432: } ! 433: ! 434: /***************************************************************************/ ! 435: ! 436:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.