Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

Display_Be.i

Go to the documentation of this file.
00001 /*
00002  *  Display_Be.i - C64 graphics display, emulator window handling,
00003  *                 Be specific stuff
00004  *
00005  *  Frodo (C) 1994-1997 Christian Bauer
00006  *  GameKit stuff by Tinic Urou
00007  */
00008 
00009 #include <AppKit.h>
00010 #include <InterfaceKit.h>
00011 #include <GameKit.h>
00012 #include <string.h>
00013 
00014 #include "C64.h"
00015 #include "main.h"
00016 
00017 
00018 // Window thread messages
00019 const uint32 MSG_REDRAW = 1;
00020 
00021 
00022 // C64 display and window frame
00023 const BRect DisplayFrame = BRect(0, 0, DISPLAY_X-1, DISPLAY_Y-1);
00024 const BRect WindowFrame = BRect(0, 0, DISPLAY_X-1, DISPLAY_Y-1 + 16);
00025 
00026 
00027 // Background color
00028 const rgb_color fill_gray = {208, 208, 208, 0};
00029 const rgb_color shine_gray = {232, 232, 232, 0};
00030 const rgb_color shadow_gray = {152, 152, 152, 0};
00031 
00032 
00033 /*
00034   C64 keyboard matrix:
00035 
00036     Bit 7   6   5   4   3   2   1   0
00037   0    CUD  F5  F3  F1  F7 CLR RET DEL
00038   1    SHL  E   S   Z   4   A   W   3
00039   2     X   T   F   C   6   D   R   5
00040   3     V   U   H   B   8   G   Y   7
00041   4     N   O   K   M   0   J   I   9
00042   5     ,   @   :   .   -   L   P   +
00043   6     /   ^   =  SHR HOM  ;   *   
00044   7    R/S  Q   C= SPC  2  CTL  <-  1
00045 */
00046 
00047 
00048 /*
00049   Tables for key translation
00050   Bit 0..2: row/column in C64 keyboard matrix
00051   Bit 3   : implicit shift
00052   Bit 5   : joystick emulation (bit 0..4: mask)
00053 */
00054 
00055 const int key_byte[128] = {
00056           -1,   7,   0,8+0,   0,8+0,  0, 8+0,
00057            0, 8+0,  -1, -1,  -1, -1, -1,  -1,
00058 
00059            7,   7,   7,  7,   1,  1,  2,   2,
00060            3,   3,   4,  4,   5,  5,  0, 8+0,
00061 
00062            6,   6,  -1, -1,  -1, -1, -1,   7,
00063            1,   1,   2,  2,   3,  3,  4,   4,
00064 
00065            5,   5,   6,  6,   0,  6,  6,0x25,
00066         0x21,0x29,  -1,  1,   1,  1,  2,   2,
00067 
00068            3,   3,   4,  4,   5,  5,  6,   0,
00069         0x24,0x30,0x28,  1,   1,  2,  2,   3,
00070 
00071            3,   4,   4,  5,   5,  6,  6, 8+0,
00072         0x26,0x22,0x2a,  0,   7, -1,  7,  -1,
00073 
00074            7, 8+0,   0,  0,0x30, -1,  7,   7,
00075           -1,  -1,  -1, -1,  -1, -1, -1,  -1,
00076 
00077           -1,  -1,  -1, -1,  -1, -1, -1,  -1,
00078           -1,  -1,  -1, -1,  -1, -1, -1,  -1
00079 };
00080 
00081 const int key_bit[128] = {
00082         -1,  7,  4,  4,  5,  5,  6,  6,
00083          3,  3, -1, -1, -1, -1, -1, -1,
00084 
00085          7,  1,  0,  3,  0,  3,  0,  3,
00086          0,  3,  0,  3,  0,  3,  0,  0,
00087 
00088          3,  0, -1, -1, -1, -1, -1,  6,
00089          1,  6,  1,  6,  1,  6,  1,  6,
00090 
00091          1,  6,  1,  6,  0,  0,  5, -1,
00092         -1, -1, -1,  7,  2,  5,  2,  5,
00093 
00094          2,  5,  2,  5,  2,  5,  2,  1,
00095         -1, -1, -1,  7,  4,  7,  4,  7,
00096 
00097          4,  7,  4,  7,  4,  7,  4,  7,
00098         -1, -1, -1,  1,  2, -1,  4, -1,
00099 
00100          5,  2,  7,  2, -1, -1,  5,  5,
00101         -1, -1, -1, -1, -1, -1, -1, -1,
00102 
00103         -1, -1, -1, -1, -1, -1, -1, -1,
00104         -1, -1, -1, -1, -1, -1, -1, -1
00105 };
00106 
00107 
00108 /*
00109  *  A simple view class for blitting a bitmap on the screen
00110  */
00111 
00112 class BitmapView : public BView {
00113 public:
00114         BitmapView(BRect frame, BBitmap *bitmap);
00115         virtual void Draw(BRect update);
00116         virtual void KeyDown(const char *bytes, int32 numBytes);
00117         void ChangeBitmap(BBitmap *bitmap);
00118 
00119 private:
00120         BBitmap *the_bitmap;
00121 };
00122 
00123 
00124 /*
00125  *  Class for the main C64 display window
00126  */
00127 
00128 class SpeedoView;
00129 class LEDView;
00130 
00131 class C64Window : public BWindow {
00132 public:
00133         C64Window();
00134 
00135         virtual bool QuitRequested(void);
00136         virtual void MessageReceived(BMessage *msg);
00137 
00138         BBitmap *TheBitmap[2];
00139         SpeedoView *Speedometer;
00140         LEDView *LED[4];
00141 
00142 private:
00143         BitmapView *main_view;
00144 };
00145 
00146 
00147 /*
00148  *  Class for the main C64 display using the GameKit
00149  */
00150 
00151 class C64Screen : public BWindowScreen {
00152 public:
00153         C64Screen(C64Display *display) : BWindowScreen("Frodo", B_8_BIT_640x480, &error), the_display(display)
00154         {
00155                 Lock();
00156                 BitmapView *main_view = new BitmapView(Bounds(), NULL);
00157                 AddChild(main_view);
00158                 main_view->MakeFocus();
00159                 Connected = false;
00160                 Unlock();
00161         }
00162 
00163         virtual void ScreenConnected(bool active);
00164         virtual void DispatchMessage(BMessage *msg, BHandler *handler);
00165         void DrawLED(int i, int state);
00166         void DrawSpeedometer(void);
00167         void FillRect(int x1, int y1, int x2, int y2, int color);
00168 
00169         bool Connected;                 // Flag: screen connected
00170         int Speed;
00171         char SpeedoStr[16];             // Speedometer value converted to a string
00172 
00173 private:
00174         C64Display *the_display;
00175         status_t error;
00176 };
00177 
00178 
00179 /*
00180  *  Class for speedometer
00181  */
00182 
00183 class SpeedoView : public BView {
00184 public:
00185         SpeedoView(BRect frame);
00186         virtual void Draw(BRect update);
00187         virtual void Pulse(void);
00188         void SetValue(int percent);
00189 
00190 private:
00191         char speedostr[16];             // Speedometer value converted to a string
00192         BRect bounds;
00193 };
00194 
00195 
00196 /*
00197  *  Class for drive LED
00198  */
00199 
00200 class LEDView : public BView {
00201 public:
00202         LEDView(BRect frame, const char *label);
00203         virtual void Draw(BRect update);
00204         virtual void Pulse(void);
00205         void DrawLED(void);
00206         void SetState(int state);
00207 
00208 private:
00209         int current_state;
00210         const char *the_label;
00211         BRect bounds;
00212 };
00213 
00214 
00215 /*
00216  *  Display constructor: Create window/screen
00217  */
00218 
00219 C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
00220 {
00221         // LEDs off
00222         for (int i=0; i<4; i++)
00223                 led_state[i] = old_led_state[i] = LED_OFF;
00224 
00225         // Open window/screen
00226         draw_bitmap = 1;
00227         if (ThePrefs.DisplayType == DISPTYPE_SCREEN) {
00228                 using_screen = true;
00229                 the_screen = new C64Screen(this);
00230                 the_screen->Show();
00231                 while (!the_screen->Connected)
00232                         snooze(20000);
00233         } else {
00234                 using_screen = false;
00235                 the_window = new C64Window();
00236                 the_window->Show();
00237         }
00238 
00239         // Prepare key_info buffer
00240         get_key_info(&old_key_info);
00241 }
00242 
00243 
00244 /*
00245  *  Display destructor
00246  */
00247 
00248 C64Display::~C64Display()
00249 {
00250         if (using_screen) {
00251                 the_screen->Lock();
00252                 the_screen->Quit();
00253         } else {
00254                 the_window->Lock();
00255                 the_window->Quit();
00256         }
00257 }
00258 
00259 
00260 /*
00261  *  Prefs may have changed
00262  */
00263 
00264 void C64Display::NewPrefs(Prefs *prefs)
00265 {
00266         if (prefs->DisplayType == DISPTYPE_SCREEN) {
00267                 if (!using_screen) {
00268                         // Switch to full screen display
00269                         using_screen = true;
00270                         the_window->Lock();
00271                         the_window->Quit();
00272                         the_screen = new C64Screen(this);
00273                         the_screen->Show();
00274                         while (!the_screen->Connected)
00275                                 snooze(20000);
00276                 }
00277         } else {
00278                 if (using_screen) {
00279                         // Switch to window display
00280                         using_screen = false;
00281                         the_screen->Lock();
00282                         the_screen->Quit();
00283                         the_window = new C64Window();
00284                         the_window->Show();
00285                 }
00286         }
00287 }
00288 
00289 
00290 /*
00291  *  Redraw bitmap (let the window thread do it)
00292  */
00293 
00294 void C64Display::Update(void)
00295 {
00296         if (using_screen) {
00297 
00298                 // Update LEDs/speedometer
00299                 for (int i=0; i<4; i++)
00300                         the_screen->DrawLED(i, led_state[i]);
00301                 the_screen->DrawSpeedometer();
00302 
00303         } else {
00304 
00305                 // Update C64 display
00306                 BMessage msg(MSG_REDRAW);
00307                 msg.AddInt32("bitmap", draw_bitmap);
00308                 the_window->PostMessage(&msg);
00309                 draw_bitmap ^= 1;
00310 
00311                 // Update LEDs
00312                 for (int i=0; i<4; i++)
00313                         if (led_state[i] != old_led_state[i]) {
00314                                 the_window->LED[i]->SetState(led_state[i]);
00315                                 old_led_state[i] = led_state[i];
00316                         }
00317         }
00318 }
00319 
00320 
00321 /*
00322  *  Set value displayed by the speedometer
00323  */
00324 
00325 void C64Display::Speedometer(int speed)
00326 {
00327         if (using_screen) {
00328                 the_screen->Speed = speed;
00329                 sprintf(the_screen->SpeedoStr, "%3d%%", speed);
00330         } else
00331                 the_window->Speedometer->SetValue(speed);
00332 }
00333 
00334 
00335 /*
00336  *  Return pointer to bitmap data
00337  */
00338 
00339 uint8 *C64Display::BitmapBase(void)
00340 {
00341         if (using_screen)
00342                 return (uint8 *)the_screen->CardInfo()->frame_buffer;
00343         else
00344                 return (uint8 *)the_window->TheBitmap[draw_bitmap]->Bits();
00345 }
00346 
00347 
00348 /*
00349  *  Return number of bytes per row
00350  */
00351 
00352 int C64Display::BitmapXMod(void)
00353 {
00354         if (using_screen)
00355                 return the_screen->CardInfo()->bytes_per_row;
00356         else
00357                 return the_window->TheBitmap[draw_bitmap]->BytesPerRow();
00358 }
00359 
00360 
00361 /*
00362  *  Poll the keyboard
00363  */
00364 
00365 void C64Display::PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick)
00366 {
00367         key_info the_key_info;
00368         int be_code, be_byte, be_bit, c64_byte, c64_bit;
00369         bool shifted;
00370 
00371         // Window must be active, command key must be up
00372         if (using_screen) {
00373                 if (!the_screen->Connected)
00374                         return;
00375         } else
00376                 if (!the_window->IsActive())
00377                         return;
00378         if (!(modifiers() & B_COMMAND_KEY)) {
00379 
00380                 // Read the state of all keys
00381                 get_key_info(&the_key_info);
00382 
00383                 // Did anything change at all?
00384                 if (!memcmp(&old_key_info, &the_key_info, sizeof(key_info)))
00385                         return;
00386 
00387                 // Loop to convert BeOS keymap to C64 keymap
00388                 for (be_code=0; be_code<0x68; be_code++) {
00389                         be_byte = be_code >> 3;
00390                         be_bit = 1 << (~be_code & 7);
00391 
00392                         // Key state changed?
00393                         if ((the_key_info.key_states[be_byte] & be_bit)
00394                              != (old_key_info.key_states[be_byte] & be_bit)) {
00395 
00396                                 c64_byte = key_byte[be_code];
00397                                 c64_bit = key_bit[be_code];
00398                                 if (c64_byte != -1) {
00399                                         if (!(c64_byte & 0x20)) {
00400 
00401                                                 // Normal keys
00402                                                 shifted = c64_byte & 8;
00403                                                 c64_byte &= 7;
00404                                                 if (the_key_info.key_states[be_byte] & be_bit) {
00405 
00406                                                         // Key pressed
00407                                                         if (shifted) {
00408                                                                 key_matrix[6] &= 0xef;
00409                                                                 rev_matrix[4] &= 0xbf;
00410                                                         }
00411                                                         key_matrix[c64_byte] &= ~(1 << c64_bit);
00412                                                         rev_matrix[c64_bit] &= ~(1 << c64_byte);
00413                                                 } else {
00414 
00415                                                         // Key released
00416                                                         if (shifted) {
00417                                                                 key_matrix[6] |= 0x10;
00418                                                                 rev_matrix[4] |= 0x40;
00419                                                         }
00420                                                         key_matrix[c64_byte] |= (1 << c64_bit);
00421                                                         rev_matrix[c64_bit] |= (1 << c64_byte);
00422                                                 }
00423                                         } else {
00424 
00425                                                 // Joystick emulation
00426                                                 c64_byte &= 0x1f;
00427                                                 if (the_key_info.key_states[be_byte] & be_bit)
00428                                                         *joystick &= ~c64_byte;
00429                                                 else
00430                                                         *joystick |= c64_byte;
00431                                         }
00432                                 }
00433                         }
00434                 }
00435 
00436                 old_key_info = the_key_info;
00437         }
00438 }
00439 
00440 
00441 /*
00442  *  Check if NumLock is down (for switching the joystick keyboard emulation)
00443  */
00444 
00445 bool C64Display::NumLock(void)
00446 {
00447         return modifiers() & B_NUM_LOCK;
00448 }
00449 
00450 
00451 /*
00452  *  Allocate C64 colors
00453  */
00454 
00455 void C64Display::InitColors(uint8 *colors)
00456 {
00457         BScreen scr(using_screen ? (BWindow *)the_screen : the_window);
00458         for (int i=0; i<256; i++)
00459                 colors[i] = scr.IndexForColor(palette_red[i & 0x0f], palette_green[i & 0x0f], palette_blue[i & 0x0f]);
00460 }
00461 
00462 
00463 /*
00464  *  Pause display (GameKit only)
00465  */
00466 
00467 void C64Display::Pause(void)
00468 {
00469         if (using_screen)
00470                 the_screen->Hide();
00471 }
00472 
00473 
00474 /*
00475  *  Resume display (GameKit only)
00476  */
00477 
00478 void C64Display::Resume(void)
00479 {
00480         if (using_screen)
00481                 the_screen->Show();
00482 }
00483 
00484 
00485 /*
00486  *  Window constructor
00487  */
00488 
00489 C64Window::C64Window() : BWindow(WindowFrame, "Frodo", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
00490 {
00491         // Move window to right position
00492         Lock();
00493         MoveTo(80, 60);
00494 
00495         // Set up menus
00496         BMenuBar *bar = new BMenuBar(Bounds(), "");
00497         BMenu *menu = new BMenu("Frodo");
00498         menu->AddItem(new BMenuItem("About Frodo" B_UTF8_ELLIPSIS, new BMessage(B_ABOUT_REQUESTED)));
00499         menu->AddItem(new BSeparatorItem);
00500         menu->AddItem(new BMenuItem("Preferences" B_UTF8_ELLIPSIS, new BMessage(MSG_PREFS), 'P'));
00501         menu->AddItem(new BSeparatorItem);
00502         menu->AddItem(new BMenuItem("Reset C64", new BMessage(MSG_RESET)));
00503         menu->AddItem(new BMenuItem("Insert next disk", new BMessage(MSG_NEXTDISK), 'D'));
00504         menu->AddItem(new BMenuItem("SAM" B_UTF8_ELLIPSIS, new BMessage(MSG_SAM), 'M'));
00505         menu->AddItem(new BSeparatorItem);
00506         menu->AddItem(new BMenuItem("Load snapshot" B_UTF8_ELLIPSIS, new BMessage(MSG_OPEN_SNAPSHOT), 'O'));
00507         menu->AddItem(new BMenuItem("Save snapshot" B_UTF8_ELLIPSIS, new BMessage(MSG_SAVE_SNAPSHOT), 'S'));
00508         menu->AddItem(new BSeparatorItem);
00509         menu->AddItem(new BMenuItem("Quit Frodo", new BMessage(B_QUIT_REQUESTED), 'Q'));
00510         menu->SetTargetForItems(be_app);
00511         bar->AddItem(menu);
00512         AddChild(bar);
00513         SetKeyMenuBar(bar);
00514         int mbar_height = bar->Frame().bottom + 1;
00515 
00516         // Resize window to fit menu bar
00517         ResizeBy(0, mbar_height);
00518 
00519         // Allocate bitmaps
00520         TheBitmap[0] = new BBitmap(DisplayFrame, B_COLOR_8_BIT);
00521         TheBitmap[1] = new BBitmap(DisplayFrame, B_COLOR_8_BIT);
00522 
00523         // Create top view
00524         BRect b = Bounds();
00525         BView *top = new BView(BRect(0, mbar_height, b.right, b.bottom), "top", B_FOLLOW_NONE, 0);
00526         AddChild(top);
00527 
00528         // Create bitmap view
00529         main_view = new BitmapView(DisplayFrame, TheBitmap[0]);
00530         top->AddChild(main_view);
00531         main_view->MakeFocus();
00532 
00533         // Create speedometer
00534         Speedometer = new SpeedoView(BRect(0, DISPLAY_Y, DISPLAY_X/5-1, DISPLAY_Y+15));
00535         top->AddChild(Speedometer);
00536 
00537         // Create drive LEDs
00538         LED[0] = new LEDView(BRect(DISPLAY_X/5, DISPLAY_Y, DISPLAY_X*2/5-1, DISPLAY_Y+15), "Drive 8");
00539         top->AddChild(LED[0]);
00540         LED[1] = new LEDView(BRect(DISPLAY_X*2/5, DISPLAY_Y, DISPLAY_X*3/5-1, DISPLAY_Y+15), "Drive 9");
00541         top->AddChild(LED[1]);
00542         LED[2] = new LEDView(BRect(DISPLAY_X*3/5, DISPLAY_Y, DISPLAY_X*4/5-1, DISPLAY_Y+15), "Drive 10");
00543         top->AddChild(LED[2]);
00544         LED[3] = new LEDView(BRect(DISPLAY_X*4/5, DISPLAY_Y, DISPLAY_X-1, DISPLAY_Y+15), "Drive 11");
00545         top->AddChild(LED[3]);
00546 
00547         // Set pulse rate to 0.4 seconds for blinking drive LEDs
00548         SetPulseRate(400000);
00549         Unlock();
00550 }
00551 
00552 
00553 /*
00554  *  Closing the window quits Frodo
00555  */
00556 
00557 bool C64Window::QuitRequested(void)
00558 {
00559         be_app->PostMessage(B_QUIT_REQUESTED);
00560         return false;
00561 }
00562 
00563 
00564 /*
00565  *  Handles redraw messages
00566  */
00567 
00568 void C64Window::MessageReceived(BMessage *msg)
00569 {
00570         BMessage *msg2;
00571 
00572         switch (msg->what) {
00573                 case MSG_REDRAW:  // Redraw bitmap
00574                         MessageQueue()->Lock();
00575                         while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL)
00576                                 MessageQueue()->RemoveMessage(msg2);
00577                         MessageQueue()->Unlock();
00578                         main_view->ChangeBitmap(TheBitmap[msg->FindInt32("bitmap")]);
00579                         Lock();
00580                         main_view->Draw(DisplayFrame);
00581                         Unlock();
00582                         break;
00583 
00584                 default:
00585                         BWindow::MessageReceived(msg);
00586         }
00587 }
00588 
00589 
00590 /*
00591  *  Workspace activated/deactivated
00592  */
00593 
00594 void C64Screen::ScreenConnected(bool active)
00595 {
00596         if (active) {
00597                 FillRect(0, 0, 639, 479, 0);    // Clear screen
00598                 the_display->TheC64->Resume();
00599                 Connected = true;
00600         } else {
00601                 the_display->TheC64->Pause();
00602                 Connected = false;
00603         }
00604         BWindowScreen::ScreenConnected(active);
00605 }
00606 
00607 
00608 /*
00609  *  Simulate menu commands
00610  */
00611 
00612 void C64Screen::DispatchMessage(BMessage *msg, BHandler *handler)
00613 {
00614         switch (msg->what) {
00615                 case B_KEY_DOWN: {
00616                         uint32 mods = msg->FindInt32("modifiers");
00617                         if (mods & B_COMMAND_KEY) {
00618                                 uint32 key = msg->FindInt32("raw_char");
00619                                 switch (key) {
00620                                         case 'p':
00621                                                 be_app->PostMessage(MSG_PREFS);
00622                                                 break;
00623                                         case 'd':
00624                                                 be_app->PostMessage(MSG_NEXTDISK);
00625                                                 break;
00626                                         case 'm':
00627                                                 be_app->PostMessage(MSG_SAM);
00628                                                 break;
00629                                 }
00630                         }
00631                         BWindowScreen::DispatchMessage(msg, handler);
00632                         break;
00633                 }
00634 
00635                 default:
00636                         BWindowScreen::DispatchMessage(msg, handler);
00637         }
00638 }
00639 
00640 
00641 /*
00642  *  Draw drive LEDs
00643  */
00644 
00645 void C64Screen::DrawLED(int i, int state)
00646 {
00647         switch (state) {
00648                 case LED_ON:
00649                         FillRect(10+i*20, DISPLAY_Y-20, 20+i*20, DISPLAY_Y-12, 54);
00650                         break;
00651                 case LED_ERROR_ON:
00652                         FillRect(10+i*20, DISPLAY_Y-20, 20+i*20, DISPLAY_Y-12, 44);
00653                         break;
00654         }
00655 }
00656 
00657 
00658 /*
00659  *  Draw speedometer
00660  */
00661 
00662 static const int8 Digits[11][8] = {     // Digit images
00663         {0x3c, 0x66, 0x6e, 0x76, 0x66, 0x66, 0x3c, 0x00},
00664         {0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7e, 0x00},
00665         {0x3c, 0x66, 0x06, 0x0c, 0x30, 0x60, 0x7e, 0x00},
00666         {0x3c, 0x66, 0x06, 0x1c, 0x06, 0x66, 0x3c, 0x00},
00667         {0x06, 0x0e, 0x1e, 0x66, 0x7f, 0x06, 0x06, 0x00},
00668         {0x7e, 0x60, 0x7c, 0x06, 0x06, 0x66, 0x3c, 0x00},
00669         {0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00},
00670         {0x7e, 0x66, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x00},
00671         {0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00},
00672         {0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00},
00673         {0x62, 0x66, 0x0c, 0x18, 0x30, 0x66, 0x46, 0x00},
00674 };
00675 
00676 void C64Screen::DrawSpeedometer()
00677 {
00678         // Don't display speedometer if we're running at about 100%
00679         if (Speed >= 99 && Speed <= 101)
00680                 return;
00681 
00682         char *s = SpeedoStr;
00683         char c;
00684         long xmod = CardInfo()->bytes_per_row;
00685         uint8 *p = (uint8 *)CardInfo()->frame_buffer + DISPLAY_X - 8*8 + (DISPLAY_Y-20) * xmod;
00686         while (c = *s++) {
00687                 if (c == ' ')
00688                         continue;
00689                 if (c == '%')
00690                         c = 10;
00691                 else
00692                         c -= '0';
00693                 uint8 *q = p;
00694                 for (int y=0; y<8; y++) {
00695                         uint8 data = Digits[c][y];
00696                         for (int x=0; x<8; x++) {
00697                                 if (data & (1 << (7-x)))
00698                                         q[x] = 255;
00699                                 else
00700                                         q[x] = 0;
00701                         }
00702                         q += xmod;
00703                 }
00704                 p += 8;
00705         }
00706 }
00707 
00708 
00709 /*
00710  *  Fill rectangle
00711  */
00712 
00713 void C64Screen::FillRect(int x1, int y1, int x2, int y2, int color)
00714 {
00715         long xmod = CardInfo()->bytes_per_row;
00716         uint8 *p = (uint8 *)CardInfo()->frame_buffer + y1 * xmod + x1;
00717         int n = x2 - x1 + 1;
00718         for(int y=y1; y<=y2; y++) {
00719                 memset_nc(p, color, n);
00720                 p += xmod;
00721         }
00722 }
00723 
00724 
00725 /*
00726  *  Bitmap view constructor
00727  */
00728 
00729 BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
00730 {
00731         ChangeBitmap(bitmap);
00732 }
00733 
00734 
00735 /*
00736  *  Blit the bitmap
00737  */
00738 
00739 void BitmapView::Draw(BRect update)
00740 {
00741         if (the_bitmap != NULL)
00742                 DrawBitmapAsync(the_bitmap, update, update);
00743 }
00744 
00745 
00746 /*
00747  *  Receive special key-down events (main C64 keyboard handling is done in PollKeyboard)
00748  */
00749 
00750 void BitmapView::KeyDown(const char *bytes, int32 numBytes)
00751 {
00752         if (bytes[0] == B_FUNCTION_KEY || bytes[0] == '+' || bytes[0] == '-' || bytes[0] == '*' || bytes[0] == '/') {
00753                 BMessage *msg = Window()->CurrentMessage();
00754                 long key;
00755                 if (msg->FindInt32("key", &key) == B_NO_ERROR) {
00756                         switch (key) {
00757 
00758                                 case B_F11_KEY: // F11: NMI (Restore)
00759                                         be_app->PostMessage(MSG_NMI);
00760                                         break;
00761 
00762                                 case B_F12_KEY: // F12: Reset
00763                                         be_app->PostMessage(MSG_RESET);
00764                                         break;
00765 
00766                                 case 0x3a:              // '+' on keypad: Increase SkipFrames
00767                                         ThePrefs.SkipFrames++;
00768                                         break;
00769 
00770                                 case 0x25:              // '-' on keypad: Decrease SkipFrames
00771                                         if (ThePrefs.SkipFrames > 1)
00772                                                 ThePrefs.SkipFrames--;
00773                                         break;
00774 
00775                                 case 0x24:              // '*' on keypad: Toggle speed limiter
00776                                         ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed;
00777                                         break;
00778 
00779                                 case 0x23:              // '/' on keypad: Toggle processor-level 1541 emulation
00780                                         be_app->PostMessage(MSG_TOGGLE_1541);
00781                                         break;
00782                         }
00783                 }
00784         }
00785 }
00786 
00787 
00788 /*
00789  *  Change view bitmap
00790  */
00791 
00792 void BitmapView::ChangeBitmap(BBitmap *bitmap)
00793 {
00794         the_bitmap = bitmap;
00795 }
00796 
00797 
00798 /*
00799  *  Speedometer constructor
00800  */
00801 
00802 SpeedoView::SpeedoView(BRect frame) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED)
00803 {
00804         speedostr[0] = 0;
00805         bounds = Bounds();
00806         SetViewColor(fill_gray);
00807         SetFont(be_plain_font);
00808 }
00809 
00810 
00811 /*
00812  *  Draw speedometer
00813  */
00814 
00815 void SpeedoView::Draw(BRect update)
00816 {
00817         // Draw bevelled border
00818         SetHighColor(shine_gray);
00819         StrokeLine(BPoint(0, bounds.bottom), BPoint(0, 0));
00820         StrokeLine(BPoint(bounds.right, 0));
00821         SetHighColor(shadow_gray);
00822         StrokeLine(BPoint(bounds.right, bounds.bottom), BPoint(bounds.right, 1));
00823 
00824         // Draw text
00825         SetHighColor(0, 0, 0);
00826         DrawString(speedostr, BPoint(24, 12));
00827 }
00828 
00829 
00830 /*
00831  *  Update speedometer at regular intervals
00832  */
00833 
00834 void SpeedoView::Pulse(void)
00835 {
00836         Invalidate(BRect(1, 1, bounds.right-1, 15));
00837 }
00838 
00839 
00840 /*
00841  *  Set new speedometer value
00842  */
00843 
00844 void SpeedoView::SetValue(int speed)
00845 {
00846         sprintf(speedostr, "%d%%", speed);
00847 }
00848 
00849 
00850 /*
00851  *  LED view constructor
00852  */
00853 
00854 LEDView::LEDView(BRect frame, const char *label) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED)
00855 {
00856         current_state = 0;
00857         the_label = label;
00858         bounds = Bounds();
00859         SetViewColor(fill_gray);
00860         SetFont(be_plain_font);
00861 }
00862 
00863 
00864 /*
00865  *  Draw drive LED
00866  */
00867 
00868 void LEDView::Draw(BRect update)
00869 {
00870         // Draw bevelled border
00871         SetHighColor(shine_gray);
00872         StrokeLine(BPoint(0, bounds.bottom), BPoint(0, 0));
00873         StrokeLine(BPoint(bounds.right, 0));
00874         SetHighColor(shadow_gray);
00875         StrokeLine(BPoint(bounds.right, bounds.bottom), BPoint(bounds.right, 1));
00876 
00877         // Draw label
00878         SetHighColor(0, 0, 0);
00879         SetLowColor(fill_gray);
00880         DrawString(the_label, BPoint(8, 12));
00881 
00882         // Draw LED
00883         SetHighColor(shadow_gray);
00884         StrokeLine(BPoint(bounds.right-24, 12), BPoint(bounds.right-24, 4));
00885         StrokeLine(BPoint(bounds.right-8, 4));
00886         SetHighColor(shine_gray);
00887         StrokeLine(BPoint(bounds.right-23, 12), BPoint(bounds.right-8, 12));
00888         StrokeLine(BPoint(bounds.right-8, 5));
00889         DrawLED();
00890 }
00891 
00892 
00893 /*
00894  *  Redraw just the LED
00895  */
00896 
00897 void LEDView::DrawLED(void)
00898 {
00899         Window()->Lock();
00900         switch (current_state) {
00901                 case LED_OFF:
00902                 case LED_ERROR_OFF:
00903                         SetHighColor(32, 32, 32);
00904                         break;
00905                 case LED_ON:
00906                         SetHighColor(0, 240, 0);
00907                         break;
00908                 case LED_ERROR_ON:
00909                         SetHighColor(240, 0, 0);
00910                         break;
00911         }
00912         FillRect(BRect(bounds.right-23, 5, bounds.right-9, 11));
00913         Window()->Unlock();
00914 }
00915 
00916 
00917 /*
00918  *  Set LED state
00919  */
00920 
00921 void LEDView::SetState(int state)
00922 {
00923         if (state != current_state) {
00924                 current_state = state;
00925                 DrawLED();
00926         }
00927 }
00928 
00929 
00930 /*
00931  *  Toggle red error LED
00932  */
00933 
00934 void LEDView::Pulse(void)
00935 {
00936         switch (current_state) {
00937                 case LED_ERROR_ON:
00938                         current_state = LED_ERROR_OFF;
00939                         DrawLED();
00940                         break;
00941                 case LED_ERROR_OFF:
00942                         current_state = LED_ERROR_ON;
00943                         DrawLED();
00944                         break;
00945         }
00946 }
00947 
00948 
00949 /*
00950  *  Show a requester
00951  */
00952 
00953 long ShowRequester(char *str, char *button1, char *button2)
00954 {
00955         BAlert *the_alert;
00956         
00957         the_alert = new BAlert("", str, button1, button2, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
00958         return the_alert->Go();
00959 }

Generated on Tue Feb 8 04:07:47 2005 for E32frodo by doxygen 1.3.3