1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * BeBox port specific stuff
5 *
6 * (c) 1996-1998 Christian Bauer
7 * (c) 1996 Patrick Hanevold
8 */
9
10 #include <AppKit.h>
11 #include <InterfaceKit.h>
12 #include <KernelKit.h>
13 #include <MediaKit.h>
14 #include <StorageKit.h>
15 #include <device/Joystick.h>
16
17 extern "C" {
18 #include "sysconfig.h"
19 #include "sysdeps.h"
20 #include "config.h"
21 #include "options.h"
22 #include "threaddep/penguin.h"
23 #include "uae.h"
24 #include "gensound.h"
25 #include "sounddep/sound.h"
26 #include "events.h"
27 #include "memory.h"
28 #include "custom.h"
29 #include "readcpu.h"
30 #include "newcpu.h"
31 #include "disk.h"
32 #include "gui.h"
33 #include "debug.h"
34 #include "xwin.h"
35 #include "joystick.h"
36 #include "keyboard.h"
37 #include "keybuf.h"
38 #include "gui.h"
39 #include "zfile.h"
40 #include "picasso96.h"
41 }
42
43
44 // Constants
45 const char APP_SIGNATURE[] = "application/x-vnd.cebix-UAE";
46
47 const uint32 MSG_INSERT_DF0 = 'idf0'; // Messages
48 const uint32 MSG_EJECT_DF0 = 'edf0';
49 const uint32 MSG_INSERT_DF1 = 'idf1';
50 const uint32 MSG_EJECT_DF1 = 'edf1';
51 const uint32 MSG_INSERT_DF2 = 'idf2';
52 const uint32 MSG_EJECT_DF2 = 'edf2';
53 const uint32 MSG_INSERT_DF3 = 'idf3';
54 const uint32 MSG_EJECT_DF3 = 'edf3';
55 const uint32 MSG_FLOPPY_PANEL_RETURNED = 'flpn';
56 const uint32 MSG_FR1 = 'mfr1';
57 const uint32 MSG_FR2 = 'mfr2';
58 const uint32 MSG_FR3 = 'mfr3';
59 const uint32 MSG_FR4 = 'mfr4';
60 const uint32 MSG_FR5 = 'mfr5';
61 const uint32 MSG_FR6 = 'mfr6';
62 const uint32 MSG_RESET = 'rset';
63 const uint32 MSG_DEBUG = 'dbug';
64 const uint32 MSG_REDRAW = 'draw';
65 const uint32 MSG_QUIT = 'quit';
66 const uint32 MSG_ABOUT = 'abut';
67
68 const rgb_color PowerDark = {0x40, 0x00, 0x00, 0}; // LED colors
69 const rgb_color PowerLight = {0xff, 0x00, 0x00, 0};
70 const rgb_color DriveDark = {0x00, 0x40, 0x00, 0};
71 const rgb_color DriveLight = {0x00, 0xff, 0x00, 0};
72
73
74 // Array for converting Be keycodes to Amiga keycodes
75 static const int keycode2amiga[128] = {
76 -1, AK_ESC, AK_F1, AK_F2, AK_F3, AK_F4, AK_F5, AK_F6,
77 AK_F7, AK_F8, AK_F9, AK_F10, -1, AK_mousestuff, -1, -1,
78
79 -1, AK_BACKQUOTE, AK_1, AK_2, AK_3, AK_4, AK_5, AK_6,
80 AK_7, AK_8, AK_9, AK_0, AK_MINUS, AK_EQUAL, AK_BS, AK_HELP,
81
82 AK_NPLPAREN, AK_NPRPAREN, -1, AK_NPDIV, AK_NPMUL, AK_NPSUB, AK_TAB, AK_Q,
83 AK_W, AK_E, AK_R, AK_T, AK_Y, AK_U, AK_I, AK_O,
84
85 AK_P, AK_LBRACKET, AK_RBRACKET, AK_BACKSLASH, AK_DEL, AK_LALT, AK_RALT, AK_NP7,
86 AK_NP8, AK_NP9, AK_NPADD, AK_CAPSLOCK, AK_A, AK_S, AK_D, AK_F,
87
88 AK_G, AK_H, AK_J, AK_K, AK_L, AK_SEMICOLON, AK_QUOTE, AK_RET,
89 AK_NP4, AK_NP5, AK_NP6, AK_LSH, AK_Z, AK_X, AK_C, AK_V,
90
91 AK_B, AK_N, AK_M, AK_COMMA, AK_PERIOD, AK_SLASH, AK_RSH, AK_UP,
92 AK_NP1, AK_NP2, AK_NP3, AK_ENT, AK_CTRL, AK_LAMI, AK_SPC, AK_RAMI,
93
94 AK_RALT, AK_LF, AK_DN, AK_RT, AK_NP0, AK_NPDEL, AK_LALT, AK_RALT,
95 AK_LTGT, -1, -1, -1, -1, -1, -1, -1,
96
97 -1, -1, -1, -1, -1, -1, -1, -1,
98 -1, -1, -1, -1, -1, -1, -1, -1
99 };
100
101
102 // Global variables
103 static bool reset_thyself = false;
104
105 static key_info old_key_info;
106 static bool window_open;
107 static bool LEDs[4];
108
109 static int the_argc;
110 static char **the_argv;
111
112 static BJoystick *joy;
113
114
115 /*
116 * A simple view class for blitting a bitmap on the screen
117 */
118
119 class BitmapView : public BView {
120 public:
121 BitmapView(BRect frame, BBitmap *bitmap);
122 virtual void Draw(BRect update);
123 virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message);
124 void Draw(BRect from, BRect to);
125
126 private:
127 BBitmap *the_bitmap;
128 };
129
130 static BitmapView *bitmap_view;
131
132
133 /*
134 * The window in which the Amiga graphics are displayed, handles I/O
135 */
136
137 class UAEWindow : public BWindow {
138 public:
139 UAEWindow(BRect frame, BBitmap *bitmap);
140 virtual bool QuitRequested(void);
141 virtual void MessageReceived(BMessage *msg);
142
143 private:
144 BMessenger this_messenger;
145 BitmapView *main_view;
146 BFilePanel *floppy_panel;
147 int panel_drive_num;
148 };
149
150 static UAEWindow *bitmap_window;
151
152
153 /*
154 * The BeOS application object
155 */
156
157 class UAE : public BApplication {
158 public:
159 UAE();
160 virtual void ReadyToRun(void);
161 virtual bool QuitRequested(void);
162
163 int GraphicsInit(void);
164 void GraphicsLeave(void);
165
166 private:
167 static long thread_func(void *obj);
168
169 BBitmap *the_bitmap;
170 UAEWindow *main_window;
171 thread_id the_thread;
172 };
173
174 static UAE *the_app;
175
176
177 /*
178 * LED
179 */
180
181 class LEDView : public BView {
182 public:
183 LEDView(BRect frame, rgb_color active, rgb_color idle);
184 virtual void Draw(BRect update);
185 void SetState(bool new_state);
186
187 private:
188 BRect bounds;
189 rgb_color active_color;
190 rgb_color idle_color;
191 bool state;
192 };
193
194 static LEDView *PowerLED, *DriveLED[4];
195
196
197 /*
198 * Create application object and start it
199 */
200
main(int argc,char ** argv)201 int main(int argc, char **argv)
202 {
203 // Copy command line arguments
204 the_argc = argc;
205 the_argv = new char *[argc];
206 for (int i=0; i<argc; i++)
207 the_argv[i] = strdup(argv[i]);
208
209 the_app = new UAE();
210 the_app->Run();
211 delete the_app;
212 return 0;
213 }
214
215
216 /*
217 * UAE Constructor: Initialize member variables
218 */
219
UAE()220 UAE::UAE() : BApplication('UAEm')
221 {
222 // Find application directory and cwd to it
223 app_info the_info;
224 GetAppInfo(&the_info);
225 BEntry the_file(&the_info.ref);
226 BEntry the_dir;
227 the_file.GetParent(&the_dir);
228 BPath the_path;
229 the_dir.GetPath(&the_path);
230 chdir(the_path.Path());
231
232 // Initialize other variables
233 the_bitmap = NULL;
234 main_window = NULL;
235 window_open = false;
236 }
237
238
239 /*
240 * Arguments processed, create and start emulation
241 */
242
ReadyToRun(void)243 void UAE::ReadyToRun(void)
244 {
245 // Start the emulation thread
246 the_thread = spawn_thread(thread_func, "UAE 68000", B_NORMAL_PRIORITY, this);
247 resume_thread(the_thread);
248 }
249
250
251 /*
252 * Quit requested (either by menu or by closing the window)
253 */
254
QuitRequested(void)255 bool UAE::QuitRequested(void)
256 {
257 // Quit the thread
258 uae_quit();
259 status_t l;
260 wait_for_thread(the_thread, &l);
261 return true;
262 }
263
264
265 /*
266 * The thread's main function
267 */
268
thread_func(void * obj)269 long UAE::thread_func(void *obj)
270 {
271 real_main(the_argc, the_argv);
272 return 0;
273 }
274
275
276 /*
277 * UAE Window constructor
278 */
279
UAEWindow(BRect frame,BBitmap * bitmap)280 UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame,"UAE", B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE), this_messenger(this)
281 {
282 int i;
283
284 // Initialize xcolors
285 {
286 BScreen scr(this);
287 i = 0;
288 for (int r=0; r<16; r++) {
289 for (int g=0; g<16; g++) {
290 for (int b=0; b<16; b++)
291 xcolors[i++] = scr.IndexForColor(r<<4 | r, g<<4 | g, b<<4 | b);
292 }
293 }
294 }
295
296 // Move window to right position
297 Lock();
298 MoveTo(80, 80);
299
300 // Set up menus
301 BRect bounds = Bounds();
302 bounds.OffsetBy(0, bounds.IntegerHeight() + 1);
303 BMenuBar *bar = new BMenuBar(bounds, "menu");
304 BMenu *menu = new BMenu("UAE");
305 menu->AddItem(new BMenuItem("About UAE" B_UTF8_ELLIPSIS, new BMessage(MSG_ABOUT)));
306 menu->AddItem(new BSeparatorItem);
307 BMenu *submenu = new BMenu("Framerate");
308 submenu->AddItem(new BMenuItem("1/1", new BMessage(MSG_FR1)));
309 submenu->AddItem(new BMenuItem("1/2", new BMessage(MSG_FR2)));
310 submenu->AddItem(new BMenuItem("1/3", new BMessage(MSG_FR3)));
311 submenu->AddItem(new BMenuItem("1/4", new BMessage(MSG_FR4)));
312 submenu->AddItem(new BMenuItem("1/5", new BMessage(MSG_FR5)));
313 submenu->AddItem(new BMenuItem("1/6", new BMessage(MSG_FR6)));
314 submenu->SetRadioMode(true);
315 menu->AddItem(submenu);
316 menu->AddItem(new BMenuItem("Reset", new BMessage(MSG_RESET)));
317 menu->AddItem(new BMenuItem("Debugger", new BMessage(MSG_DEBUG)));
318 menu->AddItem(new BSeparatorItem);
319 menu->AddItem(new BMenuItem("Quit", new BMessage(MSG_QUIT)));
320 bar->AddItem(menu);
321 menu = new BMenu("Floppy");
322 submenu = new BMenu("DF0");
323 submenu->AddItem(new BMenuItem("Insert" B_UTF8_ELLIPSIS, new BMessage(MSG_INSERT_DF0)));
324 submenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF0)));
325 menu->AddItem(submenu);
326 submenu = new BMenu("DF1");
327 submenu->AddItem(new BMenuItem("Insert" B_UTF8_ELLIPSIS, new BMessage(MSG_INSERT_DF1)));
328 submenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF1)));
329 menu->AddItem(submenu);
330 submenu = new BMenu("DF2");
331 submenu->AddItem(new BMenuItem("Insert" B_UTF8_ELLIPSIS, new BMessage(MSG_INSERT_DF2)));
332 submenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF2)));
333 menu->AddItem(submenu);
334 submenu = new BMenu("DF3");
335 submenu->AddItem(new BMenuItem("Insert" B_UTF8_ELLIPSIS, new BMessage(MSG_INSERT_DF3)));
336 submenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF3)));
337 menu->AddItem(submenu);
338 bar->AddItem(menu);
339 AddChild(bar);
340 bar->ResizeBy(-5*4, 0); // Make room for LEDs
341 int mbar_height = bar->Frame().IntegerHeight() + 1;
342
343 // Resize window to fit menu bar
344 ResizeBy(0, mbar_height);
345
346 // Create LEDs
347 BRect PowerRect = bar->Frame();
348 PowerRect.left = PowerRect.right+1;
349 PowerRect.right = PowerRect.left+3;
350 PowerLED = new LEDView(PowerRect, PowerLight, PowerDark);
351 AddChild(PowerLED);
352
353 BRect DriveRect = PowerRect;
354 for (i=0; i<4; i++) {
355 DriveRect.left += 4;
356 DriveRect.right += 4;
357 DriveLED[i] = new LEDView(DriveRect, DriveLight, DriveDark);
358 AddChild(DriveLED[i]);
359 }
360
361 // Create bitmap view
362 BRect BitmapRect = frame;
363 main_view = new BitmapView(BitmapRect, bitmap);
364 AddChild(main_view);
365 main_view->MakeFocus();
366 get_key_info(&old_key_info);
367
368 bitmap_view = main_view;
369 bitmap_window = this;
370
371 // Create file panel
372 floppy_panel = new BFilePanel(B_OPEN_PANEL, &this_messenger, NULL, 0, false, new BMessage(MSG_FLOPPY_PANEL_RETURNED));
373 panel_drive_num = 0;
374
375 // Show window
376 Unlock();
377 Show();
378 window_open = true;
379 }
380
381
382 /*
383 * Message received
384 */
385
MessageReceived(BMessage * msg)386 void UAEWindow::MessageReceived(BMessage *msg)
387 {
388 BMessage *msg2;
389
390 switch(msg->what) {
391 case MSG_INSERT_DF0:
392 panel_drive_num = 0;
393 floppy_panel->Hide();
394 floppy_panel->Window()->SetTitle("UAE: Insert floppy in DF0:");
395 floppy_panel->Show();
396 break;
397
398 case MSG_EJECT_DF0:
399 disk_eject(0);
400 break;
401
402 case MSG_INSERT_DF1:
403 panel_drive_num = 1;
404 floppy_panel->Hide();
405 floppy_panel->Window()->SetTitle("UAE: Insert floppy in DF1:");
406 floppy_panel->Show();
407 break;
408
409 case MSG_EJECT_DF1:
410 disk_eject(1);
411 break;
412
413 case MSG_INSERT_DF2:
414 panel_drive_num = 2;
415 floppy_panel->Hide();
416 floppy_panel->Window()->SetTitle("UAE: Insert floppy in DF2:");
417 floppy_panel->Show();
418 break;
419
420 case MSG_EJECT_DF2:
421 disk_eject(2);
422 break;
423
424 case MSG_INSERT_DF3:
425 panel_drive_num = 3;
426 floppy_panel->Hide();
427 floppy_panel->Window()->SetTitle("UAE: Insert floppy in DF3:");
428 floppy_panel->Show();
429 break;
430
431 case MSG_EJECT_DF3:
432 disk_eject(3);
433 break;
434
435 case MSG_FLOPPY_PANEL_RETURNED: {
436 entry_ref the_ref;
437 BEntry the_entry;
438 if (msg->FindRef("refs", &the_ref) == B_NO_ERROR)
439 if (the_entry.SetTo(&the_ref) == B_NO_ERROR) {
440 BPath the_path;
441 the_entry.GetPath(&the_path);
442 disk_eject(panel_drive_num);
443 disk_insert(panel_drive_num, the_path.Path());
444 }
445 break;
446 }
447
448 case MSG_FR1:
449 currprefs.framerate = 1;
450 break;
451 case MSG_FR2:
452 currprefs.framerate = 2;
453 break;
454 case MSG_FR3:
455 currprefs.framerate = 3;
456 break;
457 case MSG_FR4:
458 currprefs.framerate = 4;
459 break;
460 case MSG_FR5:
461 currprefs.framerate = 5;
462 break;
463 case MSG_FR6:
464 currprefs.framerate = 6;
465 break;
466
467 case MSG_RESET:
468 reset_thyself = true;
469 break;
470
471 case MSG_DEBUG:
472 activate_debugger();
473 break;
474
475 case MSG_QUIT:
476 be_app->PostMessage(B_QUIT_REQUESTED);
477 break;
478
479 case MSG_ABOUT: {
480 char str[256];
481 sprintf(str, " Un*x Amiga Emulator V%d.%d.%d\n"
482 " by Bernd Schmidt\n"
483 " BeBox port by Christian Bauer\n"
484 "Additional porting by Patrick Hanevold", UAEMAJOR, UAEMINOR, UAEURSAMINOR);
485 BAlert *the_alert = new BAlert("", str, "OK");
486 the_alert->Go();
487 break;
488 }
489
490 case MSG_REDRAW:
491 MessageQueue()->Lock();
492 while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) {
493 MessageQueue()->RemoveMessage(msg2);
494 delete msg2;
495 }
496 MessageQueue()->Unlock();
497 Lock();
498 main_view->Draw(BRect(0, 0, currprefs.gfx_width-1, currprefs.gfx_height-1));
499 Unlock();
500 break;
501
502 default:
503 BWindow::MessageReceived(msg);
504 break;
505 }
506 }
507
508
509 /*
510 * Closing the window quits UAE
511 */
512
QuitRequested(void)513 bool UAEWindow::QuitRequested(void)
514 {
515 window_open = false;
516 be_app->PostMessage(B_QUIT_REQUESTED);
517 return false;
518 }
519
520
521 /*
522 * Bitmap view constructor
523 */
524
BitmapView(BRect frame,BBitmap * bitmap)525 BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
526 {
527 the_bitmap = bitmap;
528 }
529
530
531 /*
532 * Blit the bitmap
533 */
534
Draw(BRect update)535 void BitmapView::Draw(BRect update)
536 {
537 DrawBitmap(the_bitmap, update, update);
538 }
539
Draw(BRect from,BRect to)540 void BitmapView::Draw(BRect from, BRect to)
541 {
542 DrawBitmap(the_bitmap, from, to);
543 }
544
545
546 /*
547 * Mouse moved
548 */
549
MouseMoved(BPoint point,uint32 transit,const BMessage * message)550 void BitmapView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
551 {
552 newmousecounters = 0;
553 switch (transit) {
554 case B_ENTERED_VIEW:
555 newmousecounters = 1;
556 lastmx = point.x;
557 lastmy = point.y;
558 break;
559 case B_EXITED_VIEW:
560 break;
561 case B_INSIDE_VIEW:
562 lastmx = point.x;
563 lastmy = point.y;
564 break;
565 }
566 }
567
568
569 /*
570 * LED
571 */
572
LEDView(BRect frame,rgb_color active,rgb_color idle)573 LEDView::LEDView(BRect frame, rgb_color active, rgb_color idle) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
574 {
575 active_color = active;
576 idle_color = idle;
577 state = false;
578 SetViewColor(idle_color);
579 SetHighColor(idle_color);
580 bounds = Bounds();
581 }
582
Draw(BRect update)583 void LEDView::Draw(BRect update)
584 {
585 FillRect(bounds);
586 }
587
SetState(bool new_state)588 void LEDView::SetState(bool new_state)
589 {
590 if (new_state != state) {
591 state = new_state;
592 Window()->Lock();
593 if (state) {
594 SetViewColor(active_color);
595 SetHighColor(active_color);
596 } else {
597 SetViewColor(idle_color);
598 SetHighColor(idle_color);
599 }
600 Draw(bounds);
601 Window()->Unlock();
602 }
603 }
604
605
606 /*
607 * Redraw a line
608 */
609
flush_line(int y)610 void flush_line(int y)
611 {
612 if (window_open) {
613 bitmap_window->Lock();
614 bitmap_view->Draw(BRect(0, y, currprefs.gfx_width-1, y));
615 bitmap_window->Unlock();
616 }
617 }
618
619
620 /*
621 * Redraw a block
622 */
623
flush_block(int ystart,int ystop)624 void flush_block(int ystart, int ystop)
625 {
626 }
627
628
629 /*
630 * Redraw the screen
631 */
632
flush_screen(int ystart,int ystop)633 void flush_screen(int ystart, int ystop)
634 {
635 if (window_open)
636 bitmap_window->PostMessage(new BMessage(MSG_REDRAW));
637 }
638
639
640 /*
641 * Init graphics
642 */
643
graphics_setup(void)644 int graphics_setup(void)
645 {
646 return 1;
647 }
648
graphics_init(void)649 int graphics_init(void)
650 {
651 return the_app->GraphicsInit();
652 }
653
GraphicsInit(void)654 int UAE::GraphicsInit(void)
655 {
656 if (currprefs.color_mode > 5)
657 fprintf(stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
658
659 if (currprefs.gfx_width < 320)
660 currprefs.gfx_width = 320;
661 if (currprefs.gfx_height < 200)
662 currprefs.gfx_height = 200;
663 if (currprefs.gfx_height > 300 && ! currprefs.gfx_linedbl)
664 currprefs.gfx_height = 300;
665 if (currprefs.gfx_height > 600)
666 currprefs.gfx_height = 600;
667
668 gfxvidinfo.width = currprefs.gfx_width;
669 gfxvidinfo.height = currprefs.gfx_height;
670 gfxvidinfo.can_double = 1;
671
672 // Allocate bitmap
673 the_bitmap = new BBitmap(BRect(0, 0, currprefs.gfx_width-1, currprefs.gfx_height-1), B_COLOR_8_BIT);
674
675 // Set up vidinfo
676 gfxvidinfo.pixbytes = 1;
677 gfxvidinfo.rowbytes = the_bitmap->BytesPerRow();
678 gfxvidinfo.bufmem = (char *)the_bitmap->Bits();
679 gfxvidinfo.linemem = NULL;
680 gfxvidinfo.maxblocklines = 100; /* whatever... */
681
682 // Open window
683 main_window = new UAEWindow(BRect(0, 0, currprefs.gfx_width-1, currprefs.gfx_height-1), the_bitmap);
684
685 // Initialize mouse and keyboard variables
686 buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
687 lastmx = lastmy = 0;
688 newmousecounters = 0;
689
690 return true;
691 }
692
693
694 /*
695 * Exit graphics
696 */
697
graphics_leave(void)698 void graphics_leave(void)
699 {
700 the_app->GraphicsLeave();
701 }
702
GraphicsLeave(void)703 void UAE::GraphicsLeave(void)
704 {
705 // Deallocate bitmap
706 delete the_bitmap;
707 }
708
709
710 /*
711 * Poll mouse and keyboard
712 */
713
handle_events(void)714 void handle_events(void)
715 {
716 key_info the_key_info;
717 int be_code, be_byte, be_bit, amiga_code;
718 BPoint mouse_point;
719 uint32 mouse_buttons;
720
721 if (reset_thyself) {
722 uae_reset();
723 reset_thyself = false;
724 }
725
726 // Redraw drive LEDs
727 for (int i=0; i<4; i++)
728 DriveLED[i]->SetState(LEDs[i]);
729
730 if (window_open && bitmap_window->IsActive()) {
731
732 get_key_info(&the_key_info);
733 bitmap_window->Lock();
734 bitmap_view->GetMouse(&mouse_point, &mouse_buttons, false);
735 bitmap_window->Unlock();
736
737 // Keyboard
738 if (memcmp(the_key_info.key_states, old_key_info.key_states, sizeof(the_key_info.key_states))) {
739 for (be_code=0; be_code<0x80; be_code++) {
740 be_byte = be_code >> 3;
741 be_bit = 1 << (~be_code & 7);
742
743 // Key state changed?
744 if ((the_key_info.key_states[be_byte] & be_bit)
745 != (old_key_info.key_states[be_byte] & be_bit)) {
746
747 amiga_code = keycode2amiga[be_code];
748 if (the_key_info.key_states[be_byte] & be_bit) {
749
750 // Key pressed
751 if (amiga_code == AK_mousestuff)
752 togglemouse();
753 else
754 record_key(amiga_code << 1);
755 } else {
756
757 // Key released
758 record_key((amiga_code << 1) | 1);
759 }
760 }
761 }
762 old_key_info = the_key_info;
763 }
764
765 // "Affengriff"
766 if ((the_key_info.key_states[0x5c >> 3] & (1 << (~0x5c & 7)))
767 && (the_key_info.key_states[0x5d >> 3] & (1 << (~0x5d & 7)))
768 && (the_key_info.key_states[0x5f >> 3] & (1 << (~0x5f & 7))))
769 m68k_reset();
770
771 // Scroll lock toggles inhibit_frame
772 if (inhibit_frame != 2)
773 inhibit_frame = the_key_info.key_states[0x0f >> 3] & (1 << (~0x0f & 7));
774
775 // Mouse buttons
776 if (mouse_point.x >= 0 && mouse_point.y >= 0 && mouse_point.x < currprefs.gfx_width && mouse_point.y < currprefs.gfx_height) {
777 buttonstate[0] = mouse_buttons & B_PRIMARY_MOUSE_BUTTON;
778 buttonstate[1] = mouse_buttons & B_TERTIARY_MOUSE_BUTTON;
779 buttonstate[2] = mouse_buttons & B_SECONDARY_MOUSE_BUTTON;
780 }
781 }
782 }
783
784
785 /*
786 * Joystick routines
787 */
788
789 extern "C" {
790 void init_joystick(void);
791 void close_joystick(void);
792 void read_joystick(int nr, unsigned int *dir, int *button);
793 };
794
795 int nr_joysticks;
796
read_joystick(int nr,unsigned int * dir,int * button)797 void read_joystick(int nr, unsigned int *dir, int *button)
798 {
799 static int joy_minx = 32767, joy_maxx = 0,
800 joy_miny = 32767, joy_maxy = 0;
801 int left = 0, right = 0, top = 0, bot = 0;
802
803 *dir = 0;
804 *button = 0;
805
806 if (nr >= nr_joysticks)
807 return;
808
809 if (joy->Update() != B_ERROR) {
810 if (joy->horizontal > joy_maxx)
811 joy_maxx = joy->horizontal;
812 if (joy->horizontal < joy_minx)
813 joy_minx = joy->horizontal;
814 if (joy->vertical > joy_maxy)
815 joy_maxy = joy->vertical;
816 if (joy->vertical < joy_miny)
817 joy_miny = joy->vertical;
818
819 if (joy_maxx-joy_minx < 100 || joy_maxy-joy_miny < 100)
820 return;
821
822 if (joy->horizontal < (joy_minx + (joy_maxx-joy_minx)/3))
823 right = 1;
824 else if (joy->horizontal > (joy_minx + 2*(joy_maxx-joy_minx)/3))
825 left = 1;
826
827 if (joy->vertical < (joy_miny + (joy_maxy-joy_miny)/3))
828 bot = 1;
829 else if (joy->vertical > (joy_miny + 2*(joy_maxy-joy_miny)/3))
830 top = 1;
831
832 if (left) top = !top;
833 if (right) bot = !bot;
834 *dir = bot | (right << 1) | (top << 8) | (left << 9);
835 *button = !joy->button1;
836 }
837 }
838
init_joystick(void)839 void init_joystick(void)
840 {
841 joy = new BJoystick();
842 joy->Open("joystick1");
843 nr_joysticks = 1;
844 }
845
close_joystick(void)846 void close_joystick(void)
847 {
848 joy->Close();
849 delete joy;
850 }
851
852
853 /*
854 * Sound routines
855 */
856
857 extern "C" {
858 extern int sound_available;
859 extern int smplcnt;
860 extern int init_sound(void);
861 extern int setup_sound(void);
862 extern void flush_sound_buffer(void);
863 extern void init_sound_table16(void);
864 extern void sample16_handler(void);
865 };
866
867 uae_u16 *sndbuffer;
868 uae_u16 *sndbufpt;
869 int sndbufsize;
870
871 static uint8 *buffers[2] = {NULL, NULL};
872 static int buf_num;
873 static BDACStream *the_stream;
874 static BSubscriber *the_sub;
875 static bool sound_ready = false;
876 static sem_id sound_sync_sem;
877
878 bool stream_func(void *arg, char *buf, size_t count, void *header);
879
init_sound(void)880 int init_sound(void)
881 {
882 sound_sync_sem = create_sem(0, "UAE Sound Sync Semaphore");
883 the_stream = new BDACStream();
884 the_sub = new BSubscriber("UAE DAC subscriber");
885
886 if (!currprefs.produce_sound)
887 return 0;
888 sound_ready = the_sub->Subscribe(the_stream) == B_NO_ERROR;
889 if (!sound_ready)
890 return 0;
891
892 sndbufsize = 44100 / 8 * 4;
893 buffers[0] = new uint8[sndbufsize];
894 buffers[1] = new uint8[sndbufsize];
895 memset(buffers[0], 0, sndbufsize);
896 memset(buffers[1], 0, sndbufsize);
897 buf_num = 0;
898 sndbufpt = sndbuffer = (uae_u16 *)buffers[buf_num];
899
900 init_sound_table16();
901 eventtab[ev_sample].handler = sample16_handler;
902 scaled_sample_evtime = (unsigned long)maxhpos * maxvpos * vblank_hz * CYCLE_UNIT / 44100;
903 scaled_sample_evtime_ok = 1;
904
905 sound_available = 1;
906 the_stream->SetSamplingRate(44100);
907 the_stream->SetStreamBuffers(sndbufsize, 4);
908 the_sub->EnterStream(NULL, true, NULL, stream_func, NULL, true);
909 return 1;
910 }
911
setup_sound(void)912 int setup_sound(void)
913 {
914 sound_available = 1;
915 return 1;
916 }
917
close_sound(void)918 void close_sound(void)
919 {
920 if (sound_ready) {
921 the_sub->ExitStream(true);
922 the_stream->SetStreamBuffers(4096, 8);
923 the_sub->Unsubscribe();
924 sound_ready = false;
925 }
926 delete the_sub;
927 delete the_stream;
928
929 delete_sem(sound_sync_sem);
930
931 delete buffers[0];
932 delete buffers[1];
933 }
934
flush_sound_buffer(void)935 void flush_sound_buffer(void)
936 {
937 if (sound_ready) {
938 long l;
939 get_sem_count(sound_sync_sem, &l);
940 if (l > 0)
941 acquire_sem_etc(sound_sync_sem, l+1, 0, 0);
942 else
943 acquire_sem(sound_sync_sem);
944 }
945
946 sndbufpt = sndbuffer = (uae_u16 *)buffers[buf_num];
947 buf_num ^= 1;
948 }
949
stream_func(void * arg,char * buf,size_t count,void * header)950 bool stream_func(void *arg, char *buf, size_t count, void *header)
951 {
952 memcpy(buf, buffers[buf_num], count);
953 release_sem(sound_sync_sem);
954 return true;
955 }
956
957
958 /*
959 * Misc routines
960 */
961
debuggable(void)962 int debuggable(void)
963 {
964 return true;
965 }
966
needmousehack(void)967 int needmousehack(void)
968 {
969 return true;
970 }
971
LED(int on)972 void LED(int on)
973 {
974 PowerLED->SetState(!on);
975 }
976
setup_brkhandler(void)977 void setup_brkhandler(void)
978 {
979 }
980
gui_changesettings(void)981 void gui_changesettings(void)
982 {
983 }
984
gui_led(int led,int on)985 void gui_led(int led, int on)
986 {
987 if (led > 0 && led < 5)
988 LEDs[led-1] = on;
989 }
990
gui_init(void)991 int gui_init(void)
992 {
993 LEDs[0] = LEDs[1] = LEDs[2] = LEDs[3] = false;
994 quit_program = 0;
995 return 0;
996 }
997
gui_exit(void)998 void gui_exit(void)
999 {
1000 }
1001
gui_update(void)1002 int gui_update(void)
1003 {
1004 return 0;
1005 }
1006
gui_filename(int num,const char * name)1007 void gui_filename(int num, const char *name)
1008 {
1009 }
1010
getline(char * p)1011 static void getline(char *p)
1012 {
1013 }
1014
gui_handle_events(void)1015 void gui_handle_events(void)
1016 {
1017 }
1018