|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * GGI - Interface
5: *
6: * Always remember: "GGI - The right thing to do[tm]"
7: *
8: * Copyright 1997 Christian Schmitt <[email protected]>,
9: * Stefan Reinauer <[email protected]>
10: */
11:
12: #include "sysconfig.h"
13: #include "sysdeps.h"
14:
15: #include <stdio.h>
16: #include <stdlib.h>
17: #include <time.h>
18: #include <unistd.h>
19: #include <ggi/libggi.h>
20: #include <ggi/libggi_db.h>
21: #include <ggi/events.h>
22: #include <string.h>
23:
24: #include "config.h"
25: #include "options.h"
26: #include "threaddep/penguin.h"
27: #include "uae.h"
28: #include "memory.h"
29: #include "custom.h"
30: #include "readcpu.h"
31: #include "newcpu.h"
32: #include "keyboard.h"
33: #include "xwin.h"
34: #include "keybuf.h"
35: #include "gui.h"
36: #include "picasso96.h"
37:
38: static ggi_visual_t vis;
39: static ggi_graphtype amiga_modetype;
40: static unsigned char pack[256];
41: static uae_u8 dither_buf[1000];
42: int buttonstate[3] = {0, 0, 0};
43: int lastmx,lastmy,newmousecounters=0;
44: static int keystate[256];
45:
46: int need_dither,bpp;
47: void *linear=NULL;
48:
49: static int screen_is_picasso;
50: static char picasso_invalid_lines[1200];
51: static ggi_graphtype picasso_modetype;
52:
53: struct bstring *video_mode_menu = NULL;
54:
55: /* We don't need a brkhandler with GGI */
56: void setup_brkhandler(void)
57: {
58: }
59:
60: #define MAX_SCREEN_MODES 6
61: #define MAX_GGI_COLOR_MODES 4
62:
63: int x_size_table[MAX_SCREEN_MODES]={320,640,640,800,1024,1152};
64: int y_size_table[MAX_SCREEN_MODES]={200,400,480,600,768,864};
65: ggi_graphtype color_table[MAX_GGI_COLOR_MODES]=
66: {GT_4BIT,GT_8BIT,GT_16BIT,GT_32BIT};
67:
68: static struct ggi_graphmodes{
69: int x;
70: int y;
71: int col;
72: struct ggi_graphmodes *next;
73: } got_modes;
74:
75:
76: int graphics_setup(void)
77: {
78: struct ggi_graphmodes *dummy;
79: int count=0;
80: char buf[80];
81: int i,j,c=0;
82:
83: ggiInit();
84:
85: if((vis=ggiOpen(NULL))==NULL) {
86: fprintf(stderr,"Can't open Visual\n");
87: return 0;
88: }
89:
90: for(i=0;i<MAX_SCREEN_MODES;i++) {
91: for(j=0;j<MAX_GGI_COLOR_MODES;j++) {
92: if (ggiCheckGraphMode(vis, x_size_table[i], y_size_table[i],
93: x_size_table[i], y_size_table[i],
94: color_table[j]) != 0)
95: continue;
96:
97: dummy=(struct ggi_graphmodes *)malloc(sizeof(struct ggi_graphmodes));
98: dummy->x=x_size_table[i];
99: dummy->y=y_size_table[i];
100: switch(color_table[j]) {
101: case GT_4BIT : c=4;break;
102: case GT_8BIT : c=8;break;
103: case GT_16BIT : c=16;break;
104: case GT_32BIT : c=32;break;
105: default : break; /* Ups */
106: }
107: dummy->col=c;
108: dummy->next=got_modes.next;
109: got_modes.next=dummy;
110: count++;
111: }
112: }
113: count++;
114: video_mode_menu = (struct bstring *)malloc(sizeof (struct bstring)*count);
115: memset(video_mode_menu, 0, sizeof (struct bstring)*count);
116: dummy=got_modes.next;
117: for (i = 0; i < count - 1; i++) {
118: sprintf(buf, "%3dx%d, %2d Bit", dummy->x, dummy->y,dummy->col);
119: video_mode_menu[i].val = -1;
120: video_mode_menu[i].data = strdup(buf);
121: dummy = dummy->next;
122: }
123: video_mode_menu[count-1].val = -3;
124: video_mode_menu[count-1].data = NULL;
125: return 1;
126: }
127:
128: void vidmode_menu_selected(int m)
129: {
130: int i;
131: struct ggi_graphmodes *dummy=got_modes.next;
132: for(i=1;i<=m;i++) dummy=dummy->next;
133: currprefs.gfx_width = dummy->x;
134: currprefs.gfx_height = dummy->y;
135: currprefs.color_mode = dummy->col == 32 ? 5 : dummy->col == 16 ? 2 : 0;
136: }
137:
138: static int colors_allocated;
139: static ggi_color map[256];
140: static ggi_color vga_map[256];
141:
142: static void restore_vga_colors (void)
143: {
144: int i;
145: if (gfxvidinfo.pixbytes != 1)
146: return;
147: memcpy (map, vga_map, sizeof map);
148: ggiSetPaletteVec(vis, 0, colors_allocated, map);
149: }
150:
151: static int get_color(int r, int g, int b, xcolnr *cnp)
152: {
153: if(colors_allocated == 255)
154: return -1;
155: *cnp = colors_allocated;
156: map[colors_allocated].r = doMask (r,16,0);
157: map[colors_allocated].g = doMask (g,16,0);
158: map[colors_allocated].b = doMask (b,16,0);
159:
160: colors_allocated++;
161: return 1;
162: }
163:
164: static void init_colors(void)
165: {
166: if (need_dither) {
167: setup_dither (8, get_color);
168: } else {
169: int i;
170: colors_allocated = 0;
171: gfxvidinfo.can_double = 0;
172: switch (bpp){
173: case 8:
174: alloc_colors256 (get_color);
175: ggiSetPaletteVec (vis, 0, colors_allocated, map);
176: memcpy (vga_map, map, sizeof vga_map);
177: for (i = 0; i < 4096;i++)
178: xcolors[i] *= 0x01010101;
179: gfxvidinfo.can_double=1;
180: break;
181: case 16:
182: alloc_colors64k (5, 6, 5, 11, 5, 0);
183: for(i = 0; i < 4096; i++)
184: xcolors[i] *= 0x00010001;
185: gfxvidinfo.can_double=1;
186: break;
187: case 32:
188: alloc_colors64k(8, 8, 8, 16, 8, 0);
189: break;
190: default:
191: break;
192: }
193: }
194: }
195:
196: static int set_amiga_mode (void)
197: {
198: int sx = gfxvidinfo.width;
199: int sy = gfxvidinfo.height;
200: ggi_directbuffer_t gbuf=NULL;
201: ggi_pixellinearbuffer *plb;
202:
203: ggiSetFocus(vis);
204:
205: if (ggiSetGraphMode (vis, sx, sy, sx, sy, amiga_modetype) != 0) {
206: fprintf(stderr,"Can't set graphics mode\n");
207: return 0;
208: }
209: ggiDBGetBuffer(vis,&gbuf);
210: plb=ggiDBGetPLB(gbuf);
211: linear = plb->write;
212: return 1;
213: }
214:
215: int graphics_init (void) /* See how simple it is? :-> */
216: {
217: int err,i;
218:
219: switch(currprefs.color_mode) {
220: case 0:
221: amiga_modetype = GT_8BIT;
222: need_dither = 0;
223: break;
224: case 1:
225: case 2:
226: amiga_modetype = GT_16BIT;
227: need_dither = 0;
228: break;
229: case 3:
230: amiga_modetype = GT_8BIT;
231: need_dither = 1;
232: break;
233: case 4:
234: amiga_modetype = GT_4BIT;
235: need_dither = 1;
236: break;
237: default:
238: fprintf(stderr, "Bad color mode selected. Using default.\n");
239: currprefs.color_mode = 0;
240: amiga_modetype = GT_8BIT;
241: break;
242: }
243:
244: gfxvidinfo.width = currprefs.gfx_width;
245: gfxvidinfo.height = currprefs.gfx_height;
246:
247: if (! set_amiga_mode ())
248: return 0;
249:
250: bpp = ggiGetBPP (vis);
251:
252: gfxvidinfo.pixbytes = bpp >> 3;
253: gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * currprefs.gfx_width;
254: if (linear != NULL)
255: gfxvidinfo.bufmem = linear;
256: else
257: gfxvidinfo.bufmem = (char *)malloc (gfxvidinfo.rowbytes * currprefs.gfx_height);
258: gfxvidinfo.maxblocklines = 0;
259: memset (gfxvidinfo.bufmem, 0, gfxvidinfo.rowbytes * currprefs.gfx_height);
260:
261: screen_is_picasso = 0;
262:
263: for (i = 0; i < 256; i++) {
264: map[i].r=i;
265: map[i].g=i;
266: map[i].b=i;
267: }
268: ggiPackColors(vis, pack, map, 256);
269: init_colors ();
270:
271: buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
272: for (i = 0; i < 256; i++)
273: keystate[i] = 0;
274: lastmx = lastmy = 0;
275: return 1;
276: }
277:
278: void graphics_leave(void)
279: {
280: ggiClose (vis);
281: ggiExit ();
282: }
283:
284: void flush_line(int y)
285: {
286: int target_y = y;
287: int bit_unit=8;
288: int i=0;
289: char *addr;
290:
291: if (linear != NULL && !need_dither)
292: return;
293:
294: addr = gfxvidinfo.bufmem + y*gfxvidinfo.rowbytes;
295: if (target_y < 400 && target_y >= 0) {
296: if (need_dither) {
297: if (linear == NULL){
298: DitherLine (dither_buf, (uae_u16 *)addr, 0, y,
299: gfxvidinfo.width, bit_unit);
300: addr = dither_buf;
301: ggiPutHLine (vis, 0, target_y, gfxvidinfo.width, addr);
302: } else {
303: DitherLine (linear + gfxvidinfo.rowbytes*y, (uae_u16 *)addr, 0, y,
304: gfxvidinfo.width, bit_unit);
305: }
306: return;
307: }
308: if(linear==NULL)
309: ggiPutHLine(vis, 0, target_y, gfxvidinfo.width, addr);
310: }
311: }
312:
313: void flush_block(int a, int b){};
314: void flush_screen(int a, int b){};
315:
316: #define KEY_NOTHING 0x00
317: #define AK_QUIT 0xf00
318:
319: /* We should not need to have different versions for different keyboard */
320: static short decodekey[128]={
321: KEY_NOTHING, /* 0 */
322: AK_ESC,
323: AK_1, AK_2, AK_3, AK_4, AK_5, AK_6, AK_7, AK_8, AK_9, AK_0,
324: AK_MINUS, /* 12 */
325: AK_EQUAL,
326: AK_BS,
327: AK_TAB, /* 0x0f */
328: AK_Q, AK_W, AK_E, AK_R, AK_T,
329: AK_Y, /* 0x15 Attention: language specific !!!! */
330: AK_U, AK_I, AK_O, AK_P, AK_LBRACKET,
331: AK_RBRACKET, /* 0x1b */
332: AK_RET,
333: AK_CTRL,
334: AK_A, AK_S, AK_D, AK_F, AK_G, AK_H, AK_J, AK_K, AK_L,
335: AK_SEMICOLON, /* 0x27 */
336: AK_QUOTE, /* ä 0x28 */
337: KEY_NOTHING,
338: AK_LSH, /* 0x2a */
339: AK_LTGT, /* < 0x2b Attention: language specific !!!! */
340: AK_Z, /* 0x2c Attention: language specific !!!! */
341: AK_X, AK_C, AK_V, AK_B, AK_N, AK_M, AK_COMMA, AK_PERIOD,
342: AK_SLASH, /* 0x35 */
343: AK_RSH, /* 0x36 */
344: AK_NPMUL,
345: AK_LALT,
346: AK_SPC,
347: AK_CAPSLOCK, /* 0x3a */
348: AK_F1, AK_F2, AK_F3, AK_F4, AK_F5, AK_F6, AK_F7, AK_F8, AK_F9,
349: AK_F10, /* 0x44 */
350: KEY_NOTHING, /* NumLock */
351: KEY_NOTHING, /* "Rollen" */
352: AK_NP7, /* 0x47 */
353: AK_NP8,
354: AK_NP9,
355: AK_NPSUB, /* 0x4a */
356: AK_NP4,
357: AK_NP5,
358: AK_NP6,
359: AK_NPADD, /* 0x4e */
360: AK_NP1,
361: AK_NP2,
362: AK_NP3,
363: AK_NP0, /* 0x52 */
364: AK_NPDEL,
365: KEY_NOTHING, /* ??? */
366: KEY_NOTHING, /* ??? */
367: KEY_NOTHING, /* ??? */
368: AK_BS, /* 0x57 --> F11 */
369: AK_QUIT, /* 0x58 --> F12 */
370: KEY_NOTHING, /* ??? */
371: KEY_NOTHING, /* ??? */
372: KEY_NOTHING, /* ??? */
373: KEY_NOTHING, /* ??? */
374: KEY_NOTHING, /* ??? */
375: KEY_NOTHING, /* ??? */
376: KEY_NOTHING, /* ??? */
377: AK_ENT, /* 0x60 */
378: AK_RCTRL, /* 0x61 */
379: AK_NPDIV,
380: KEY_NOTHING,
381: AK_RALT, /* 0x64 */
382: KEY_NOTHING, /* ??? */
383: AK_NP7, /* Pos1 */
384: AK_UP, /* 0x67 */
385: AK_LAMI, /* 0x68 --> PgUp, */
386: AK_LF, /* 0x69 */
387: AK_RT, /* 0x6a */
388: AK_NP1, /* End */
389: AK_DN, /* 0x6c */
390: AK_RAMI, /* --> PgDown */
391: AK_HELP, /* 0x6e --> insert */
392: AK_DEL,
393: KEY_NOTHING,
394: KEY_NOTHING,
395: KEY_NOTHING,
396: KEY_NOTHING,
397: KEY_NOTHING,
398: KEY_NOTHING,
399: KEY_NOTHING,
400: KEY_NOTHING, /* 0x77 --> Pause */
401: KEY_NOTHING,
402: KEY_NOTHING,
403: KEY_NOTHING,
404: KEY_NOTHING,
405: KEY_NOTHING,
406: AK_LAMI, /* 0x7d --> WindOoze left */
407: AK_RAMI, /* --> WindOoze right */
408: AK_CTRL /* 0x7f --> WindOoze Menu */
409: };
410:
411: void handle_events (void)
412: {
413: struct timeval t={0,1};
414: ggi_event ev;
415: ggi_event_mask mask;
416: int akey;
417: uint32 state=0,button=0;
418: while(ggiEventPoll(vis,emPtrButton|emPtrRelative|emKey,&t)) {
419: ggiEventRead(vis,&ev,emPtrButton|emPtrRelative|emKey);
420: switch(ev.any.type){
421: case evPtrButtonPress:
422: case evPtrButtonRelease:
423: state=ev.pbutton.state;
424: button=ev.pbutton.button;
425: switch(button) {
426: case 1 : buttonstate[2]=state&button;break;
427: case 2 : buttonstate[0]=(state&button)>>1;break;
428: case 4 : buttonstate[1]=(state&button)>>2;break;
429: default: break;
430: }
431: break;
432: case evPtrRelative:
433: lastmx+=ev.pmove.x;
434: lastmy+=ev.pmove.y;
435: break;
436: case evKeyPress:
437: case evKeyRelease:
438: if(ev.key.sym==0) continue;
439: if(ev.key.code>128) return;
440: akey=decodekey[ev.key.code];
441: if(akey==0xf00) uae_quit();
442: if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
443: m68k_reset();
444: switch(ev.key.type) {
445: case 6 : keystate[akey]=0;
446: record_key((akey << 1) | 1);
447: break;
448: case 5 : if(akey==KEY_NOTHING) break;
449: if(!keystate[akey]) {
450: keystate[akey]=1;
451: record_key(akey << 1);
452: }
453: break;
454: default : break;
455: }
456: default:
457: printf("Ugh\n");
458: }
459: }
460:
461:
462:
463: #ifdef PICASSO96
464: if (screen_is_picasso && !picasso_vidinfo.extra_mem) {
465: int i;
466: char *addr = gfxmemory + (picasso96_state.Address - gfxmem_start);
467: for (i = 0; i < picasso_vidinfo.height; i++, addr += picasso96_state.BytesPerRow) {
468: if (!picasso_invalid_lines[i])
469: continue;
470: picasso_invalid_lines[i] = 0;
471: ggiPutHLine (vis, 0, i, gfxvidinfo.width, addr);
472: }
473: }
474: #endif
475:
476: return;
477: }
478:
479: void write_log(const char *buf)
480: {
481: fprintf(stderr,buf);
482: }
483:
484: int debuggable(void)
485: {
486: return 0;
487: }
488:
489: int needmousehack(void)
490: {
491: return 0;
492: }
493:
494: /* This is not implemented yet as GGI is not that far */
495: void LED(int on)
496: {
497: }
498:
499: #ifdef PICASSO96
500:
501: void DX_Invalidate (int first, int last)
502: {
503: do {
504: picasso_invalid_lines[first] = 1;
505: first++;
506: } while (first <= last);
507: }
508:
509: int DX_BitsPerCannon (void)
510: {
511: return 8;
512: }
513:
514: void DX_SetPalette(int start, int count)
515: {
516: int i;
517:
518: if (!screen_is_picasso || picasso_vidinfo.pixbytes != 1)
519: return;
520:
521: fprintf (stderr, "DX_SetPalette\n");
522:
523: for (i = 0; i < count; i++) {
524: map[start + i].r = picasso96_state.CLUT[start + i].Red * 0x0101;
525: map[start + i].g = picasso96_state.CLUT[start + i].Green * 0x0101;
526: map[start + i].b = picasso96_state.CLUT[start + i].Blue * 0x0101;
527: }
528: ggiSetPaletteVec (vis, start, count, map + start);
529: }
530:
531: int DX_FillResolutions (uae_u16 *ppixel_format)
532: {
533: int i, count = 0;
534: uae_u16 format = 0;
535:
536: for (i = 0; i < MAX_SCREEN_MODES; i++) {
537: if (ggiCheckGraphMode (vis, x_size_table[i], y_size_table[i],
538: x_size_table[i], y_size_table[i],
539: GT_8BIT) == 0) {
540: DisplayModes[count].res.width = x_size_table[i];
541: DisplayModes[count].res.height = y_size_table[i];
542: DisplayModes[count].depth = 1;
543: DisplayModes[count].refresh = 75;
544: count++;
545: format |= RGBFF_CHUNKY;
546: }
547: if (ggiCheckGraphMode (vis, x_size_table[i], y_size_table[i],
548: x_size_table[i], y_size_table[i],
549: GT_16BIT) == 0) {
550: DisplayModes[count].res.width = x_size_table[i];
551: DisplayModes[count].res.height = y_size_table[i];
552: DisplayModes[count].depth = 2;
553: DisplayModes[count].refresh = 75;
554: count++;
555: format |= RGBFF_R5G6B5PC;
556: }
557: if (ggiCheckGraphMode (vis, x_size_table[i], y_size_table[i],
558: x_size_table[i], y_size_table[i],
559: GT_32BIT) == 0) {
560: DisplayModes[count].res.width = x_size_table[i];
561: DisplayModes[count].res.height = y_size_table[i];
562: DisplayModes[count].depth = 4;
563: DisplayModes[count].refresh = 75;
564: count++;
565: format |= RGBFF_B8G8R8A8;
566: }
567: }
568:
569: *ppixel_format = format;
570: return count;
571: }
572:
573: static void set_window_for_picasso (void)
574: {
575: int sx, sy;
576: ggi_directbuffer_t gbuf=NULL;
577: ggi_pixellinearbuffer *plb;
578:
579: sx = picasso_vidinfo.width;
580: sy = picasso_vidinfo.height;
581: fprintf (stderr, "picasso mode %d %d %d!\n", sx, sy, picasso_modetype);
582: if (ggiSetGraphMode (vis, sx, sy, sx, sy, picasso_modetype) != 0) {
583: fprintf (stderr,"Can't set graphics mode\n");
584: abort ();
585: }
586: fprintf (stderr, "picasso mode ok!\n");
587:
588: ggiDBGetBuffer(vis,&gbuf);
589: plb=ggiDBGetPLB(gbuf);
590: linear = plb->write;
591:
592: if (linear != NULL)
593: picasso_vidinfo.extra_mem = 1;
594: else
595: picasso_vidinfo.extra_mem = 0;
596: fprintf (stderr, "em: %d\n", picasso_vidinfo.extra_mem);
597: DX_SetPalette (0, 256);
598: }
599:
600: static void set_window_for_amiga (void)
601: {
602: set_amiga_mode ();
603: if (linear != NULL && !need_dither)
604: gfxvidinfo.bufmem = linear;
605:
606: restore_vga_colors ();
607: }
608:
609: void gfx_set_picasso_modeinfo (int w, int h, int depth)
610: {
611: fprintf (stderr, "set_picasso_modeinfo\n");
612: picasso_vidinfo.width = w;
613: picasso_vidinfo.height = h;
614: picasso_vidinfo.depth = depth;
615: picasso_vidinfo.pixbytes = depth >> 3;
616: picasso_vidinfo.rowbytes = w /* @@@ */;
617: picasso_modetype = (depth == 8 ? GT_8BIT
618: : depth == 16 ? GT_16BIT
619: : GT_32BIT);
620: if (screen_is_picasso)
621: set_window_for_picasso ();
622: }
623:
624: void gfx_set_picasso_baseaddr (uaecptr a)
625: {
626: }
627:
628: void gfx_set_picasso_state (int on)
629: {
630: if (on == screen_is_picasso)
631: return;
632: fprintf (stderr, "set_picasso_state\n");
633: screen_is_picasso = on;
634: if (on)
635: set_window_for_picasso ();
636: else
637: set_window_for_amiga ();
638: }
639:
640: uae_u8 *lockscr (void)
641: {
642: return linear;
643: }
644: void unlockscr (void)
645: {
646: }
647: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.