view cdcnv.c @ 11:1ee15e2dc386 default tip

added support for macosx
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Fri, 30 Nov 2012 22:10:10 +0900
parents c6f444d2272c
children
line wrap: on
line source

/* cdcnv.c ---------------------------------------------
$Id: cdcnv.c,v 1.1 2002/12/21 01:13:27 tosy Exp $

  (以前の履歴は rcctl.c 参照)
  v0.30  97.12.13  コード変換部(cdcnv.c)分離
  v0.31  98.03.07  Mac21対応
  v0.31a 98.03.11  Syncom対応(要rc_send修正)
  v0.31b 98.03.15  ALISA3(L)対応
  v0.32  98.11.29  鉄人,Σ,NET7000対応
  v0.40  02.12.15  B-kara,HyperJOY対応,Σバグ修正
  v0.50  11.01.06  libhidを使ってlinux用に書き直し (yaz)
------------------------------------------------------*/

#include <string.h>
#include <stdio.h>
#include "debug.h"

#if defined(__FreeBSD__) || defined(linux) || defined(__APPLE__)
#define stricmp(s, c) strcasecmp(s, c)
#endif

const char mks[] = "XUGJHBPDSNKMALZTCI";
#define M_X2 0	/* X2000 */
#define M_UK 1	/* U-kara */
#define M_GI 2	/* GIGA */
#define M_JO 3	/* JOYSOUND */
#define M_HJ 4	/* HyperJOY */
#define M_BT 5	/* BeMax'S(T) */
#define M_PR 6	/* Prologue21 */
#define M_DA 7	/* DAM */
#define M_SY 8	/* Syncom/孫悟空 */
#define M_N7 9	/* NET7000 */
#define M_BK 10 /* B-kara */
#define M_MA 11	/* Mac21 */
#define M_A3 12	/* ALISA3(A) */
#define M_AL 13	/* ALISA3(L) */
#define M_AZ 14	/* ALISA3(Z) */
#define M_TS 15	/* 東映システム */
#define M_SI 16	/* Σシステム */
#define M_TJ 17	/* カラオケの鉄人 */

#define K_SE 3
#define K_KU 4
#define K_KD 5
#define K_SP 6
#define K_ST 7
#define K_CL 8
#define K_NM 9

int cvt[][21] = {
  /* cd,  IDL,  IDH,   SE,   KU,   KD,   SP,   ST,   CL, */
  /*  0,    1,    2,    3,    4,    5,    6,    7,    8,    9,    A,    B*/
  {0x30, 0x2e, 0xd1, 0x17, 0x02, 0x03, 0x0c, 0x1c, 0x0d,         /* X2000 */
   0x13, 0x10, 0x14, 0x18, 0x11, 0x15, 0x19, 0x12, 0x16, 0x1a,   -1,   -1 },
  {0x30, 0x98, 0x67, 0x0c, 0x13, 0x12, 0x0f, 0x0e, 0x0d,     /* U-kara/-2 */
   0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   -1,   -1 },
  {0x10, 0x84, 0x10,   -1, 0x04, 0x05, 0x0f, 0x01,   -1,          /* GIGA */
   0xf0, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0,   -1,   -1 },
  {0x40, 0x81, 0x16, 0x1f, 0x54, 0x0b, 0x1d, 0x5c, 0x1c,      /* JOYSOUND */
   0x00, 0x07, 0x0a, 0x58, 0x03, 0x06, 0x50, 0x01, 0x0e, 0x5d,   -1,   -1 },
  {0x20, 0x81, 0x16, 0x1f, 0x54, 0x0b, 0x1d, 0x5c, 0x1c,      /* HyperJOY */
   0x00, 0x07, 0x0a, 0x58, 0x03, 0x06, 0x50, 0x01, 0x0e, 0x5d,   -1,   -1 },
  {0x20, 0xac, 0x53, 0x9d, 0xcc, 0xca, 0x96, 0xdc, 0x9a,   /* BeMax'S (T) */
   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,   -1,   -1 },
  {0x10, 0x81, 0xb0, 0x33, 0xd3, 0xb3, 0x93, 0x13,   -1,    /* Prologue21 */
   0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, 0x01, 0x09,   -1,   -1 },
  {0x10, 0xd1, 0x2d, 0x09, 0x04, 0x05, 0x00, 0x01, 0x07,           /* DAM */
   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b },
  {0x60, 0xc3, 0xc3, 0x05, 0x2c, 0x2d, 0x04, 0xc7, 0x02,        /* Syncom */
   0x0f, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,   -1,   -1 },
  {0x30, 0x84, 0x05, 0x0f, 0x0e, 0x0c, 0x07,   -1, 0x1e,       /* NET7000 */
   0x1c, 0x10, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19, 0x1a,   -1,   -1 },
  {0x10, 0x2e, 0xd1, 0x4c, 0x35, 0x33, 0x4f, 0x4e, 0x4d,        /* B-kara */
   0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b },
  {0x30, 0x80, 0x00, 0x03, 0x18, 0x14, 0x1e,   -1, 0x07,         /* Mac21 */
   0x00, 0x0c, 0x0d, 0x0e, 0x08, 0x09, 0x0a, 0x04, 0x05, 0x06, 0x01, 0x02 },
  {0x30, 0x87, 0x56, 0x12, 0x43, 0x47, 0x11,   -1, 0x42,        /* ALISA3 */
   0x0d, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f },
  {0x30, 0x87, 0x56, 0x12, 0x43, 0x47, 0x11,   -1, 0x42,        /* ALISA3 */
   0x0d, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f },
  {0x30, 0x87, 0x56, 0x12, 0x43, 0x47, 0x11,   -1, 0x42,        /* ALISA3 */
   0x0d, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f },
  {0x30, 0x00, 0xff, 0x41, 0x08, 0x09, 0x4c, 0x45, 0x44,      /* TOEI sys */
   0x13, 0x0f, 0x4f, 0x4e, 0x07, 0x47, 0x46, 0x03, 0x43, 0x42, 0x53, 0x52 },

  {0x10, 0x55, 0xaa, 0x3e, 0x08, 0x09, 0x5c,   -1,   -1,     /* Σ System */
   0x13, 0x0f, 0x4f, 0x4e, 0x07, 0x47, 0x46, 0x03, 0x43, 0x42, 0x53, 0x52 },

  {0x40, 0xae, 0x51, 0xdc, 0x03, 0x02, 0x96,   -1, 0xdd,          /* 鉄人 */
   0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0xda, 0xdb }
  };

