|
|
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.