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

Display_Acorn.i

Go to the documentation of this file.
00001 /*
00002  * Display_Acorn.i
00003  *
00004  * Handles redraws and suchlike as well as the keyboard
00005  * Frodo (C) 1994-1997 by Christian Bauer
00006  * Acorn port by Andreas Dehmel, 1997
00007  *
00008  */
00009 
00010 
00011 #include "C64.h"
00012 #include "ROlib.h"
00013 #include "AcornGUI.h"
00014 #include "SAM.h"
00015 #include "VIC.h"
00016 
00017 
00018 
00019 // (from Display_x.i)
00020 /*
00021   C64 keyboard matrix:
00022 
00023     Bit 7   6   5   4   3   2   1   0
00024   0    CUD  F5  F3  F1  F7 CLR RET DEL
00025   1    SHL  E   S   Z   4   A   W   3
00026   2     X   T   F   C   6   D   R   5
00027   3     V   U   H   B   8   G   Y   7
00028   4     N   O   K   M   0   J   I   9
00029   5     ,   @   :   .   -   L   P   +
00030   6     /   ^   =  SHR HOM  ;   *   
00031   7    R/S  Q   C= SPC  2  CTL  <-  1
00032 */
00033 
00034 
00035 #define IntKey_MinCode   3      // Scan from ShiftLeft (leave out Shift, Ctrl, Alt)
00036 #define IntKey_MaxCode   124
00037 #define IntKey_Copy     105
00038 
00039 // Maps internal keyboard numbers (Acorn) to C64 keyboard-matrix.
00040 // Format: top nibble - row#, bottom nibble - column (bit#).
00041 // Entry == 0xff <==> don't map
00042 char KeysAcornToCBM[] = {
00043   0x17, 0x72, 0x75, 0x17,       // 0  -  3: SHL, CTRL, ALT(C=), SHL
00044   0x72, 0x75, 0x64, 0x72,       // 4  -  7: CTRL, ALT, SHR, CTRL
00045   0x75, 0xff, 0xff, 0xff,       // 8  - 11: ALT, MouseSlct, MouseMen, MouseAdj
00046   0xff, 0xff, 0xff, 0xff,       // 12 - 15: dummies
00047   0x76, 0x10, 0x13, 0x20,       // 16 - 19: q, 3,4,5
00048   0x03, 0x33, 0xff, 0x53,       // 20 - 23: F4(F7), 8, F7, -
00049   0x23, 0x02, 0xff, 0xff,       // 24 - 27: 6, crsrL, num6, num7
00050   0xff, 0xff, 0xff, 0xff,       // 28 - 31: F11, F12, F10, ScrLock
00051   0xff, 0x11, 0x16, 0x26,       // 32 - 35: Print, w, e, t
00052   0x30, 0x41, 0x40, 0x43,       // 36 - 39: 7, i, 9, 0
00053   0x53, 0x07, 0xff, 0xff,       // 40 - 43: -, crsrD, num8, num9
00054   0x77, 0x71, 0x60, 0x00,       // 44 - 47: break, `, , DEL
00055   0x70, 0x73, 0x22, 0x21,       // 48 - 51: 1, 2, d, r
00056   0x23, 0x36, 0x46, 0x51,       // 52 - 55: 6, u, o, p
00057   0x56, 0x07, 0x50, 0x53,       // 56 - 59: [(@), crsrU, num+(+), num-(-)
00058   0xff, 0x00, 0x63, 0xff,       // 60 - 63: numENTER, insert, home, pgUp
00059   0x17, 0x12, 0x27, 0x25,       // 64 - 67: capsLCK, a, x, f
00060   0x31, 0x42, 0x45, 0x73,       // 68 - 71: y, j, k, 2
00061   0x55, 0x01, 0xff, 0xff,       // 72 - 75: ;(:), RET, num/, dummy
00062   0xff, 0xff, 0xff, 0x62,       // 76 - 79: num., numLCK, pgDown, '(;)
00063   0xff, 0x15, 0x24, 0x32,       // 80 - 83: dummy, s, c, g
00064   0x35, 0x47, 0x52, 0x55,       // 84 - 87: h, n, l, ;(:)
00065   0x61, 0x00, 0xff, 0xff,       // 88 - 91: ](*), Delete, num#, num*
00066   0xff, 0x65, 0xff, 0xff,       // 92 - 95: dummy, =, dummies
00067   0x72, 0x14, 0x74, 0x37,       // 96 - 99: TAB(CTRL), z, SPACE, v
00068   0x34, 0x44, 0x57, 0x54,       // 100-103: b, m, ',', .
00069   0x67, 0xff, 0xff, 0xff,       // 104-107: /, Copy, num0, num1
00070   0xff, 0xff, 0xff, 0xff,       // 108-111: num3, dummies
00071   0x77, 0x04, 0x05, 0x06,       // 112-115: ESC, F1(F1), F2(F3), F3(F5)
00072   0xff, 0xff, 0xff, 0xff,       // 116-119: F5, F6, F8, F9
00073   0x66, 0x02, 0xff, 0xff,       // 120-123: \(^), crsrR, num4, num5
00074   0xff, 0xff, 0xff, 0xff        // 124-127: num2, dummies
00075 };
00076 
00077 
00078 // Special keycodes that have to be processed seperately:
00079 #define IntKey_CrsrL    25
00080 #define IntKey_CrsrR    121
00081 #define IntKey_CrsrU    57
00082 #define IntKey_CrsrD    41
00083 #define IntKey_Insert   61
00084 #define IntKey_NumLock  77
00085 #define IntKey_F5       116
00086 #define IntKey_F6       117
00087 #define IntKey_F7       22
00088 #define IntKey_F8       118
00089 #define IntKey_PageUp   63
00090 #define IntKey_PageDown 78
00091 #define IntKey_NumSlash 74
00092 #define IntKey_NumStar  91
00093 #define IntKey_NumCross 90
00094 
00095 #define KeyJoy1_Up      108     // num3
00096 #define KeyJoy1_Down    76      // num.
00097 #define KeyJoy1_Left    107     // num1
00098 #define KeyJoy1_Right   124     // num2
00099 #define KeyJoy1_Fire    60      // numReturn
00100 #define KeyJoy2_Up      67      // "f"
00101 #define KeyJoy2_Down    82      // "c"
00102 #define KeyJoy2_Left    97      // "z"
00103 #define KeyJoy2_Right   66      // "x"
00104 #define KeyJoy2_Fire    83      // "g"
00105 
00106 
00107 
00108 
00109 C64Display::C64Display(C64 *the_c64) : TheC64(the_c64)
00110 {
00111   int i;
00112 
00113   bitmap = new uint8[DISPLAY_X * DISPLAY_Y];
00114   screen = new ROScreen();
00115   ModeChange();
00116   for (i=0; i<8; i++) {lastkeys[i] = 0;}
00117   // First joystick: mapped to port 2 if numLOCK is on, else port 2
00118   JoystickKeys[0].up   = KeyJoy1_Up;   JoystickKeys[0].down  = KeyJoy1_Down;
00119   JoystickKeys[0].left = KeyJoy1_Left; JoystickKeys[0].right = KeyJoy1_Right;
00120   JoystickKeys[0].fire = KeyJoy1_Fire;
00121   // Second joystick: only active if numLOCK is off! Mapped to port 2 then.
00122   JoystickKeys[1].up   = KeyJoy2_Up;   JoystickKeys[1].down  = KeyJoy2_Down;
00123   JoystickKeys[1].left = KeyJoy2_Left; JoystickKeys[1].right = KeyJoy2_Right;
00124   JoystickKeys[1].fire = KeyJoy2_Fire;
00125 }
00126 
00127 
00128 C64Display::~C64Display(void)
00129 {
00130   delete bitmap; delete screen;
00131 }
00132 
00133 
00134 void C64Display::ModeChange(void)
00135 {
00136   register int i;
00137 
00138   screen->ReadMode();
00139   // find best matching colours in current mode.
00140   switch (screen->ldbpp)
00141   {
00142     case 0:
00143     case 1:
00144     case 2:
00145     case 3: for (i=0; i<16; i++)        // for 1,2,4 and 8bpp
00146             {
00147               mode_cols[i] = ModeColourNumber((palette_blue[i] << 24) + (palette_green[i] << 16) + (palette_red[i] << 8));
00148             }
00149             break;
00150     case 4: for (i=0; i<16; i++)        // for 16bpp
00151             {
00152               int r,g,b;
00153 
00154               r = (palette_red[i]   + 4) & 0x1f8; if (r > 0xff) {r = 0xf8;}
00155               g = (palette_green[i] + 4) & 0x1f8; if (g > 0xff) {g = 0xf8;}
00156               b = (palette_blue[i]  + 4) & 0x1f8; if (b > 0xff) {b = 0xf8;}
00157               mode_cols[i] = (r >> 3) | (g << 2) | (b << 7);
00158             }
00159             break;
00160     case 5: for (i=0; i<16; i++)        // for 32bpp
00161             {
00162               mode_cols[i] = palette_red[i] | (palette_green[i] << 8) | (palette_blue[i] << 16);
00163             }
00164             break;
00165   }
00166 }
00167 
00168 
00169 uint8 *C64Display::BitmapBase(void)
00170 {
00171   return bitmap;
00172 }
00173 
00174 
00175 void C64Display::InitColors(uint8 *colors)
00176 {
00177   register int i;
00178 
00179   // write index mapping C64colours -> ROcolours
00180   if (screen->ldbpp <= 3) // at most 8bpp ==> use actual colour
00181   {
00182     for (i=0; i<256; i++) {colors[i] = mode_cols[i&15];}
00183   }
00184   else // else use index (takes time but can't be changed...
00185   {
00186     for (i=0; i<256; i++) {colors[i] = i&15;}
00187   }
00188 }
00189 
00190 
00191 int C64Display::BitmapXMod(void)
00192 {
00193   return DISPLAY_X;
00194 }
00195 
00196 
00197 // This routine reads the raw keyboard data from the host machine. Not entirely
00198 // conformant with Acorn's rules but the only way to detect multiple simultaneous
00199 // keypresses.
00200 void C64Display::PollKeyboard(uint8 *key_matrix, uint8 *rev_matrix, uint8 *joystick, uint8 *joystick2)
00201 {
00202   register int scan_from=IntKey_MinCode, code, row, col;
00203   int status;
00204   uint8 kjoy, kjoy2;
00205   uint32 newkeys[8];
00206   UBYTE kjoy, kjoy2;
00207 
00208   // Clear keyboard
00209   for (code=0; code<8; code++) {key_matrix[code] = 0xff; rev_matrix[code] = 0xff; newkeys[code] = 0;}
00210   kjoy = kjoy2 = 0xff;
00211   status = ReadKeyboardStatus();
00212   if ((status & 16) == 0) {key_matrix[1] &= 0x7f; rev_matrix[7] &= 0xfd;} // Caps lock
00213 
00214   while (scan_from <= IntKey_MaxCode)
00215   {
00216     if ((code = ScanKeys(scan_from)) != 0xff)
00217     {
00218       newkeys[code >> 5] |= (1 << (code & 0x1f));       // update keys pressed
00219       row = KeysAcornToCBM[code];
00220       if ((status & 4) != 0)    // numLOCK off? ==> check for 2nd keyboard joystick too
00221       {
00222         if (code == JoystickKeys[1].up) {kjoy2 &= 0xfe; row = 0xff;}
00223         else if (code == JoystickKeys[1].down)  {kjoy2 &= 0xfd; row = 0xff;}
00224         else if (code == JoystickKeys[1].left)  {kjoy2 &= 0xfb; row = 0xff;}
00225         else if (code == JoystickKeys[1].right) {kjoy2 &= 0xf7; row = 0xff;}
00226         else if (code == JoystickKeys[1].fire)  {kjoy2 &= 0xef; row = 0xff;}
00227       }
00228       // check 1st keyboard joystick
00229       if (code == JoystickKeys[0].up) {kjoy &= 0xfe; row = 0xff;}
00230       else if (code == JoystickKeys[0].down)  {kjoy &= 0xfd; row = 0xff;}
00231       else if (code == JoystickKeys[0].left)  {kjoy &= 0xfb; row = 0xff;}
00232       else if (code == JoystickKeys[0].right) {kjoy &= 0xf7; row = 0xff;}
00233       else if (code == JoystickKeys[0].fire)  {kjoy &= 0xef; row = 0xff;}
00234 
00235       // If key not mapped to joystick: try mapping to keyboard
00236       if (row != 0xff)
00237       {
00238         col = row & 7; row >>= 4;
00239         key_matrix[row] &= ~(1<<col); rev_matrix[col] &= ~(1<<row);
00240       }
00241 
00242       // None of the keys listed below should be used for
00243       // joystick definitions since they're always used here.
00244       switch(code)
00245       {
00246         // For either of these: additionally set SHIFT key.
00247         case IntKey_CrsrL:  // already mapped to CrsrL
00248         case IntKey_CrsrU:  // already mapped to CrsrD
00249         case IntKey_Insert: // already mapped to DEL
00250              key_matrix[6] &= (0xff - (1<<4)); rev_matrix[4] &= (0xff - (1<<6));
00251              break;
00252         case IntKey_F6:
00253              if ((status & 2) == 0)     // call SAM only in multitasking mode!
00254              {
00255                TheC64->Pause(); SAM(TheC64); TheC64->Resume();
00256              }
00257              break;
00258         case IntKey_F7: TheC64->NMI(); break;
00259         case IntKey_F8: TheC64->Reset(); break;
00260         default: break;
00261       }
00262 
00263       // These shouldn't auto-repeat, therefore I check them seperately.
00264       if ((lastkeys[code >> 5] & (1 << (code & 0x1f))) == 0)
00265       {
00266         // Icons should be updated, not force-redrawed (--> single tasking)
00267         switch (code)
00268         {
00269           // decrease framerate
00270           case IntKey_PageUp:
00271                TheC64->TheWIMP->PrefsWindow->
00272                  WriteIconNumberU(Icon_Prefs_SkipFText,++ThePrefs.SkipFrames);
00273                break;
00274           // increase framerate
00275           case IntKey_PageDown: if (ThePrefs.SkipFrames > 0)
00276                {
00277                  TheC64->TheWIMP->PrefsWindow->
00278                    WriteIconNumberU(Icon_Prefs_SkipFText,--ThePrefs.SkipFrames);
00279                }
00280                break;
00281           // toggle floppy emulation status
00282           case IntKey_NumSlash:
00283                {
00284                  register int eor, i;
00285                  Prefs *prefs = new Prefs(ThePrefs);
00286 
00287                  // If Emulation active then ungrey icons now, else grey them
00288                  prefs->Emul1541Proc = !prefs->Emul1541Proc;
00289                  TheC64->TheWIMP->SetLEDIcons(prefs->Emul1541Proc);
00290                  TheC64->NewPrefs(prefs);
00291                  ThePrefs = *prefs;
00292                  // Show change in prefs window too
00293                  TheC64->TheWIMP->PrefsWindow->
00294                    SetIconState(Icon_Prefs_Emul1541,(prefs->Emul1541Proc)?IFlg_Slct:0,IFlg_Slct);
00295                  delete prefs;
00296                }
00297                break;
00298           // toggle speed limiter
00299           case IntKey_NumStar:
00300                ThePrefs.LimitSpeed = !ThePrefs.LimitSpeed;
00301                TheC64->TheWIMP->SetSpeedLimiter(ThePrefs.LimitSpeed);
00302                break;
00303           // toggle sound emulation
00304           case IntKey_F5:
00305                {
00306                  Window *pw = TheC64->TheWIMP->PrefsWindow;
00307                  int i, j;
00308                  Prefs *prefs = new Prefs(ThePrefs);
00309 
00310                  if (prefs->SIDType == SIDTYPE_NONE) {prefs->SIDType = SIDTYPE_DIGITAL; i = 1;}
00311                  else {prefs->SIDType = SIDTYPE_NONE; i = 0;}
00312                  for (j=0; j<3; j++)
00313                  {
00314                    pw->SetIconState(SIDtoIcon[j], (j==i) ? IFlg_Slct : 0, IFlg_Slct);
00315                  }
00316                  TheC64->TheWIMP->SoundWindow->
00317                    SetIconState(Icon_Sound_Notes, (i==0) ? IFlg_Grey : 0, IFlg_Grey);
00318                  TheC64->NewPrefs(prefs);
00319                  ThePrefs = *prefs;
00320                  delete prefs;
00321                }
00322                break;
00323           case IntKey_Copy: TheC64->Pause();
00324                TheC64->TheWIMP->EmuPane->WriteIconTextU(Icon_Pane_Pause,PANE_TEXT_RESUME); break;
00325           default: break;
00326         }
00327       }
00328     }
00329     scan_from = code+1;
00330   }
00331   for (code=0; code<8; code++) {lastkeys[code] = newkeys[code];}
00332   *joystick = kjoy; *joystick2 = kjoy2;
00333 }
00334 
00335 
00336 bool C64Display::NumLock(void)
00337 {
00338   return(((ReadKeyboardStatus() & 4) == 0) ? true : false);
00339 }
00340 
00341 
00342 /*
00343  *  Prefs may have changed
00344  */
00345 
00346 void C64Display::NewPrefs(Prefs *prefs)
00347 {
00348 }
00349 
00350 
00351 void C64Display::Update(void)
00352 {
00353   int i, state;
00354   int *ic;
00355 
00356   // Do a redraw of the emulator window
00357   TheC64->TheWIMP->UpdateEmuWindow();
00358 
00359   // Update the LEDs if necessary
00360   for (i=0; i<4; i++)
00361   {
00362     if ((state = led_state[i]) != old_led_state[i])
00363     {
00364       ic = (int*)TheC64->TheWIMP->EmuPane->GetIcon(LEDtoIcon[i]);
00365       switch(state)
00366       {
00367         case LED_OFF:
00368         case LED_ERROR_OFF:
00369              sprintf((char*)ic[5],"led_off"); break;
00370         case LED_ON:
00371              sprintf((char*)ic[5],"led_on"); break;
00372         case LED_ERROR_ON:
00373              sprintf((char*)ic[5],"led_error"); break;
00374       }
00375       TheC64->TheWIMP->EmuPane->UpdateIcon(LEDtoIcon[i]);       // update, not force-redraw!
00376       old_led_state[i] = state;
00377     }
00378   }
00379 }
00380 
00381 
00382 unsigned int *C64Display::GetColourTable(void)
00383 {
00384   return (mode_cols);
00385 }
00386 
00387 
00388 // Check whether unpause-key (copy) is pressed
00389 bool C64Display::CheckForUnpause(bool CheckLastState)
00390 {
00391   int scan_from = IntKey_MinCode, code;
00392   uint32 newkeys[8];
00393   uint32 lastpause;
00394 
00395   for (code=0; code<8; code++) {newkeys[code] = 0;}
00396 
00397   while (scan_from <= IntKey_MaxCode)
00398   {
00399     if ((code = ScanKeys(scan_from)) != 0xff)
00400     {
00401       newkeys[code >> 5] |= (1 << (code & 0x1f));
00402     }
00403     scan_from = code+1;
00404   }
00405   lastpause = lastkeys[IntKey_Copy >> 5] & (1 << (IntKey_Copy & 0x1f));
00406   for (code=0; code<8; code++) {lastkeys[code] = newkeys[code];}
00407   // unpause-key pressed?
00408   if ((newkeys[IntKey_Copy >> 5] & (1 << (IntKey_Copy & 0x1f))) != 0)
00409   {
00410     if ((lastpause == 0) || !CheckLastState)
00411     {
00412       TheC64->Resume();
00413       TheC64->TheWIMP->EmuPane->WriteIconTextU(Icon_Pane_Pause,PANE_TEXT_PAUSE);
00414       return(true);
00415     }
00416   }
00417   return(false);
00418 }
00419 
00420 
00421 // Requester dialogue box
00422 long ShowRequester(char *str, char *button1, char *button2)
00423 {
00424   _kernel_oserror myerr;
00425 
00426   myerr.errnum = 0x0; strcpy(myerr.errmess,str);
00427   Wimp_ReportError(&myerr,1,TASKNAME); // always provide an OK box
00428   return(1);
00429 }

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