int tsc[] = {0x00, 0x04, 0x0c, 0x10, 0x01, 0x05, 0x0d, 0x11};
int tjc[] = {0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xde, 0xd0, 0xd1, 0xd2, 0xd3};

char *cverrstr[] = {
  "Invalid maker code.",
  "Invalid music number.",
  "Invalid function code."
};

int cdcnv(int buf[], char *mak, char *cod)
{
    int maker, i, c, n, *q;
    char *tmp = NULL;

    debug(2, "mak=%s cod=%s\n", mak, cod);

    tmp = strchr(mks, *mak & 0xdf);
    if(!tmp)
        return -1;

    maker = (int)(tmp - mks);
    debug(2, "maker=%d\n", maker);

    q = buf;

    *q++ = 0x80;	/* wake-up code */
    *q++ = cvt[maker][0];
    *q++ = cvt[maker][1];
    *q++ = cvt[maker][2];

    /* 統合機種等でのメーカー名指定 */
    if ((c = *++mak) != 0) {
        if ((maker == M_A3)&&('0' <= c)&&(c <= '4'))
            cvt[maker][K_SE] = 0x12 + (c - '0');
        else if ((maker == M_AZ)&&('1' <= c)&&(c <= '4'))
            *q++ = 0x13 + (c - '1');
        else if ((maker == M_AL)&&('0' <= c)&&(c <= '9')) {
            *q++ = cvt[maker][K_NM + (c - '0')];
            *q++ = 0x10;
        }
        else if ((maker == M_TS)&&('1' <= c)&&(c <= '8'))
            *q++ = tsc[c - '1'];
        else if ((maker == M_TJ)&&('0' <= c)&&(c <= '9'))
            *q++ = tjc[c - '1'];
        else if ((maker == M_UK)&&('2' == c)) {
            buf[1] = 0x70;
            *q++ = 0xf0;
        }
    }
    if (maker == M_BK)
        *q++ = 0xf0;

    if (('0' <= *cod)&&(*cod <= '9')) {
        if (maker == M_DA)
            *q++ = 0x08;
        else if (maker == M_MA)
            *q++ = 0x10;	/* Req.1 */
        else if (maker == M_SI) {
            /* [1-9A-F] -> '01','02',...,'15' , NULL -> '00' */
            if (*mak == 0) {
                *q++ = cvt[maker][K_NM + 0];
                *q++ = cvt[maker][K_NM + 0];
            }
            else {
                if (mak[1] != 0)
                    *q++ = cvt[maker][K_NM + (*mak++ - '0')];
                else
                    *q++ = cvt[maker][K_NM + ((*mak >= 'A')? 1: 0)];
                *q++ = cvt[maker][K_NM + ((*mak % 0x41) & 0x0f)];
            }
        }

        /* 曲コード変換 */
        while((c = *cod++) != '\0') {
            if (('0' <= c)&&(c <= '9'))
                *q = cvt[maker][c - '0' + K_NM];
            else if ((c == 'A')||(c == 'a'))
                *q = cvt[maker][10 + K_NM];
            else if ((c == 'B')||(c == 'b'))
                *q = cvt[maker][11 + K_NM];
            else if (c == '-') {
                if (maker == M_TJ)
                    *q = cvt[maker][K_SE];
                else
                    continue;
            }
            else
                *q = -1;
            if (*q++ == -1)
                return -2;
        }

        /* 送信直前処理 */
        switch(maker) {
        case M_X2:
            /* X2000: 曲コードの末尾 2 桁の直前にも SET を送信 */
            q -= 2;
            q[3] = cvt[maker][K_SE];
            q[2] = q[1];
            q[1] = q[0];
            q[0] = cvt[maker][K_SE];
            q += 4;
            break;

        case M_GI:
            /* GIGA: 曲コードが 6 桁以下の場合は最後に'0'を埋める */
            while(q < &buf[10])
                *q++ = cvt[maker][K_NM];
            break;

        case M_PR:
            /* Prologue21: */
            for( i=0; i<3; i++ ) {
                buf[10-i] = 0;
                if (q > &buf[4])
                    buf[10-i] = *--q << 4;
                if (q > &buf[4])
                    buf[10-i] |= *--q;
            }
            q = &buf[11];
            *q++ = 0x33;
            buf[4] = buf[8];
            buf[5] = buf[9];
            buf[6] = buf[10];
            buf[7] = buf[11];
            break;  /* q=&buf[8] にしないとバグのような… */

        case M_SI:
            /* Σシステム: コード長 10 バイト(<Maker[2]>,<Code[7]>,<SET>)固定 */
        case M_DA:
            /* DAM: コード長 9 バイト(0x08,<Code[7]>,<SET>)固定 */
        case M_BK:
            /* B-kara: コード長 9 バイト(0xf0,<Code[7]>,<SET>)固定 */
            n = (maker == M_SI)? 12: 11; /* 数字の最終桁を buf[n] とした値 */
            for( i=0; i<7; i++ ) {
                c = *(q-1);
                if ((i == 1)&&((c == cvt[maker][K_NM+10])||(c == cvt[maker][K_NM+11])))
                    /* 曲コード中の'A','B'以降の桁数が1桁なら'0'を挿入 */
                    buf[n-i] = cvt[maker][K_NM + 0];
                else if ((i == 2)&&(c!=cvt[maker][K_NM+10])&&(c!=cvt[maker][K_NM+11]))
                    /* 曲コードの末尾 3 文字めが'A','B'でなければ'-'を設定 */
                    buf[n-i] = (maker == M_BK)? 0x3d: ((maker == M_SI)? 0x51: 0x3c);
                else if (q > &buf[n-6])
                    buf[n-i] = *--q;
                else
                    /* 桁数の足らない部分には'0'を設定 */
                    buf[n-i] = cvt[maker][K_NM + 0];
            }
            q = &buf[n+1];
        default:
            *q++ = cvt[maker][K_SE];
            break;
        }
    }
    /* 制御コードの処理 */
    else {
        *q = -1;
        if (!stricmp(cod, "SE"))
            *q = cvt[maker][K_SE];
        else if (!stricmp(cod, "KU"))
            *q = cvt[maker][K_KU];
        else if (!stricmp(cod, "KD"))
            *q = cvt[maker][K_KD];
        else if (!stricmp(cod, "SP"))
            *q = cvt[maker][K_SP];
        else if (!stricmp(cod, "ST"))
            *q = cvt[maker][K_ST];
        else if (!stricmp(cod, "CL"))
            *q = cvt[maker][K_CL];
        if (*q == -1)
            return -3;
        q++;
    }

    if ((maker == M_BK)||((maker == M_UK)&&('2' == *mak)))
        *q++ = 0xf7;

    buf[1] |= q-buf-2;	/* 実送信バイト数(PIC 制御用)を埋め込み */
    return q-buf;
}