DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/snd_pc98/generic/keydisp.c
00001 #include    "np2glue.h"
00002 //#include      "compiler.h"
00003 
00004 #if defined(SUPPORT_KEYDISP)
00005 
00006 #include        "pccore.h"
00007 #include        "iocore.h"
00008 #include        "sound.h"
00009 #include        "fmboard.h"
00010 #include        "keydisp.h"
00011 
00012 typedef struct {
00013         UINT16  posx;
00014         UINT16  pals;
00015 const UINT8     *data;
00016 } KDKEYPOS;
00017 
00018 typedef struct {
00019         UINT8   k[KEYDISP_NOTEMAX];
00020         UINT8   r[KEYDISP_NOTEMAX];
00021         UINT    remain;
00022         UINT8   flag;
00023         UINT8   padding[3];
00024 } KDCHANNEL;
00025 
00026 typedef struct {
00027         UINT8   ch;
00028         UINT8   key;
00029 } KDDELAYE;
00030 
00031 typedef struct {
00032         UINT    pos;
00033         UINT    rem;
00034         UINT8   warm;
00035         UINT8   warmbase;
00036 } KDDELAY;
00037 
00038 typedef struct {
00039         UINT16  fnum[4];
00040         UINT8   lastnote[4];
00041         UINT8   flag;
00042         UINT8   extflag;
00043 } KDFMCTRL;
00044 
00045 typedef struct {
00046         UINT16  fto[4];
00047         UINT8   lastnote[4];
00048         UINT8   flag;
00049         UINT8   mix;
00050         UINT8   padding[2];
00051 } KDPSGCTRL;
00052 
00053 typedef struct {
00054         UINT8           mode;
00055         UINT8           dispflag;
00056         UINT8           framepast;
00057         UINT8           keymax;
00058         UINT8           fmmax;
00059         UINT8           psgmax;
00060         UINT8           fmpos[KEYDISP_FMCHMAX];
00061         UINT8           psgpos[KEYDISP_PSGMAX];
00062         const UINT8     *pfmreg[KEYDISP_FMCHMAX];
00063         KDDELAY         delay;
00064         KDCHANNEL       ch[KEYDISP_CHMAX];
00065         KDFMCTRL        fmctl[KEYDISP_FMCHMAX];
00066         KDPSGCTRL       psgctl[KEYDISP_PSGMAX];
00067         UINT8           pal8[KEYDISP_PALS];
00068         UINT16          pal16[KEYDISP_LEVEL*2];
00069         RGB32           pal32[KEYDISP_LEVEL*2];
00070         KDKEYPOS        keypos[128];
00071         KDDELAYE        delaye[KEYDISP_DELAYEVENTS];
00072 } KEYDISP;
00073 
00074 static  KEYDISP         keydisp;
00075 
00076 #include        "keydisp.res"
00077 
00078 
00079 // ---- event
00080 
00081 static void keyon(UINT ch, UINT8 note) {
00082 
00083         UINT            i;
00084         KDCHANNEL       *kdch;
00085 
00086         note &= 0x7f;
00087         kdch = keydisp.ch + ch;
00088         for (i=0; i<kdch->remain; i++) {
00089                 if (kdch->k[i] == note) {                               // ヒットした
00090                         for (; i<(kdch->remain-1); i++) {
00091                                 kdch->k[i] = kdch->k[i+1];
00092                                 kdch->r[i] = kdch->r[i+1];
00093                         }
00094                         kdch->k[i] = note;
00095                         kdch->r[i] = 0x80 | (KEYDISP_LEVEL - 1);
00096                         kdch->flag |= 1;
00097                         return;
00098                 }
00099         }
00100         if (i < KEYDISP_NOTEMAX) {
00101                 kdch->k[i] = note;
00102                 kdch->r[i] = 0x80 | (KEYDISP_LEVEL - 1);
00103                 kdch->flag |= 1;
00104                 kdch->remain++;
00105         }
00106 }
00107 
00108 static void keyoff(UINT ch, UINT8 note) {
00109 
00110         UINT            i;
00111         KDCHANNEL       *kdch;
00112 
00113         note &= 0x7f;
00114         kdch = keydisp.ch + ch;
00115         for (i=0; i<kdch->remain; i++) {
00116                 if (kdch->k[i] == note) {                               // ヒットした
00117                         kdch->r[i] = 0x80 | (KEYDISP_LEVEL - 2);
00118                         kdch->flag |= 1;
00119                         break;
00120                 }
00121         }
00122 }
00123 
00124 static void chkeyoff(UINT ch) {
00125 
00126         UINT            i;
00127         KDCHANNEL       *kdch;
00128 
00129         kdch = keydisp.ch + ch;
00130         for (i=0; i<kdch->remain; i++) {
00131                 if ((kdch->r[i] & (~0x80)) >= (KEYDISP_LEVEL - 1)) {
00132                         kdch->r[i] = 0x80 | (KEYDISP_LEVEL - 2);
00133                         kdch->flag |= 1;
00134                 }
00135         }
00136 }
00137 
00138 static void keyalloff(void) {
00139 
00140         UINT8   i;
00141 
00142         for (i=0; i<KEYDISP_CHMAX; i++) {
00143                 chkeyoff(i);
00144         }
00145 }
00146 
00147 static void keyallreload(void) {
00148 
00149         UINT    i;
00150 
00151         for (i=0; i<KEYDISP_CHMAX; i++) {
00152                 keydisp.ch[i].flag = 2;
00153         }
00154 }
00155 
00156 static void keyallclear(void) {
00157 
00158         ZeroMemory(keydisp.ch, sizeof(keydisp.ch));
00159         keyallreload();
00160 }
00161 
00162 
00163 // ---- delay event
00164 
00165 static void delayreset(void) {
00166 
00167         keydisp.delay.warm = keydisp.delay.warmbase;
00168         keydisp.delay.pos = 0;
00169         keydisp.delay.rem = 0;
00170         ZeroMemory(keydisp.delaye, sizeof(keydisp.delaye));
00171         keyalloff();
00172 }
00173 
00174 static void delayexecevent(UINT8 framepast) {
00175 
00176         KDDELAYE        *ebase;
00177         UINT            pos;
00178         UINT            rem;
00179         KDDELAYE        *ev;
00180 
00181         ebase = keydisp.delaye;
00182         pos = keydisp.delay.pos;
00183         rem = keydisp.delay.rem;
00184         while((keydisp.delay.warm) && (framepast)) {
00185                 keydisp.delay.warm--;
00186                 framepast--;
00187                 if (rem >= KEYDISP_DELAYEVENTS) {
00188                         ev = ebase + pos;
00189                         rem--;
00190                         if (ev->ch == 0xff) {
00191                                 keydisp.delay.warm++;
00192                         }
00193                         else if (ev->key & 0x80) {
00194                                 keyon(ev->ch, ev->key);
00195                                 rem--;
00196                         }
00197                         else {
00198                                 keyoff(ev->ch, ev->key);
00199                         }
00200                         pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1);
00201                 }
00202                 ebase[(pos + rem) & (KEYDISP_DELAYEVENTS - 1)].ch = 0xff;
00203                 rem++;
00204         }
00205         while(framepast) {
00206                 framepast--;
00207                 while(rem) {
00208                         rem--;
00209                         ev = ebase + pos;
00210                         if (ev->ch == 0xff) {
00211                                 pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1);
00212                                 break;
00213                         }
00214                         if (ev->key & 0x80) {
00215                                 keyon(ev->ch, ev->key);
00216                         }
00217                         else {
00218                                 keyoff(ev->ch, ev->key);
00219                         }
00220                         pos = (pos + 1) & (KEYDISP_DELAYEVENTS - 1);
00221                 }
00222                 ebase[(pos + rem) & (KEYDISP_DELAYEVENTS - 1)].ch = 0xff;
00223                 rem++;
00224         }
00225         keydisp.delay.pos = pos;
00226         keydisp.delay.rem = rem;
00227 }
00228 
00229 static void delaysetevent(UINT8 ch, UINT8 key) {
00230 
00231         KDDELAYE        *e;
00232 
00233         e = keydisp.delaye;
00234         if (keydisp.delay.rem < KEYDISP_DELAYEVENTS) {
00235                 e += (keydisp.delay.pos + keydisp.delay.rem) &
00236                                                                                                         (KEYDISP_DELAYEVENTS - 1);
00237                 keydisp.delay.rem++;
00238                 e->ch = ch;
00239                 e->key = key;
00240         }
00241         else {
00242                 e += keydisp.delay.pos;
00243                 keydisp.delay.pos += (keydisp.delay.pos + 1) &
00244                                                                                                         (KEYDISP_DELAYEVENTS - 1);
00245                 if (e->ch == 0xff) {
00246                         keydisp.delay.warm++;
00247                 }
00248                 else if (e->key & 0x80) {
00249                         keyon(e->ch, e->key);
00250                 }
00251                 else {
00252                         keyoff(e->ch, e->key);
00253                 }
00254                 e->ch = ch;
00255                 e->key = key;
00256         }
00257 }
00258 
00259 
00260 // ---- FM
00261 
00262 static UINT8 getfmnote(UINT16 fnum) {
00263 
00264         UINT8   ret;
00265         int             i;
00266 
00267         ret = (fnum >> 11) & 7;
00268         ret *= 12;
00269         ret += 24;
00270         fnum &= 0x7ff;
00271 
00272         while(fnum < FNUM_MIN) {
00273                 if (!ret) {
00274                         return(0);
00275                 }
00276                 ret -= 12;
00277                 fnum <<= 1;
00278         }
00279         while(fnum > FNUM_MAX) {
00280                 fnum >>= 1;
00281                 ret += 12;
00282         }
00283         for (i=0; fnum >= fnumtbl[i]; i++) {
00284                 ret++;
00285         }
00286         if (ret > 127) {
00287                 return(127);
00288         }
00289         return(ret);
00290 }
00291 
00292 static void fmkeyoff(UINT8 ch, KDFMCTRL *k) {
00293 
00294         delaysetevent(keydisp.fmpos[ch], k->lastnote[0]);
00295 }
00296 
00297 static void fmkeyon(UINT8 ch, KDFMCTRL *k) {
00298 
00299         const UINT8 *pReg;
00300 
00301         fmkeyoff(ch, k);
00302         pReg = keydisp.pfmreg[ch];
00303         if (pReg)
00304         {
00305                 pReg = pReg + 0xa0;
00306                 k->fnum[0] = ((pReg[4] & 0x3f) << 8) + pReg[0];
00307                 k->lastnote[0] = getfmnote(k->fnum[0]);
00308                 delaysetevent(keydisp.fmpos[ch], (UINT8)(k->lastnote[0] | 0x80));
00309         }
00310 }
00311 
00312 static void fmkeyreset(void) {
00313 
00314         ZeroMemory(keydisp.fmctl, sizeof(keydisp.fmctl));
00315 }
00316 
00317 void keydisp_fmkeyon(UINT8 ch, UINT8 value) {
00318 
00319         KDFMCTRL        *k;
00320 
00321         if (keydisp.mode != KEYDISP_MODEFM) {
00322                 return;
00323         }
00324         if (ch < keydisp.fmmax) {
00325                 k = keydisp.fmctl + ch;
00326                 value &= 0xf0;
00327                 if (k->flag != value) {
00328                         if (value) {
00329                                 fmkeyon(ch, k);
00330                         }
00331                         else {
00332                                 fmkeyoff(ch, k);
00333                         }
00334                         k->flag = value;
00335                 }
00336         }
00337 }
00338 
00339 static void fmkeysync(void) {
00340 
00341         UINT8           ch;
00342         KDFMCTRL        *k;
00343         const UINT8 *pReg;
00344         UINT16          fnum;
00345 
00346         for (ch=0, k=keydisp.fmctl; ch<keydisp.fmmax; ch++, k++) {
00347                 if (k->flag) {
00348                         pReg = keydisp.pfmreg[ch];
00349                         if (pReg)
00350                         {
00351                                 pReg = pReg + 0xa0;
00352                                 fnum = ((pReg[4] & 0x3f) << 8) + pReg[0];
00353                                 if (k->fnum[0] != fnum) {
00354                                         UINT8 n;
00355                                         k->fnum[0] = fnum;
00356                                         n = getfmnote(fnum);
00357                                         if (k->lastnote[0] != n) {
00358                                                 fmkeyoff(ch, k);
00359                                         }
00360                                         k->lastnote[0] = n;
00361                                         delaysetevent(keydisp.fmpos[ch],
00362                                                                                         (UINT8)(k->lastnote[0] | 0x80));
00363                                 }
00364                         }
00365                 }
00366         }
00367 }
00368 
00369 
00370 // ---- PSG
00371 
00372 static const void *psgtbl[3] = {&psg1, &psg2, &psg3};
00373 
00374 static UINT8 getpsgnote(UINT16 tone) {
00375 
00376         UINT8   ret;
00377         int             i;
00378 
00379         ret = 60;
00380         tone &= 0xfff;
00381 
00382         while(tone < FTO_MIN) {
00383                 tone <<= 1;
00384                 ret += 12;
00385                 if (ret >= 128) {
00386                         return(127);
00387                 }
00388         }
00389         while(tone > FTO_MAX) {
00390                 if (!ret) {
00391                         return(0);
00392                 }
00393                 tone >>= 1;
00394                 ret -= 12;
00395         }
00396         for (i=0; tone < ftotbl[i]; i++) {
00397                 ret++;
00398         }
00399         if (ret >= 128) {
00400                 return(127);
00401         }
00402         return(ret);
00403 }
00404 
00405 static void psgmix(UINT8 ch, PSGGEN psg) {
00406 
00407         KDPSGCTRL       *k;
00408 
00409         k = keydisp.psgctl + ch;
00410         if ((k->mix ^ psg->reg.mixer) & 7) {
00411                 UINT8 i, bit, pos;
00412                 k->mix = psg->reg.mixer;
00413                 pos = keydisp.psgpos[ch];
00414                 for (i=0, bit=1; i<3; i++, pos++, bit<<=1) {
00415                         if (k->flag & bit) {
00416                                 k->flag ^= bit;
00417                                 delaysetevent(pos, k->lastnote[i]);
00418                         }
00419                         else if ((!(k->mix & bit)) && (psg->reg.vol[i] & 0x1f)) {
00420                                 k->flag |= bit;
00421                                 k->fto[i] = LOADINTELWORD(psg->reg.tune[i]) & 0xfff;
00422                                 k->lastnote[i] = getpsgnote(k->fto[i]);
00423                                 delaysetevent(pos, (UINT8)(k->lastnote[i] | 0x80));
00424                         }
00425                 }
00426         }
00427 }
00428 
00429 static void psgvol(UINT8 ch, PSGGEN psg, UINT8 i) {
00430 
00431         KDPSGCTRL       *k;
00432         UINT8           bit;
00433         UINT8           pos;
00434         UINT16          tune;
00435 
00436         k = keydisp.psgctl + ch;
00437         bit = (1 << i);
00438         pos = keydisp.psgpos[ch] + i;
00439         if (psg->reg.vol[i] & 0x1f) {
00440                 if (!((k->mix | k->flag) & bit)) {
00441                         k->flag |= bit;
00442                         tune = LOADINTELWORD(psg->reg.tune[i]);
00443                         tune &= 0xfff;
00444                         k->fto[i] = tune;
00445                         k->lastnote[i] = getpsgnote(tune);
00446                         delaysetevent(pos, (UINT8)(k->lastnote[i] | 0x80));
00447                 }
00448         }
00449         else if (k->flag & bit) {
00450                 k->flag ^= bit;
00451                 delaysetevent(pos, k->lastnote[i]);
00452         }
00453 }
00454 
00455 static void psgkeyreset(void) {
00456 
00457         ZeroMemory(keydisp.psgctl, sizeof(keydisp.psgctl));
00458 }
00459 
00460 void keydisp_psgmix(void *psg) {
00461 
00462         UINT8   c;
00463 
00464         if (keydisp.mode != KEYDISP_MODEFM) {
00465                 return;
00466         }
00467         for (c=0; c<keydisp.psgmax; c++) {
00468                 if (psgtbl[c] == psg) {
00469                         psgmix(c, (PSGGEN)psg);
00470                         break;
00471                 }
00472         }
00473 }
00474 
00475 void keydisp_psgvol(void *psg, UINT8 ch) {
00476 
00477         UINT8   c;
00478 
00479         if (keydisp.mode != KEYDISP_MODEFM) {
00480                 return;
00481         }
00482         for (c=0; c<keydisp.psgmax; c++) {
00483                 if (psgtbl[c] == psg) {
00484                         psgvol(c, (PSGGEN)psg, ch);
00485                         break;
00486                 }
00487         }
00488 }
00489 
00490 static void psgkeysync(void) {
00491 
00492         UINT8           ch;
00493         KDPSGCTRL       *k;
00494         UINT8           bit;
00495         UINT8           i;
00496         UINT8           pos;
00497         PSGGEN          psg;
00498         UINT16          tune;
00499         UINT8           n;
00500 
00501         for (ch=0, k=keydisp.psgctl; ch<keydisp.psgmax; ch++, k++) {
00502                 psg = (PSGGEN)psgtbl[ch];
00503                 pos = keydisp.psgpos[ch];
00504                 for (i=0, bit=1; i<3; i++, pos++, bit<<=1) {
00505                         if (k->flag & bit) {
00506                                 tune = LOADINTELWORD(psg->reg.tune[i]);
00507                                 tune &= 0xfff;
00508                                 if (k->fto[i] != tune) {
00509                                         k->fto[i] = tune;
00510                                         n = getpsgnote(tune);
00511                                         if (k->lastnote[i] != n) {
00512                                                 delaysetevent(pos, k->lastnote[i]);
00513                                                 k->lastnote[i] = n;
00514                                                 delaysetevent(pos, (UINT8)(n | 0x80));
00515                                         }
00516                                 }
00517                         }
00518                 }
00519         }
00520 }
00521 
00522 
00523 // ---- BOARD change...
00524 
00525 static void setfmhdl(UINT8 items, UINT base) {
00526 
00527         while(items--) {
00528                 if ((keydisp.keymax < KEYDISP_CHMAX) &&
00529                         (keydisp.fmmax < KEYDISP_FMCHMAX)) {
00530                         keydisp.fmpos[keydisp.fmmax] = keydisp.keymax++;
00531                         keydisp.pfmreg[keydisp.fmmax] = opn.reg + base;
00532                         keydisp.fmmax++;
00533                         base++;
00534                         if ((base & 3) == 3) {
00535                                 base += 0x100 - 3;
00536                         }
00537                 }
00538         }
00539 }
00540 
00541 #if defined(SUPPORT_PX)
00542 static void setfmhdlex(const OPN_T *pOpn, UINT nItems, UINT nBase) {
00543 
00544         while(nItems--) {
00545                 if ((keydisp.keymax < KEYDISP_CHMAX) &&
00546                         (keydisp.fmmax < KEYDISP_FMCHMAX)) {
00547                         keydisp.fmpos[keydisp.fmmax] = keydisp.keymax++;
00548                         keydisp.pfmreg[keydisp.fmmax] = pOpn->reg + nBase;
00549                         keydisp.fmmax++;
00550                         nBase++;
00551                         if ((nBase & 3) == 3) {
00552                                 nBase += 0x100 - 3;
00553                         }
00554                 }
00555         }
00556 }
00557 #endif  // defined(SUPPORT_PX)
00558 
00559 static void setpsghdl(UINT8 items) {
00560 
00561         while(items--) {
00562                 if ((keydisp.keymax <= (KEYDISP_CHMAX - 3)) &&
00563                         (keydisp.psgmax < KEYDISP_PSGMAX)) {
00564                         keydisp.psgpos[keydisp.psgmax++] = keydisp.keymax;
00565                         keydisp.keymax += 3;
00566                 }
00567         }
00568 }
00569 
00570 void keydisp_setfmboard(UINT b) {
00571 
00572         keydisp.keymax = 0;
00573         keydisp.fmmax = 0;
00574         keydisp.psgmax = 0;
00575 
00576 #if defined(SUPPORT_PX)
00577         if (b == 0x30)
00578         {
00579                 setfmhdlex(&opn, 12, 0);
00580                 setfmhdlex(&opn2, 12, 0);
00581                 setpsghdl(2);
00582                 b = 0;
00583         }
00584         if (b == 0x50)
00585         {
00586                 setfmhdlex(&opn, 12, 0);
00587                 setfmhdlex(&opn2, 12, 0);
00588                 setfmhdlex(&opn3, 6, 0);
00589                 setpsghdl(3);
00590                 b = 0;
00591         }
00592 
00593 #endif  // defined(SUPPORT_PX)
00594 
00595         if (b & 0x02) {
00596                 if (!(b & 0x04)) {
00597                         setfmhdl(3, 0);
00598                 }
00599                 else {                                                          // 2枚刺しの時レジスタ移動
00600                         setfmhdl(3, 0x200);
00601                 }
00602                 setpsghdl(1);
00603         }
00604         if (b & 0x04) {
00605                 setfmhdl(6, 0);
00606                 setpsghdl(1);
00607         }
00608         if (b & 0x08) {
00609                 setfmhdl(6, 0);
00610                 setpsghdl(1);
00611         }
00612         if (b & 0x20) {
00613                 setfmhdl(6, 0);
00614                 setpsghdl(1);
00615         }
00616         if (b & 0x40) {
00617                 setfmhdl(12, 0);
00618                 setpsghdl(1);
00619         }
00620         if (b & 0x80) {
00621                 setpsghdl(3);
00622         }
00623         delayreset();
00624         fmkeyreset();
00625         psgkeyreset();
00626 
00627         if (keydisp.mode == KEYDISP_MODEFM) {
00628                 keydisp.dispflag |= KEYDISP_FLAGSIZING;
00629         }
00630 }
00631 
00632 
00633 // ---- MIDI
00634 
00635 void keydisp_midi(const UINT8 *cmd) {
00636 
00637         if (keydisp.mode != KEYDISP_MODEMIDI) {
00638                 return;
00639         }
00640         switch(cmd[0] & 0xf0) {
00641                 case 0x80:
00642                         keyoff(cmd[0] & 0x0f, cmd[1]);
00643                         break;
00644 
00645                 case 0x90:
00646                         if (cmd[2] & 0x7f) {
00647                                 keyon(cmd[0] & 0x0f, cmd[1]);
00648                         }
00649                         else {
00650                                 keyoff(cmd[0] & 0x0f, cmd[1]);
00651                         }
00652                         break;
00653 
00654                 case 0xb0:
00655                         if ((cmd[1] == 0x78) || (cmd[1] == 0x79) || (cmd[1] == 0x7b)) {
00656                                 chkeyoff(cmd[0] & 0x0f);
00657                         }
00658                         break;
00659 
00660                 case 0xfe:
00661                         keyalloff();
00662                         break;
00663         }
00664 }
00665 
00666 
00667 // ---- draw
00668 
00669 static int getdispkeys(void) {
00670 
00671         int             keys;
00672 
00673         switch(keydisp.mode) {
00674                 case KEYDISP_MODEFM:
00675                         keys = keydisp.keymax;
00676                         break;
00677 
00678                 case KEYDISP_MODEMIDI:
00679                         keys = 16;
00680                         break;
00681 
00682                 default:
00683                         keys = 0;
00684                         break;
00685         }
00686         if (keys > KEYDISP_CHMAX) {
00687                 keys = KEYDISP_CHMAX;
00688         }
00689         return(keys);
00690 }
00691 
00692 static void clearrect(CMNVRAM *vram, int x, int y, int cx, int cy) {
00693 
00694         CMNPAL  col;
00695 
00696         switch(vram->bpp) {
00697 #if defined(SUPPORT_8BPP)
00698                 case 8:
00699                         col.pal8 = keydisp.pal8[KEYDISP_PALBG];
00700                         break;
00701 #endif
00702 #if defined(SUPPORT_16BPP)
00703                 case 16:
00704                         col.pal16 = keydisp.pal16[KEYDISP_LEVEL];
00705                         break;
00706 #endif
00707 #if defined(SUPPORT_24BPP)
00708                 case 24:
00709 #endif
00710 #if defined(SUPPORT_32BPP)
00711                 case 32:
00712 #endif
00713 #if defined(SUPPORT_24BPP) || defined(SUPPORT_32BPP)
00714                         col.pal32 = keydisp.pal32[KEYDISP_LEVEL];
00715                         break;
00716 #endif
00717                 default:
00718                         return;
00719         }
00720         cmndraw_fill(vram, x, y, cx, cy, col);
00721 }
00722 
00723 static void drawkeybg(CMNVRAM *vram) {
00724 
00725         CMNPAL  bg;
00726         CMNPAL  fg;
00727         int             i;
00728 
00729         switch(vram->bpp) {
00730 #if defined(SUPPORT_8BPP)
00731                 case 8:
00732                         bg.pal8 = keydisp.pal8[KEYDISP_PALBG];
00733                         fg.pal8 = keydisp.pal8[KEYDISP_PALFG];
00734                         break;
00735 #endif
00736 #if defined(SUPPORT_16BPP)
00737                 case 16:
00738                         bg.pal16 = keydisp.pal16[KEYDISP_LEVEL];
00739                         fg.pal16 = keydisp.pal16[0];
00740                         break;
00741 #endif
00742 #if defined(SUPPORT_24BPP)
00743                 case 24:
00744                         bg.pal32 = keydisp.pal32[KEYDISP_LEVEL];
00745                         fg.pal32 = keydisp.pal32[0];
00746                         break;
00747 #endif
00748 #if defined(SUPPORT_32BPP)
00749                 case 32:
00750                         bg.pal32 = keydisp.pal32[KEYDISP_LEVEL];
00751                         fg.pal32 = keydisp.pal32[0];
00752                         break;
00753 #endif
00754                 default:
00755                         return;
00756         }
00757         for (i=0; i<10; i++) {
00758                 cmndraw_setpat(vram, keybrd1, i * KEYDISP_KEYCX, 0, bg, fg);
00759         }
00760         cmndraw_setpat(vram, keybrd2, 10 * KEYDISP_KEYCX, 0, bg, fg);
00761 }
00762 
00763 static BOOL draw1key(CMNVRAM *vram, KDCHANNEL *kdch, UINT n) {
00764 
00765         KDKEYPOS        *pos;
00766         UINT            pal;
00767         CMNPAL          fg;
00768 
00769         pos = keydisp.keypos + (kdch->k[n] & 0x7f);
00770         pal = kdch->r[n] & 0x7f;
00771         switch(vram->bpp) {
00772 #if defined(SUPPORT_8BPP)
00773                 case 8:
00774                         if (pal != (KEYDISP_LEVEL - 1)) {
00775                                 fg.pal8 = keydisp.pal8[
00776                                                                         (pos->pals)?KEYDISP_PALBG:KEYDISP_PALFG];
00777                                 cmndraw_setfg(vram, pos->data, pos->posx, 0, fg);
00778                                 kdch->r[n] = 0;
00779                                 return(TRUE);
00780                         }
00781                         fg.pal8 = keydisp.pal8[KEYDISP_PALHIT];
00782                         break;
00783 #endif
00784 #if defined(SUPPORT_16BPP)
00785                 case 16:
00786                         fg.pal16 = keydisp.pal16[pal + pos->pals];
00787                         break;
00788 #endif
00789 #if defined(SUPPORT_24BPP)
00790                 case 24:
00791                         fg.pal32 = keydisp.pal32[pal + pos->pals];
00792                         break;
00793 #endif
00794 #if defined(SUPPORT_32BPP)
00795                 case 32:
00796                         fg.pal32 = keydisp.pal32[pal + pos->pals];
00797                         break;
00798 #endif
00799                 default:
00800                         return(FALSE);
00801         }
00802         cmndraw_setfg(vram, pos->data, pos->posx, 0, fg);
00803         return(FALSE);
00804 }
00805 
00806 static BOOL draw1ch(CMNVRAM *vram, UINT8 framepast, KDCHANNEL *kdch) {
00807 
00808         BOOL    draw;
00809         UINT    i;
00810         BOOL    coll;
00811         UINT8   nextf;
00812         UINT    j;
00813 
00814         draw = FALSE;
00815         if (kdch->flag & 2) {
00816                 drawkeybg(vram);
00817                 draw = TRUE;
00818         }
00819         if (kdch->flag) {
00820                 coll = FALSE;
00821                 nextf = 0;
00822                 for (i=0; i<kdch->remain; i++) {
00823                         if ((kdch->r[i] & 0x80) || (kdch->flag & 2)) {
00824                                 kdch->r[i] &= ~0x80;
00825                                 if (kdch->r[i] < (KEYDISP_LEVEL - 1)) {
00826                                         if (kdch->r[i] > framepast) {
00827                                                 kdch->r[i] -= framepast;
00828                                                 kdch->r[i] |= 0x80;
00829                                                 nextf = 1;
00830                                         }
00831                                         else {
00832                                                 kdch->r[i] = 0;
00833                                                 coll = TRUE;
00834                                         }
00835                                 }
00836                                 coll |= draw1key(vram, kdch, i);
00837                                 draw = TRUE;
00838                         }
00839                 }
00840                 if (coll) {
00841                         for (i=0; i<kdch->remain; i++) {
00842                                 if (!kdch->r[i]) {
00843                                         break;
00844                                 }
00845                         }
00846                         for (j=i; i<kdch->remain; i++) {
00847                                 if (kdch->r[i]) {
00848                                         kdch->k[j] = kdch->k[i];
00849                                         kdch->r[j] = kdch->r[i];
00850                                         j++;
00851                                 }
00852                         }
00853                         kdch->remain = j;
00854                 }
00855                 kdch->flag = nextf;
00856         }
00857         return(draw);
00858 }
00859 
00860 
00861 // ----
00862 
00863 void keydisp_initialize(void) {
00864 
00865         int             r;
00866         UINT16  x;
00867         int             i;
00868 
00869         r = 0;
00870         x = 0;
00871         do {
00872                 for (i=0; i<12 && r<128; i++, r++) {
00873                         keydisp.keypos[r].posx = keyposdef[i].posx + x;
00874                         keydisp.keypos[r].pals = keyposdef[i].pals;
00875                         keydisp.keypos[r].data = keyposdef[i].data;
00876                 }
00877                 x += 28;
00878         } while(r < 128);
00879         keyallclear();
00880 }
00881 
00882 void keydisp_setpal(CMNPALFN *palfn) {
00883 
00884         UINT    i;
00885         RGB32   pal32[KEYDISP_PALS];
00886 
00887         if (palfn == NULL) {
00888                 return;
00889         }
00890         if (palfn->get8) {
00891                 for (i=0; i<KEYDISP_PALS; i++) {
00892                         keydisp.pal8[i] = (*palfn->get8)(palfn, i);
00893                 }
00894         }
00895         if (palfn->get32) {
00896                 for (i=0; i<KEYDISP_PALS; i++) {
00897                         pal32[i].d = (*palfn->get32)(palfn, i);
00898                         cmndraw_makegrad(keydisp.pal32, KEYDISP_LEVEL,
00899                                                                 pal32[KEYDISP_PALFG], pal32[KEYDISP_PALHIT]);
00900                         cmndraw_makegrad(keydisp.pal32 + KEYDISP_LEVEL, KEYDISP_LEVEL,
00901                                                                 pal32[KEYDISP_PALBG], pal32[KEYDISP_PALHIT]);
00902                 }
00903                 if (palfn->cnv16) {
00904                         for (i=0; i<KEYDISP_LEVEL*2; i++) {
00905                                 keydisp.pal16[i] = (*palfn->cnv16)(palfn, keydisp.pal32[i]);
00906                         }
00907                 }
00908         }
00909         keydisp.dispflag |= KEYDISP_FLAGREDRAW;
00910 }
00911 
00912 void keydisp_setmode(UINT8 mode) {
00913 
00914         if (keydisp.mode != mode) {
00915                 keydisp.mode = mode;
00916                 keydisp.dispflag |= KEYDISP_FLAGREDRAW | KEYDISP_FLAGSIZING;
00917                 keyallclear();
00918                 if (mode == KEYDISP_MODEFM) {
00919                         delayreset();
00920                         fmkeyreset();
00921                         psgkeyreset();
00922                 }
00923         }
00924         else {
00925                 keyalloff();
00926         }
00927 }
00928 
00929 void keydisp_setdelay(UINT8 frames) {
00930 
00931         keydisp.delay.warmbase = frames;
00932         delayreset();
00933 }
00934 
00935 UINT8 keydisp_process(UINT8 framepast) {
00936 
00937         int             keys;
00938         int             i;
00939 
00940         if (framepast) {
00941                 if (keydisp.mode == KEYDISP_MODEFM) {
00942                         fmkeysync();
00943                         psgkeysync();
00944                         delayexecevent(framepast);
00945                 }
00946                 keydisp.framepast += framepast;
00947         }
00948         keys = getdispkeys();
00949         for (i=0; i<keys; i++) {
00950                 if (keydisp.ch[i].flag) {
00951                         keydisp.dispflag |= KEYDISP_FLAGDRAW;
00952                         break;
00953                 }
00954         }
00955         return(keydisp.dispflag);
00956 }
00957 
00958 void keydisp_getsize(int *width, int *height) {
00959 
00960         if (width) {
00961                 *width = KEYDISP_WIDTH;
00962         }
00963         if (height) {
00964                 *height = (getdispkeys() * KEYDISP_KEYCY) + 1;
00965         }
00966         keydisp.dispflag &= ~KEYDISP_FLAGSIZING;
00967 }
00968 
00969 BOOL keydisp_paint(CMNVRAM *vram, BOOL redraw) {
00970 
00971         BOOL            draw;
00972         int                     keys;
00973         int                     i;
00974         KDCHANNEL       *p;
00975 
00976         draw = FALSE;
00977         if ((vram == NULL) ||
00978                 (vram->width < KEYDISP_WIDTH) || (vram->height < 1)) {
00979                 goto kdpnt_exit;
00980         }
00981         if (keydisp.dispflag & KEYDISP_FLAGREDRAW){
00982                 redraw = TRUE;
00983         }
00984         if (redraw) {
00985                 keyallreload();
00986                 clearrect(vram, 0, 0, KEYDISP_WIDTH, 1);
00987                 clearrect(vram, 0, 0, 1, vram->height);
00988                 draw = TRUE;
00989         }
00990         vram->ptr += vram->xalign + vram->yalign;               // ptr (1, 1)
00991         keys = (vram->height - 1) / KEYDISP_KEYCY;
00992         keys = min(keys, getdispkeys());
00993         for (i=0, p=keydisp.ch; i<keys; i++, p++) {
00994                 draw |= draw1ch(vram, keydisp.framepast, p);
00995                 vram->ptr += KEYDISP_KEYCY * vram->yalign;
00996         }
00997         keydisp.dispflag &= ~(KEYDISP_FLAGDRAW | KEYDISP_FLAGREDRAW);
00998         keydisp.framepast = 0;
00999 
01000 kdpnt_exit:
01001         return(draw);
01002 }
01003 #endif
01004