ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/Display_Be.h
Revision: 1.2
Committed: 2003-07-01T17:51:17Z (20 years, 9 months ago) by cebix
Content type: text/plain
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
updated copyright date

File Contents

# Content
1 /*
2 * Display_Be.h - C64 graphics display, emulator window handling,
3 * Be specific stuff
4 *
5 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <AppKit.h>
23 #include <InterfaceKit.h>
24 #include <GameKit.h>
25 #include <string.h>
26
27 #include "C64.h"
28 #include "main.h"
29
30
31 // Window thread messages
32 const uint32 MSG_REDRAW = 1;
33
34
35 // C64 display and window frame
36 const BRect DisplayFrame = BRect(0, 0, DISPLAY_X-1, DISPLAY_Y-1);
37 const BRect WindowFrame = BRect(0, 0, DISPLAY_X-1, DISPLAY_Y-1 + 16);
38
39
40 // Background color
41 const rgb_color fill_gray = {208, 208, 208, 0};
42 const rgb_color shine_gray = {232, 232, 232, 0};
43 const rgb_color shadow_gray = {152, 152, 152, 0};
44
45
46 /*
47 C64 keyboard matrix:
48
49 Bit 7 6 5 4 3 2 1 0
50 0 CUD F5 F3 F1 F7 CLR RET DEL
51 1 SHL E S Z 4 A W 3
52 2 X T F C 6 D R 5
53 3 V U H B 8 G Y 7
54 4 N O K M 0 J I 9
55 5 , @ : . - L P +
56 6 / ^ = SHR HOM ; * £
57 7 R/S Q C= SPC 2 CTL <- 1
58 */
59
60
61 /*
62 Tables for key translation
63 Bit 0..2: row/column in C64 keyboard matrix
64 Bit 3 : implicit shift
65 Bit 5 : joystick emulation (bit 0..4: mask)
66 */
67
68 const int key_byte[128] = {
69 -1, 7, 0,8+0, 0,8+0, 0, 8+0,
70 0, 8+0, -1, -1, -1, -1, -1, -1,
71
72 7, 7, 7, 7, 1, 1, 2, 2,
73 3, 3, 4, 4, 5, 5, 0, 8+0,
74
75 6, 6, -1, -1, -1, -1, -1, 7,
76 1, 1, 2, 2, 3, 3, 4, 4,
77
78 5, 5, 6, 6, 0, 6, 6,0x25,
79 0x21,0x29, -1, 1, 1, 1, 2, 2,
80
81 3, 3, 4, 4, 5, 5, 6, 0,
82 0x24,0x30,0x28, 1, 1, 2, 2, 3,
83
84 3, 4, 4, 5, 5, 6, 6, 8+0,
85 0x26,0x22,0x2a, 0, 7, -1, 7, -1,
86
87 7, 8+0, 0, 0,0x30, -1, 7, 7,
88 -1, -1, -1, -1, -1, -1, -1, -1,
89
90 -1, -1, -1, -1, -1, -1, -1, -1,
91 -1, -1, -1, -1, -1, -1, -1, -1
92 };
93
94 const int key_bit[128] = {
95 -1, 7, 4, 4, 5, 5, 6, 6,
96 3, 3, -1, -1, -1, -1, -1, -1,
97
98 7, 1, 0, 3, 0, 3, 0, 3,
99 0, 3, 0, 3, 0, 3, 0, 0,
100
101 3, 0, -1, -1, -1, -1, -1, 6,
102 1, 6, 1, 6, 1, 6, 1, 6,
103
104 1, 6, 1, 6, 0, 0, 5, -1,
105 -1, -1, -1, 7, 2, 5, 2, 5,
106
107 2, 5, 2, 5, 2, 5, 2, 1,
108 -1, -1, -1, 7, 4, 7, 4, 7,
109
110 4, 7, 4, 7, 4, 7, 4, 7,
111 -1, -1, -1, 1, 2, -1, 4, -1,
112
113 5, 2, 7, 2, -1, -1, 5, 5,
114 -1, -1, -1, -1, -1, -1, -1, -1,
115
116 -1, -1, -1, -1, -1, -1, -1, -1,
117 -1, -1, -1, -1, -1, -1, -1, -1
118 };
119
120
121 /*
122 * A simple view class for blitting a bitmap on the screen
123 */
124
125 class BitmapView : public BView {
126 public:
127 BitmapView(BRect frame, BBitmap *bitmap);
128 virtual void Draw(BRect update);
129 virtual void KeyDown(const char *bytes, int32 numBytes);
130 void ChangeBitmap(BBitmap *bitmap);
131
132 private:
133 BBitmap *the_bitmap;
134 };
135
136
137 /*
138 * Class for the main C64 display window
139 */
140
141 class SpeedoView;
142 class LEDView;
143
144 class C64Window : public BWindow {
145 public:
146 C64Window();
147
148 virtual bool QuitRequested(void);
149 virtual void MessageReceived(BMessage *msg);
150
151 BBitmap *TheBitmap[2];
152 SpeedoView *Speedometer;
153 LEDView *LED[4];
154
155 private:
156 BitmapView *main_view;
157 };
158
159
160 /*
161 * Class for the main C64 display using the GameKit
162 */
163
164 class C64Screen : public BWindowScreen {
165 public:
166 C64Screen(C64Display *display) : BWindowScreen("Frodo", B_8_BIT_640x480, &error), the_display(display)
167 {
168 Lock();
169 BitmapView *main_view = new BitmapView(Bounds(), NULL);
170 AddChild(main_view);
171 main_view->MakeFocus();
172 Connected = false;
173 Unlock();
174 }
175
176 virtual void ScreenConnected(bool active);
177 virtual void DispatchMessage(BMessage *msg, BHandler *handler);
178 void DrawLED(int i, int state);
179 void DrawSpeedometer(void);
180 void FillRect(int x1, int y1, int x2, int y2, int color);
181
182 bool Connected; // Flag: screen connected
183 int Speed;
184 char SpeedoStr[16]; // Speedometer value converted to a string
185
186 private:
187 C64Display *the_display;
188 status_t error;
189 };
190
191
192 /*
193 * Class for speedometer
194 */
195
196 class SpeedoView : public BView {
197 public:
198 SpeedoView(BRect frame);
199 virtual void Draw(BRect update);
200 virtual void Pulse(void);
201 void SetValue(int percent);
202
203 private:
204 char speedostr[16]; // Speedometer value converted to a string
205 BRect bounds;
206 };
207
208
209 /*
210 * Class for drive LED
211 */
212
213 class LEDView : public BView {
214 public:
215 LEDView(BRect frame, const char *label);
216 virtual void Draw(BRect update);
217 virtual void Pulse(void);
218 void DrawLED(void);
219 void SetState(int state);
220
221 private:
222 int current_state;
223 const char *the_label;
224 BRect bounds;
225 };
226
227
228 /*
229 * Display constructor: Create window/screen
230 */
231
232 C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
233 {
234 // LEDs off
235 for (int i=0; i<4; i++)
236 led_state[i] = old_led_state[i] = LED_OFF;
237
238 // Open window/screen
239 draw_bitmap = 1;
240 if (ThePrefs.DisplayType == DISPTYPE_SCREEN) {
241 using_screen = true;
242 the_screen = new C64Screen(this);
243 the_screen->Show();
244 while (!the_screen->Connected)
245 snooze(20000);
246 } else {
247 using_screen = false;
248 the_window = new C64Window();
249 the_window->Show();
250 }
251
252 // Prepare key_info buffer
253 get_key_info(&old_key_info);
254 }
255
256
257 /*
258 * Display destructor
259 */
260
261 C64Display::~C64Display()
262 {
263 if (using_screen) {
264 the_screen->Lock();
265 the_screen->Quit();
266 } else {
267 the_window->Lock();
268 the_window->Quit();
269 }
270 }
271
272
273 /*
274 * Prefs may have changed
275 */
276
277 void C64Display::NewPrefs(Prefs *prefs)
278 {
279 if (prefs->DisplayType == DISPTYPE_SCREEN) {
280 if (!using_screen) {
281 // Switch to full screen display
282 using_screen = true;
283 the_window->Lock();
284 the_window->Quit();
285 the_screen = new C64Screen(this);
286 the_screen->Show();
287 while (!the_screen->Connected)
288 snooze(20000);
289 }
290 } else {
291 if (using_screen) {
292 // Switch to window display
293 using_screen = false;
294 the_screen->Lock();
295 the_screen->Quit();
296 the_window = new C64Window();
297 the_window->Show();
298 }
299 }
300 }
301
302
303 /*
304 * Redraw bitmap (let the window thread do it)
305 */
306
307 void C64Display::Update(void)
308 {
309 if (using_screen) {
310
311 // Update LEDs/speedometer
312 for (int i=0; i<4; i++)
313 the_screen->DrawLED(i, led_state[i]);
314 the_screen->DrawSpeedometer();
315
316 } else {
317
318 // Update C64 display
319 BMessage msg(MSG_REDRAW);
320 msg.AddInt32("bitmap", draw_bitmap);
321 the_window->PostMessage(&msg);
322 draw_bitmap ^= 1;
323
324 // Update LEDs
325 for (int i=0; i<4; i++)
326 if (led_state[i] != old_led_state[i]) {
327 the_window->LED[i]->SetState(led_state[i]);
328 old_led_state[i] = led_state[i];
329 }
330 }
331 }
332
333
334 /*
335 * Set value displayed by the speedometer
336 */
337
338 void C64Display::Speedometer(int speed)
339 {
340 if (using_screen) {
341 the_screen->Speed = speed;
342 sprintf(the_screen->SpeedoStr, "%3d%%", speed);
343 } else
344 the_window->Speedometer->SetValue(speed);
345 }
346
347
348 /*
349 * Return pointer to bitmap data
350 */
351
352 uint8 *C64Display::BitmapBase(void)
353 {
354 if (using_screen)
355 return (uint8 *)the_screen->CardInfo()->frame_buffer;
356 else
357 return (uint8 *)the_window->TheBitmap[draw_bitmap]->Bits();
358 }
359
360
361 /*
362 * Return number of bytes per row
363 */
364
365 int C64Display::BitmapXMod(void)
366 {
367 if (using_screen)
368 return the_screen->CardInfo()->bytes_per_row;
369 else
370 return the_window->TheBitmap[draw_bitmap]->BytesPerRow();
371 }
372
373
374 /*
375 * Poll the keyboard
376 */
377
378 void C64Display::PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick)
379 {
380 key_info the_key_info;
381 int be_code, be_byte, be_bit, c64_byte, c64_bit;
382 bool shifted;
383
384 // Window must be active, command key must be up
385 if (using_screen) {
386 if (!the_screen->Connected)
387 return;
388 } else
389 if (!the_window->IsActive())
390 return;
391 if (!(modifiers() & B_COMMAND_KEY)) {
392
393 // Read the state of all keys
394 get_key_info(&the_key_info);
395
396 // Did anything change at all?
397 if (!memcmp(&old_key_info, &the_key_info, sizeof(key_info)))
398 return;
399
400 // Loop to convert BeOS keymap to C64 keymap
401 for (be_code=0; be_code<0x68; be_code++) {
402 be_byte = be_code >> 3;
403 be_bit = 1 << (~be_code & 7);
404
405 // Key state changed?
406 if ((the_key_info.key_states[be_byte] & be_bit)
407 != (old_key_info.key_states[be_byte] & be_bit)) {
408
409 c64_byte = key_byte[be_code];
410 c64_bit = key_bit[be_code];
411 if (c64_byte != -1) {
412 if (!(c64_byte & 0x20)) {
413
414 // Normal keys
415 shifted = c64_byte & 8;
416 c64_byte &= 7;
417 if (the_key_info.key_states[be_byte] & be_bit) {
418
419 // Key pressed
420 if (shifted) {
421 key_matrix[6] &= 0xef;
422 rev_matrix[4] &= 0xbf;
423 }
424 key_matrix[c64_byte] &= ~(1 << c64_bit);
425 rev_matrix[c64_bit] &= ~(1 << c64_byte);
426 } else {
427
428 // Key released
429 if (shifted) {
430 key_matrix[6] |= 0x10;
431 rev_matrix[4] |= 0x40;
432 }
433 key_matrix[c64_byte] |= (1 << c64_bit);
434 rev_matrix[c64_bit] |= (1 << c64_byte);
435 }
436 } else {
437
438 // Joystick emulation
439 c64_byte &= 0x1f;
440 if (the_key_info.key_states[be_byte] & be_bit)
441 *joystick &= ~c64_byte;
442 else
443 *joystick |= c64_byte;
444 }
445 }
446 }
447 }
448
449 old_key_info = the_key_info;
450 }
451 }
452
453
454 /*
455 * Check if NumLock is down (for switching the joystick keyboard emulation)
456 */
457
458 bool C64Display::NumLock(void)
459 {
460 return modifiers() & B_NUM_LOCK;
461 }
462
463
464 /*
465 * Allocate C64 colors
466 */
467
468 void C64Display::InitColors(uint8 *colors)
469 {
470 BScreen scr(using_screen ? (BWindow *)the_screen : the_window);
471 for (int i=0; i<256; i++)
472 colors[i] = scr.IndexForColor(palette_red[i & 0x0f], palette_green[i & 0x0f], palette_blue[i & 0x0f]);
473 }
474
475
476 /*
477 * Pause display (GameKit only)
478 */
479
480 void C64Display::Pause(void)
481 {
482 if (using_screen)
483 the_screen->Hide();
484 }
485
486
487 /*
488 * Resume display (GameKit only)
489 */
490
491 void C64Display::Resume(void)
492 {
493 if (using_screen)
494 the_screen->Show();
495 }
496
497
498 /*
499 * Window constructor
500 */
501
502 C64Window::C64Window() : BWindow(WindowFrame, "Frodo", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
503 {
504 // Move window to right position
505 Lock();
506 MoveTo(80, 60);
507
508 // Set up menus
509 BMenuBar *bar = new BMenuBar(Bounds(), "");
510 BMenu *menu = new BMenu("Frodo");
511 menu->AddItem(new BMenuItem("About Frodo" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)));
512 menu->AddItem(new BSeparatorItem);
513 menu->AddItem(new BMenuItem("Preferences" B_UTF8_ELLIPSIS, new BMessage(MSG_PREFS), 'P'));
514 menu->AddItem(new BSeparatorItem);
515 menu->AddItem(new BMenuItem("Reset C64", new BMessage(MSG_RESET)));
516 menu->AddItem(new BMenuItem("Insert next disk", new BMessage(MSG_NEXTDISK), 'D'));
517 menu->AddItem(new BMenuItem("SAM" B_UTF8_ELLIPSIS, new BMessage(MSG_SAM), 'M'));
518 menu->AddItem(new BSeparatorItem);
519 menu->AddItem(new BMenuItem("Load snapshot" B_UTF8_ELLIPSIS, new BMessage(MSG_OPEN_SNAPSHOT), 'O'));
520 menu->AddItem(new BMenuItem("Save snapshot" B_UTF8_ELLIPSIS, new BMessage(MSG_SAVE_SNAPSHOT), 'S'));
521 menu->AddItem(new BSeparatorItem);
522 menu->AddItem(new BMenuItem("Quit Frodo", new BMessage(B_QUIT_REQUESTED), 'Q'));
523 menu->SetTargetForItems(be_app);
524 bar->AddItem(menu);
525 AddChild(bar);
526 SetKeyMenuBar(bar);
527 int mbar_height = bar->Frame().bottom + 1;
528
529 // Resize window to fit menu bar
530 ResizeBy(0, mbar_height);
531
532 // Allocate bitmaps
533 TheBitmap[0] = new BBitmap(DisplayFrame, B_COLOR_8_BIT);
534 TheBitmap[1] = new BBitmap(DisplayFrame, B_COLOR_8_BIT);
535
536 // Create top view
537 BRect b = Bounds();
538 BView *top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, 0);
539 AddChild(top);
540
541 // Create bitmap view
542 main_view = new BitmapView(DisplayFrame, TheBitmap[0]);
543 top->AddChild(main_view);
544 main_view->MakeFocus();
545
546 // Create speedometer
547 Speedometer = new SpeedoView(BRect(0, DISPLAY_Y, DISPLAY_X/5-1, DISPLAY_Y+15));
548 top->AddChild(Speedometer);
549
550 // Create drive LEDs
551 LED[0] = new LEDView(BRect(DISPLAY_X/5, DISPLAY_Y, DISPLAY_X*2/5-1, DISPLAY_Y+15), "Drive 8");
552 top->AddChild(LED[0]);
553 LED[1] = new LEDView(BRect(DISPLAY_X*2/5, DISPLAY_Y, DISPLAY_X*3/5-1, DISPLAY_Y+15), "Drive 9");
554 top->AddChild(LED[1]);
555 LED[2] = new LEDView(BRect(DISPLAY_X*3/5, DISPLAY_Y, DISPLAY_X*4/5-1, DISPLAY_Y+15), "Drive 10");
556 top->AddChild(LED[2]);
557 LED[3] = new LEDView(BRect(DISPLAY_X*4/5, DISPLAY_Y, DISPLAY_X-1, DISPLAY_Y+15), "Drive 11");
558 top->AddChild(LED[3]);
559
560 // Set pulse rate to 0.4 seconds for blinking drive LEDs
561 SetPulseRate(400000);
562 Unlock();
563 }
564
565
566 /*
567 * Closing the window quits Frodo
568 */
569
570 bool C64Window::QuitRequested(void)
571 {
572 be_app->PostMessage(B_QUIT_REQUESTED);
573 return false;
574 }
575
576
577 /*
578 * Handles redraw messages
579 */
580
581 void C64Window::MessageReceived(BMessage *msg)
582 {
583 BMessage *msg2;
584
585 switch (msg->what) {
586 case MSG_REDRAW: // Redraw bitmap
587 MessageQueue()->Lock();
588 while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL)
589 MessageQueue()->RemoveMessage(msg2);
590 MessageQueue()->Unlock();
591 main_view->ChangeBitmap(TheBitmap[msg->FindInt32("bitmap")]);
592 Lock();
593 main_view->Draw(DisplayFrame);
594 Unlock();
595 break;
596
597 default:
598 BWindow::MessageReceived(msg);
599 }
600 }
601
602
603 /*
604 * Workspace activated/deactivated
605 */
606
607 void C64Screen::ScreenConnected(bool active)
608 {
609 if (active) {
610 FillRect(0, 0, 639, 479, 0); // Clear screen
611 the_display->TheC64->Resume();
612 Connected = true;
613 } else {
614 the_display->TheC64->Pause();
615 Connected = false;
616 }
617 BWindowScreen::ScreenConnected(active);
618 }
619
620
621 /*
622 * Simulate menu commands
623 */
624
625 void C64Screen::DispatchMessage(BMessage *msg, BHandler *handler)
626 {
627 switch (msg->what) {
628 case B_KEY_DOWN: {
629 uint32 mods = msg->FindInt32("modifiers");
630 if (mods & B_COMMAND_KEY) {
631 uint32 key = msg->FindInt32("raw_char");
632 switch (key) {
633 case 'p':
634 be_app->PostMessage(MSG_PREFS);
635 break;
636 case 'd':
637 be_app->PostMessage(MSG_NEXTDISK);
638 break;
639 case 'm':
640 be_app->PostMessage(MSG_SAM);
641 break;
642 }
643 }
644 BWindowScreen::DispatchMessage(msg, handler);
645 break;
646 }
647
648 default:
649 BWindowScreen::DispatchMessage(msg, handler);
650 }
651 }
652
653
654 /*
655 * Draw drive LEDs
656 */
657
658 void C64Screen::DrawLED(int i, int state)
659 {
660 switch (state) {
661 case LED_ON:
662 FillRect(10+i*20, DISPLAY_Y-20, 20+i*20, DISPLAY_Y-12, 54);
663 break;
664 case LED_ERROR_ON:
665 FillRect(10+i*20, DISPLAY_Y-20, 20+i*20, DISPLAY_Y-12, 44);
666 break;
667 }
668 }
669
670
671 /*
672 * Draw speedometer
673 */
674
675 static const int8 Digits[11][8] = { // Digit images
676 {0x3c, 0x66, 0x6e, 0x76, 0x66, 0x66, 0x3c, 0x00},
677 {0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00},
678 {0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00},
679 {0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00},
680 {0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00},
681 {0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00},
682 {0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00},
683 {0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00},
684 {0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00},
685 {0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00},
686 {0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00},
687 };
688
689 void C64Screen::DrawSpeedometer()
690 {
691 // Don't display speedometer if we're running at about 100%
692 if (Speed >= 99 && Speed <= 101)
693 return;
694
695 char *s = SpeedoStr;
696 char c;
697 long xmod = CardInfo()->bytes_per_row;
698 uint8 *p = (uint8 *)CardInfo()->frame_buffer + DISPLAY_X - 8*8 + (DISPLAY_Y-20) * xmod;
699 while (c = *s++) {
700 if (c == ' ')
701 continue;
702 if (c == '%')
703 c = 10;
704 else
705 c -= '0';
706 uint8 *q = p;
707 for (int y=0; y<8; y++) {
708 uint8 data = Digits[c][y];
709 for (int x=0; x<8; x++) {
710 if (data & (1 << (7-x)))
711 q[x] = 255;
712 else
713 q[x] = 0;
714 }
715 q += xmod;
716 }
717 p += 8;
718 }
719 }
720
721
722 /*
723 * Fill rectangle
724 */
725
726 void C64Screen::FillRect(int x1, int y1, int x2, int y2, int color)
727 {
728 long xmod = CardInfo()->bytes_per_row;
729 uint8 *p = (uint8 *)CardInfo()->frame_buffer + y1 * xmod + x1;
730 int n = x2 - x1 + 1;
731 for(int y=y1; y<=y2; y++) {
732 memset_nc(p, color, n);
733 p += xmod;
734 }
735 }
736
737
738 /*
739 * Bitmap view constructor
740 */
741
742 BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
743 {
744 ChangeBitmap(bitmap);
745 }
746
747
748 /*
749 * Blit the bitmap
750 */
751
752 void BitmapView::Draw(BRect update)
753 {
754 if (the_bitmap != NULL)
755 DrawBitmapAsync(the_bitmap, update, update);
756 }
757
758
759 /*
760 * Receive special key-down events (main C64 keyboard handling is done in PollKeyboard)
761 */
762
763 void BitmapView::KeyDown(const char *bytes, int32 numBytes)
764 {
765 if (bytes[0] == B_FUNCTION_KEY || bytes[0] == '+' || bytes[0] == '-' || bytes[0] == '*' || bytes[0] == '/') {
766 BMessage *msg = Window()->CurrentMessage();
767 long key;
768 if (msg->FindInt32("key", &key) == B_NO_ERROR) {
769 switch (key) {
770
771 case B_F11_KEY: // F11: NMI (Restore)
772 be_app->PostMessage(MSG_NMI);
773 break;
774
775 case B_F12_KEY: // F12: Reset
776 be_app->PostMessage(MSG_RESET);
777 break;
778
779 case 0x3a: // '+' on keypad: Increase SkipFrames
780 ThePrefs.SkipFrames++;
781 break;
782
783 case 0x25: // '-' on keypad: Decrease SkipFrames
784 if (ThePrefs.SkipFrames > 1)
785 ThePrefs.SkipFrames--;
786 break;
787
788 case 0x24: // '*' on keypad: Toggle speed limiter
789 ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed;
790 break;
791
792 case 0x23: // '/' on keypad: Toggle processor-level 1541 emulation
793 be_app->PostMessage(MSG_TOGGLE_1541);
794 break;
795 }
796 }
797 }
798 }
799
800
801 /*
802 * Change view bitmap
803 */
804
805 void BitmapView::ChangeBitmap(BBitmap *bitmap)
806 {
807 the_bitmap = bitmap;
808 }
809
810
811 /*
812 * Speedometer constructor
813 */
814
815 SpeedoView::SpeedoView(BRect frame) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED)
816 {
817 speedostr[0] = 0;
818 bounds = Bounds();
819 SetViewColor(fill_gray);
820 SetFont(be_plain_font);
821 }
822
823
824 /*
825 * Draw speedometer
826 */
827
828 void SpeedoView::Draw(BRect update)
829 {
830 // Draw bevelled border
831 SetHighColor(shine_gray);
832 StrokeLine(BPoint(0, bounds.bottom), BPoint(0, 0));
833 StrokeLine(BPoint(bounds.right, 0));
834 SetHighColor(shadow_gray);
835 StrokeLine(BPoint(bounds.right, bounds.bottom), BPoint(bounds.right, 1));
836
837 // Draw text
838 SetHighColor(0, 0, 0);
839 DrawString(speedostr, BPoint(24, 12));
840 }
841
842
843 /*
844 * Update speedometer at regular intervals
845 */
846
847 void SpeedoView::Pulse(void)
848 {
849 Invalidate(BRect(1, 1, bounds.right-1, 15));
850 }
851
852
853 /*
854 * Set new speedometer value
855 */
856
857 void SpeedoView::SetValue(int speed)
858 {
859 sprintf(speedostr, "%d%%", speed);
860 }
861
862
863 /*
864 * LED view constructor
865 */
866
867 LEDView::LEDView(BRect frame, const char *label) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED)
868 {
869 current_state = 0;
870 the_label = label;
871 bounds = Bounds();
872 SetViewColor(fill_gray);
873 SetFont(be_plain_font);
874 }
875
876
877 /*
878 * Draw drive LED
879 */
880
881 void LEDView::Draw(BRect update)
882 {
883 // Draw bevelled border
884 SetHighColor(shine_gray);
885 StrokeLine(BPoint(0, bounds.bottom), BPoint(0, 0));
886 StrokeLine(BPoint(bounds.right, 0));
887 SetHighColor(shadow_gray);
888 StrokeLine(BPoint(bounds.right, bounds.bottom), BPoint(bounds.right, 1));
889
890 // Draw label
891 SetHighColor(0, 0, 0);
892 SetLowColor(fill_gray);
893 DrawString(the_label, BPoint(8, 12));
894
895 // Draw LED
896 SetHighColor(shadow_gray);
897 StrokeLine(BPoint(bounds.right-24, 12), BPoint(bounds.right-24, 4));
898 StrokeLine(BPoint(bounds.right-8, 4));
899 SetHighColor(shine_gray);
900 StrokeLine(BPoint(bounds.right-23, 12), BPoint(bounds.right-8, 12));
901 StrokeLine(BPoint(bounds.right-8, 5));
902 DrawLED();
903 }
904
905
906 /*
907 * Redraw just the LED
908 */
909
910 void LEDView::DrawLED(void)
911 {
912 Window()->Lock();
913 switch (current_state) {
914 case LED_OFF:
915 case LED_ERROR_OFF:
916 SetHighColor(32, 32, 32);
917 break;
918 case LED_ON:
919 SetHighColor(0, 240, 0);
920 break;
921 case LED_ERROR_ON:
922 SetHighColor(240, 0, 0);
923 break;
924 }
925 FillRect(BRect(bounds.right-23, 5, bounds.right-9, 11));
926 Window()->Unlock();
927 }
928
929
930 /*
931 * Set LED state
932 */
933
934 void LEDView::SetState(int state)
935 {
936 if (state != current_state) {
937 current_state = state;
938 DrawLED();
939 }
940 }
941
942
943 /*
944 * Toggle red error LED
945 */
946
947 void LEDView::Pulse(void)
948 {
949 switch (current_state) {
950 case LED_ERROR_ON:
951 current_state = LED_ERROR_OFF;
952 DrawLED();
953 break;
954 case LED_ERROR_OFF:
955 current_state = LED_ERROR_ON;
956 DrawLED();
957 break;
958 }
959 }
960
961
962 /*
963 * Show a requester
964 */
965
966 long ShowRequester(char *str, char *button1, char *button2)
967 {
968 BAlert *the_alert;
969
970 the_alert = new BAlert("", str, button1, button2, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
971 return the_alert->Go();
972 }