source: golgotha/src/i4/video/mac/draw_sprocket.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 14 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 17.7 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include <sioux.h>
10#include <LowMem.h>
11#include "draw_sprocket.hh"
12#include "device/event.hh"
13#include "device/keys.hh"
14
15enum mac_modnum
16{
17  MAC_COMMAND = 0x37,
18  MAC_LSHIFT,
19  MAC_CAPSLOCK,
20  MAC_LOPTION,
21  MAC_LCONTROL,
22  MAC_RSHIFT,
23  MAC_ROPTION,
24  MAC_RCONTROL,
25  MAC_LAST
26};
27
28const int mac_map[8] =
29{
30  I4_COMMAND,
31  I4_SHIFT_L,
32  I4_CAPS,
33  I4_ALT_L,
34  I4_CTRL_L,
35  I4_SHIFT_R,
36  I4_ALT_R,
37  I4_CTRL_R,
38};
39
40// save area for old event mask
41short OldEventMask;
42
43// new event mask for i4 system
44const short MACEVENTS = mUpMask | mDownMask | keyUpMask | keyDownMask | autoKeyMask;
45
46draw_sprocket_class draw_sprocket;
47
48
49w32 draw_sprocket_class::device_manager_class::request_device(i4_event_handler_class *for_who,
50                                                              w32 event_types)
51//{{{
52{
53  if ((event_types&i4_device_class::FLAG_MOUSE_BUTTON_UP) ||
54      (event_types&i4_device_class::FLAG_MOUSE_BUTTON_DOWN) ||
55      (event_types&i4_device_class::FLAG_MOUSE_MOVE) ||
56      (event_types&i4_device_class::FLAG_KEY_PRESS) ||
57      (event_types&i4_device_class::FLAG_KEY_RELEASE) ||
58      (event_types&i4_device_class::FLAG_DISPLAY_CLOSE))
59  {
60    if (event_types&i4_device_class::FLAG_KEY_PRESS)
61      add_agent(for_who,i4_device_class::FLAG_KEY_PRESS);
62
63    if (event_types&i4_device_class::FLAG_KEY_RELEASE)
64      add_agent(for_who,i4_device_class::FLAG_KEY_RELEASE);
65
66    if (event_types&i4_device_class::FLAG_MOUSE_BUTTON_UP)
67      add_agent(for_who,i4_device_class::FLAG_MOUSE_BUTTON_UP);
68
69    if (event_types&i4_device_class::FLAG_MOUSE_BUTTON_DOWN)
70      add_agent(for_who,i4_device_class::FLAG_MOUSE_BUTTON_DOWN);
71   
72    if (event_types&i4_device_class::FLAG_MOUSE_MOVE)
73      add_agent(for_who,i4_device_class::FLAG_MOUSE_MOVE);
74
75    if (event_types&i4_device_class::FLAG_DISPLAY_CLOSE)
76      add_agent(for_who,i4_device_class::FLAG_DISPLAY_CLOSE);
77   
78    return (i4_device_class::FLAG_KEY_PRESS|
79            i4_device_class::FLAG_KEY_RELEASE|
80            i4_device_class::FLAG_MOUSE_BUTTON_UP|
81            i4_device_class::FLAG_MOUSE_BUTTON_DOWN|
82            i4_device_class::FLAG_MOUSE_MOVE|
83            i4_device_class::FLAG_DISPLAY_CLOSE)&event_types;
84  }
85  return 0;
86}
87//}}}
88
89
90void draw_sprocket_class::device_manager_class::release_device(i4_event_handler_class *for_who,
91                                                               w32 event_types)
92//{{{
93{
94  if (event_types&i4_device_class::FLAG_KEY_PRESS)
95    remove_agent(for_who,i4_device_class::FLAG_KEY_PRESS);
96
97  if (event_types&i4_device_class::FLAG_KEY_RELEASE)
98    remove_agent(for_who,i4_device_class::FLAG_KEY_RELEASE);
99
100  if (event_types&i4_device_class::FLAG_MOUSE_BUTTON_UP)
101    remove_agent(for_who,i4_device_class::FLAG_MOUSE_BUTTON_UP);
102
103  if (event_types&i4_device_class::FLAG_MOUSE_BUTTON_DOWN)
104    remove_agent(for_who,i4_device_class::FLAG_MOUSE_BUTTON_DOWN);
105 
106  if (event_types&i4_device_class::FLAG_MOUSE_MOVE)
107    remove_agent(for_who,i4_device_class::FLAG_MOUSE_MOVE);
108
109  if (event_types&i4_device_class::FLAG_DISPLAY_CLOSE)
110    remove_agent(for_who,i4_device_class::FLAG_DISPLAY_CLOSE);
111}
112//}}}
113
114
115i4_bool draw_sprocket_class::device_manager_class::process_events()
116//{{{
117{
118  i4_bool ret = i4_F;
119
120  Point p;
121
122  // Update mouse position
123  omx = mx;
124  omy = my;
125  ::GetMouse(&p);
126  mx = p.h;
127  my = p.v;
128  if (mx!=omx || my!=omy)
129  {
130    i4_mouse_move_event_class ev(mx,my);
131    send_event_to_agents(&ev,i4_device_class::FLAG_MOUSE_MOVE);
132    ret = i4_T;
133  }
134
135#if 0
136  if (Button())
137  {
138    i4_display_close_event_class quit(&draw_sprocket);
139    send_event_to_agents(&quit,FLAG_DISPLAY_CLOSE);
140
141    return i4_T;
142  }
143  return i4_F;
144#endif
145
146  // get mac modifiers
147  unsigned char km[16];
148  int i;
149
150  GetKeys((unsigned long*)&km);
151  for (i=0; i<MAC_LAST-MAC_COMMAND; i++)
152  {
153    char last = mac_modifier[i];
154    mac_modifier[i] = (km[ (i+MAC_COMMAND) >> 3 ] >> ((i+MAC_COMMAND) & 7)) & 1;
155    if (mac_modifier[i] != last)
156    {
157      w16 key, key_code;
158
159      key_code = mac_map[i];
160      if (mac_modifier[i])
161      {
162        key = i4_key_translate(key_code,1,shift_state);
163        i4_key_press_event_class ev(key, key_code);
164        send_event_to_agents(&ev,FLAG_KEY_PRESS);   
165        ret = i4_T;
166      }
167      else
168      {
169        key = i4_key_translate(key_code,0,shift_state);
170        i4_key_release_event_class ev(key, key_code);
171        send_event_to_agents(&ev,FLAG_KEY_RELEASE);   
172        ret = i4_T;
173      }
174    }
175  }
176
177  EventRecord MacEv;
178 
179  // process mac events
180  while (GetOSEvent(MACEVENTS,&MacEv))
181  {
182    switch (MacEv.what)
183    {
184      case keyDown :
185      case keyUp :
186      case autoKey :
187      {
188        // process key events
189
190        w16 key, key_code;
191
192        switch ((MacEv.message & keyCodeMask)>>8)
193        {
194          case 0x7d:   key_code=I4_DOWN; break;
195          case 0x7e:   key_code=I4_UP;  break;
196          case 0x7b:   key_code=I4_LEFT;  break;
197          case 0x7c:   key_code=I4_RIGHT;  break;
198          case 0x47:   key_code=I4_NUM_LOCK;  break;
199          case 0x73:   key_code=I4_HOME;  break;
200          case 0x77:   key_code=I4_END;  break;
201          case 0x33:   key_code=I4_BACKSPACE;  break;
202          case 0x30:   key_code=I4_TAB;  break;
203          case 0x24:   key_code=I4_ENTER;  break;
204          case 0x39:   key_code=I4_CAPS;  break;
205          case 0x35:   key_code=I4_ESC;  break;
206          case 0x7a:   key_code=I4_F1; break;
207          case 0x78:   key_code=I4_F2;break;
208          case 0x63:   key_code=I4_F3; break;
209          case 0x76:   key_code=I4_F4; break;
210          case 0x60:   key_code=I4_F5; break;
211          case 0x61:   key_code=I4_F6; break;
212          case 0x62:   key_code=I4_F7; break;
213          case 0x64:   key_code=I4_F8; break;
214          case 0x65:   key_code=I4_F9; break;
215          case 0x6d:   key_code=I4_F10; break;
216          case 0x67:   key_code=I4_F11; break;
217          case 0x6f:   key_code=I4_F12; break;
218          case 0x69:   key_code=I4_F13; break;
219          case 0x6b:   key_code=I4_F14; break;
220          case 0x71:   key_code=I4_F15; break;
221          case 0x72:   key_code=I4_INSERT; break;
222          case 0x75:   key_code=I4_DEL; break;
223          case 0x74:   key_code=I4_PAGEUP; break;
224          case 0x79:   key_code=I4_PAGEDOWN; break;
225         
226          case 0x52:   key_code=I4_KP0; break;
227          case 0x53:   key_code=I4_KP1; break;
228          case 0x54:   key_code=I4_KP2; break;
229          case 0x55:   key_code=I4_KP3; break;
230          case 0x56:   key_code=I4_KP4; break;
231          case 0x57:   key_code=I4_KP5; break;
232          case 0x58:   key_code=I4_KP6; break;
233          case 0x59:   key_code=I4_KP7; break;
234          case 0x5b:   key_code=I4_KP8; break;
235          case 0x5c:   key_code=I4_KP9; break;
236          case 0x51:   key_code=I4_KPEQUAL; break;
237          case 0x4b:   key_code=I4_KPSLASH; break;
238          case 0x43:   key_code=I4_KPSTAR; break;
239          case 0x4e:   key_code=I4_KPMINUS; break;
240          case 0x45:   key_code=I4_KPPLUS; break;
241          case 0x4c:   key_code=I4_KPENTER; break;
242          case 0x41:   key_code=I4_KPPERIOD; break;
243         
244          case 0x00:   key_code='A'; break;
245          case 0x0b:   key_code='B'; break;
246          case 0x08:   key_code='C'; break;
247          case 0x02:   key_code='D'; break;
248          case 0x0e:   key_code='E'; break;
249          case 0x03:   key_code='F'; break;
250          case 0x05:   key_code='G'; break;
251          case 0x04:   key_code='H'; break;
252          case 0x22:   key_code='I'; break;
253          case 0x26:   key_code='J'; break;
254          case 0x28:   key_code='K'; break;
255          case 0x25:   key_code='L'; break;
256          case 0x2e:   key_code='M'; break;
257          case 0x2d:   key_code='N'; break;
258          case 0x1f:   key_code='O'; break;
259          case 0x23:   key_code='P'; break;
260          case 0x0c:   key_code='Q'; break;
261          case 0x0f:   key_code='R'; break;
262          case 0x01:   key_code='S'; break;
263          case 0x11:   key_code='T'; break;
264          case 0x20:   key_code='U'; break;
265          case 0x09:   key_code='V'; break;
266          case 0x0d:   key_code='W'; break;
267          case 0x07:   key_code='X'; break;
268          case 0x10:   key_code='Y'; break;
269          case 0x06:   key_code='Z'; break;
270         
271          case 0x32:   key_code='`'; break;
272          case 0x12:   key_code='1'; break;
273          case 0x13:   key_code='2'; break;
274          case 0x14:   key_code='3'; break;
275          case 0x15:   key_code='4'; break;
276          case 0x17:   key_code='5'; break;
277          case 0x16:   key_code='6'; break;
278          case 0x1a:   key_code='7'; break;
279          case 0x1c:   key_code='8'; break;
280          case 0x19:   key_code='9'; break;
281          case 0x1d:   key_code='0'; break;
282          case 0x1b:   key_code='-'; break;
283          case 0x18:   key_code='='; break;
284
285          case 0x21:   key_code='['; break;
286          case 0x1e:   key_code=']'; break;
287          case 0x2a:   key_code='\\'; break;
288         
289          case 0x29:   key_code=';'; break;
290          case 0x27:   key_code='\''; break;
291         
292          case 0x2b:   key_code=','; break;
293          case 0x2f:   key_code='.'; break;
294          case 0x2c:   key_code='/'; break;
295          case 0x31:   key_code=' '; break;
296         
297          default:     key_code = 0; break;
298        }
299
300        if (key_code)
301        {
302          if (MacEv.what!=keyUp)
303          {
304            key = i4_key_translate(key_code,1,shift_state);
305            i4_key_press_event_class ev(key, key_code);
306            send_event_to_agents(&ev,FLAG_KEY_PRESS);   
307            ret = i4_T;
308          }
309          else
310          {
311            key = i4_key_translate(key_code,0,shift_state);
312            i4_key_release_event_class ev(key, key_code);
313            send_event_to_agents(&ev,FLAG_KEY_RELEASE);   
314            ret = i4_T;
315          }
316        }
317      } break;
318     
319      case mouseUp :
320      {
321        i4_mouse_button_up_event_class down(i4_mouse_button_up_event_class::LEFT);
322        send_event_to_agents(&down,FLAG_MOUSE_BUTTON_UP);
323        ret = i4_T;
324      } break;
325
326      case mouseDown :
327      {
328        i4_mouse_button_down_event_class down(i4_mouse_button_down_event_class::LEFT);
329        send_event_to_agents(&down,FLAG_MOUSE_BUTTON_DOWN);
330        ret = i4_T;
331      } break;
332    }
333  }
334
335  return ret;
336}
337//}}}
338
339
340draw_sprocket_class::device_manager_class::device_manager_class()
341  : shift_state(0)
342//{{{
343{
344  int i;
345
346  for (i=0; i<8; i++)
347    mac_modifier[i] = 0;
348}
349//}}}
350
351
352draw_sprocket_class::draw_sprocket_class()
353  : i4_display_class(), context(0), screen(0)
354//{{{
355{
356  /* tell SIOUX(stdio simulator) to shut up */
357//  SIOUXSettings.autocloseonquit = true;
358  SIOUXSettings.asktosaveonclose = false;
359
360  DSpStartup();
361
362  // open window & initialize toolbox routines to allow DrawSprockets to work?
363  printf("Draw Sprocket Initialization\n");
364
365  // save & set event mask
366  OldEventMask = LMGetSysEvtMask();
367  SetEventMask(MACEVENTS);
368}
369//}}}
370
371
372draw_sprocket_class::~draw_sprocket_class()
373//{{{
374{
375  // restore event mask
376  SetEventMask(OldEventMask);
377
378  DSpShutdown();
379}
380//}}}
381
382
383draw_sprocket_class::draw_sprocket_mode_class
384*draw_sprocket_class::new_mode(DSpContextReference context)
385//  create new video mode info struct from draw sprocket context
386//{{{
387{
388  DSpContextAttributes attr;
389  OSErr err;
390 
391  err = DSpContext_GetAttributes( context, &attr );
392 
393  if (err != noErr)
394    return 0;
395
396  if (attr.displayBestDepth != (8*I4_BYTES_PER_PIXEL))
397    return 0;
398
399  draw_sprocket_mode_class *m = new draw_sprocket_mode_class(context);
400 
401  m->xres = attr.displayWidth;
402  m->yres = attr.displayHeight;
403  m->bits_per_pixel = attr.displayBestDepth;
404  m->bits_per_color = 8;
405  m->flags = mode::PAGE_FLIPPED;
406  m->name[0] = 0;
407
408  return m;
409}
410//}}}
411
412
413draw_sprocket_class::mode *draw_sprocket_class::get_first_mode()
414//{{{
415{
416  return get_next_mode(0);
417}
418//}}}
419
420
421draw_sprocket_class::mode *draw_sprocket_class::get_next_mode(mode *last_mode)
422//{{{
423{
424  DSpContextReference cont;
425  CAST_PTR(dsm, draw_sprocket_mode_class, last_mode);
426  draw_sprocket_mode_class *ret;
427  OSErr err;
428
429  if (dsm == 0)
430  {
431    // get first screen through Display Manager
432
433    gd = DMGetFirstScreenDevice(0);
434
435    err = DMGetDisplayIDByGDevice( gd, &display_id, 0);
436   
437    if (err != noErr)
438      return 0;
439
440    // start screen enumeration through Display Manager
441    err = DSpGetFirstContext( display_id, &cont );
442   
443    if (err != noErr)
444      return 0;
445  }
446  else
447  {
448    // iterate screen enumeration through Display Manager
449
450    err = DSpGetNextContext( dsm->ref, &cont );
451
452    if (err != noErr)
453      return 0;
454  }
455
456  while (cont && (ret = new_mode(cont))==0)
457  {
458    // continue to get valid modes
459    err = DSpGetNextContext( cont, &cont );
460
461    if (err != noErr)
462      return 0;
463  }
464
465  return ret;
466}
467//}}}
468
469
470void draw_sprocket_class::setup_back_buffer()
471//  get memory pointer to back buffer for direct drawing & page flipping
472//{{{
473{
474  CGrafPtr back;
475  w8 *data;
476  w32 rowbytes;
477
478  // get CGrafPtr to back buffer
479  DSpContext_GetBackBuffer(DSp_ref, kDSpBufferKind_Normal, &back);
480
481  // get pixmap of port
482  PMH = back->portPixMap;
483
484  // ensure pixels stay in memory
485  LockPixels(PMH);
486
487  // get number of physical bytes per row
488  rowbytes = (*PMH)->rowBytes & 0x3FFF;
489
490  // get pointer to screen memory
491  data = (w8 *)GetPixBaseAddr(PMH);
492
493  i4_pal_handle_class pal;
494//#if (I4_SCREEN_DEPTH==15)
495  //pal.set_type(i4_pal_handle_class::ID_15BIT);
496//#elif (I4_SCREEN_DEPTH==16)
497  pal.set_type(i4_pal_handle_class::ID_16BIT);
498//#else
499//#error add code here
500//#endif
501
502  // setup screen with pointer into pixmap
503  if (!screen)
504  {
505    screen=new I4_SCREEN_TYPE(wx,wy,
506                              pal,
507                              rowbytes,   // bytes per line
508                              (w8 *)data);
509  }
510  else
511    screen->local_set_data((w8*)data);
512
513#if 0
514  //{{{ Debugging under 16 bit to show colors
515
516  int i,j;
517
518  for (j=0; j<1<<(16 - 8); j++)
519    for (i=0; i<1<<8; i++)
520      *((w16 *)(data + (j*rowbytes) + i*2)) = (j<<8) + i;
521
522  for (j=0; j<100; j++)
523    for (i=0; i<20; i++)
524    {
525      *((w16 *)(data + (j*rowbytes) + (i+340)*2)) = 0x001f;
526      *((w16 *)(data + (j*rowbytes) + (i+320)*2)) = 0x03e0;
527      *((w16 *)(data + (j*rowbytes) + (i+300)*2)) = 0x7c00;
528    }
529
530  //}}}
531#endif
532}
533//}}}
534
535
536i4_bool draw_sprocket_class::initialize_mode(mode *m)
537//{{{
538{
539  OSErr err;
540  DSpContextAttributes attr;
541  CAST_PTR(dsm, draw_sprocket_mode_class, m);
542
543  DSp_ref = dsm->ref;
544
545  err = DSpContext_GetAttributes( DSp_ref, &attr );
546 
547  if (err != noErr)
548    return i4_F;
549
550  // enable page flipping option
551  attr.contextOptions |= kDSpContextOption_PageFlip;
552
553  err = DSpContext_Reserve(DSp_ref, &attr);
554  if (err != noErr)
555    return i4_F;
556
557  // fade out mac scrren
558  err = DSpContext_FadeGammaOut(0, 0);
559  if (err != noErr)
560    return i4_F;
561
562  // change mode
563  err = DSpContext_SetState(DSp_ref, kDSpContextState_Active);
564  if (err != noErr)
565    return i4_F;
566
567  // fade game in
568  err = DSpContext_FadeGammaIn(0, 0);
569  if (err != noErr)
570    return i4_F;
571
572  wx = attr.displayWidth; 
573  wy = attr.displayHeight;
574
575  setup_back_buffer();
576
577  if (context)
578    delete context;
579
580  // setup context for window
581  context=new i4_draw_context_class(0,0,wx-1,wy-1);
582  context->both_dirty=new i4_rect_list_class;
583  context->single_dirty=new i4_rect_list_class;
584 
585  return i4_T;
586}
587//}}}
588
589
590i4_bool draw_sprocket_class::close()
591//{{{
592{
593  OSErr err;
594
595  if (PMH)
596    // free pixels to Mac Heap
597    UnlockPixels(PMH);
598
599  err = DSpContext_FadeGammaOut(0, 0);
600
601  // return to normal mode
602  err = DSpContext_SetState(DSp_ref, kDSpContextState_Inactive);
603
604  err = DSpContext_FadeGammaIn(0, 0);
605
606  if (context)
607    delete context;
608  context = 0;
609
610  if (screen)
611    delete screen;
612  screen = 0;
613 
614  return i4_T;
615}
616//}}}
617
618
619void draw_sprocket_class::flush()
620//{{{
621{
622  OSErr err;
623
624  PixMapHandle PMH2 = PMH;
625  w8 *data;
626  w32 rowbytes;
627  Rect r;
628
629  // save off pointers to current screen
630  rowbytes = (*PMH2)->rowBytes & 0x3FFF;
631  data = (w8 *)GetPixBaseAddr(PMH2);
632
633  // swap screens
634  err = DSpContext_SwapBuffers(DSp_ref, 0, 0);
635  setup_back_buffer();
636
637  // copy areas that changed
638  i4_rect_list_class::area_iter a=context->both_dirty->list.begin();
639  for (;a!=context->both_dirty->list.end();++a)
640  {
641    r.left = a->x1;
642    r.top = a->y1;
643    r.right = a->x2+1;
644    r.bottom = a->y2+1;
645
646    CopyBits((BitMap *)*PMH2, (BitMap *)*PMH, &r, &r, srcCopy, 0);
647  }
648
649  // free memory for old screen
650  if (PMH2)
651    UnlockPixels(PMH2);
652
653  context->single_dirty->delete_list();
654  context->both_dirty->delete_list();
655}
656//}}}
657
658
659i4_bool draw_sprocket_class::available()
660//{{{
661{
662  // should do more checks
663  return i4_T;
664}
665//}}}
666
667
668i4_bool draw_sprocket_class::realize_palette(i4_pal_handle_class pal_id)
669//{{{
670{
671  return i4_F;
672}
673//}}}
674
675
676i4_bool draw_sprocket_class::set_mouse_shape(i4_cursor_class *cursor)
677//{{{
678{
679  // not implemented yet
680  return i4_F;
681}
682//}}}
683
684
685//{{{ Emacs Locals
686// Local Variables:
687// folded-file: t
688// End:
689//}}}
Note: See TracBrowser for help on using the repository browser.