home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / lib / yotpin / src / piload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-27  |  11.0 KB  |  533 lines

  1. /*
  2. *    Yamana's Otomeza Plug-in Tool
  3. *        ぱいろーだ
  4. *    
  5. *    1995.07.23    
  6. *    1995.07.30    16色に暫定対応
  7. *    1995.08.06    デフォルトパレットの修正, ビット操作部の改良
  8. *    1995.08.13    16色の横幅の半端なものの読み込みに対応
  9. *    1995.08.20    ↑大嘘だったので修正
  10. *    
  11. *    問題点
  12. *    ・16色画像を256色とみなして処理するので、無駄なメモリを食う。
  13. *    
  14. *    
  15. *    "Pi" (c) A.Yanagisawa
  16. */
  17. #include "otome_pi.h"
  18.  
  19. const char    longname[]    = "File  :Pi ローダ";
  20. const char    extend[]    = "PI";
  21.  
  22. #define     USE_FILE    PI_LOAD
  23. #include    "otome_pi.c"
  24.  
  25. typedef
  26.     struct
  27.     {    char    mode;        /* パレットなし= 0x80 */
  28.         char    n;
  29.         char    m;            /* 縦横比 n/m */
  30.         char    pix;        /* 4 or 8 */
  31.         char    name[4];    /* 機種名 */
  32.         short    mdat_len;    /* 機種予約コードサイズ */
  33.         char    *mdat;        /* 機種予約コード */
  34.         short    x;
  35.         short    y;
  36.         char    *palt;        /* 0 or 3*16 or 3*256 */
  37.     }
  38.     PiHeader;
  39.  
  40. unsigned int    Pi_getBit();
  41.  
  42. int        Pi_countBit = 0;
  43. int     Pi_maxBit;
  44. char    *ColTbl;
  45.  
  46. int     precol;
  47.  
  48. /********************************************************************/
  49.  
  50. extern    int    Pi_getColor256();
  51. extern    int    Pi_getColor16();
  52.  
  53. int     Pi_decode( decbuf, buf, head )
  54. char        *decbuf,*buf;
  55. PiHeader    *head;
  56. {
  57.     int     i;
  58.     char    c0,c1,c2,c3;
  59.     char    *image;
  60.     int     pos,len,Width,Height;
  61.     int     prepos,Pi_all;
  62.     int     (*Pi_getColor)();
  63.     
  64.     int     Pi_posTable[][2] = 
  65.                 {    {-2, 0 },    /* 0 :前のピクセルにより変化するので注意 */
  66.                     { 0,-1 },    /* 1: 1ライン上                */
  67.                     { 0,-2 },    /* 2: 2ライン上                */
  68.                     { 1,-1 },    /* 3: 1ライン上の1ドット右    */
  69.                     {-1,-1 }    /* 4: 1ライン上の1ドット左    */
  70.                 };
  71.     
  72.     Width  = head->x;
  73.     Height = head->y;    
  74.     Pi_all = (Width * (Height+2)) ;
  75.     
  76.     for( i=1; i<=4 ; i++ )
  77.         Pi_posTable[i][0] += Pi_posTable[i][1]*Width;
  78.     
  79.     if( head->pix == 8 )    Pi_getColor = Pi_getColor256;
  80.                     else    Pi_getColor = Pi_getColor16;
  81.     
  82.     image = decbuf;
  83.     precol = 0;
  84.     c0 = Pi_getColor( buf );
  85.     c1 = Pi_getColor( buf );
  86.     
  87.     for( i=0; i<Width; i++ )    /* 先頭2ラインを先に埋める */
  88.     {
  89.         *image++ = c0;
  90.         *image++ = c1;        /* 常に2ドットごと扱う */
  91.     }
  92.     
  93.     prepos = -1;
  94.     while( Pi_countBit < Pi_maxBit )
  95.     {
  96.         /* まず位置データを得る。2 or 3 ビット長 */
  97.         pos = Pi_getBit( buf, 2 );
  98.         if( pos == 3 )    pos += Pi_getBit( buf, 1 );
  99.         
  100.         /* 位置が前に記録した位置と同じとき */
  101.         if( pos == prepos )
  102.         {    do
  103.             {    *image++ = Pi_getColor( buf );
  104.                 *image++ = Pi_getColor( buf );
  105.                 
  106.             }while( Pi_getBit(buf,1) );    /* (7) 'b' 同じパターンがない限り */
  107.             
  108.             prepos = -1;
  109.             continue;
  110.         }
  111.         prepos = pos;
  112.         
  113.         /* (4') 長さを求める */
  114.         len = Pi_getLen(buf);
  115.         
  116.         /* (3) */
  117.         if( pos )    /*  pos==(1~4) */
  118.         {
  119.             if( pos>4 )    break;
  120.             
  121.             memcpy( image, image + Pi_posTable[pos][0], len*2 );
  122.             image += len*2 ;
  123.         }
  124.         else        /*  pos==0 : 直前色と同じなら2,違うとき4ドット右 */
  125.         {
  126.             c1 = *(image-2);
  127.             c0 = *(image-1);
  128.             
  129.             if ( c0 == c1 )
  130.             {    while( len-- )        /* 同じパターンが続く限り繰り返す */
  131.                 {
  132.                     *image++ = c0;
  133.                     *image++ = c0;
  134.                 }
  135.             }else
  136.             {    c3 = *(image-4);
  137.                 c2 = *(image-3);
  138.                 
  139.                 while( len-- )
  140.                 {
  141.                     *image++ = c3;
  142.                     *image++ = c2;
  143.                     if( (len--) <= 0 )    break;    /* 2ドット単位 */
  144.                     *image++ = c1;
  145.                     *image++ = c0;
  146.                 }
  147.             }
  148.             
  149.         }/* (3) */
  150.         
  151.         precol = *(image-1);
  152.         
  153.     }/* LOOP */
  154.     
  155.     
  156.     return NOERR;
  157. }
  158.  
  159. /**************************************/
  160. /*        0         1
  161.        10x         2-3
  162.       110xx         4-7
  163.      1110xxx     8-15
  164.     11110xxxx    16-31
  165.         :          :
  166. */
  167. int        Pi_getLen(buf)        /* 長さ符号の解析 */
  168. char    *buf;
  169. {
  170.     int     i;
  171.     
  172.     for( i=0; Pi_getBit(buf,1) ; i++ );
  173.     
  174.     if( i==0 )    return 1;
  175.     
  176.     return (Pi_getBit(buf,i) | (1<<i));
  177.     
  178. }
  179.  
  180. /* 任意ビット長のデータを返す */
  181. unsigned int Pi_getBit( buf,bit )
  182. char    *buf;
  183. int     bit;
  184. {
  185.     char    restBit[]= {    0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01    };
  186.     register unsigned int    rest,low;
  187.     
  188.     if( Pi_countBit+bit >= Pi_maxBit )
  189.     {    Pi_countBit += bit;
  190.         return 0;
  191.     }
  192.     rest = (buf[ (Pi_countBit>>3) ] & restBit[ (Pi_countBit & 7) ]);
  193.     low  = (8 - (Pi_countBit & 7) );
  194.     
  195.     while( bit > low )    /* 足りないときは追加する */
  196.     {    
  197.         rest = (rest<<8) | buf[ (Pi_countBit>>3)+1 ];
  198.         low += 8;
  199.     }
  200.     Pi_countBit += bit ;
  201.     
  202.     return (rest >>(low-bit) );
  203. }
  204.  
  205.  
  206. /**************************************/
  207.  
  208. int     Pi_getColor256( buf )
  209. char    *buf;
  210. {
  211.     register unsigned int     col;
  212.     char    *p;
  213.     
  214.          if( Pi_getBit(buf,1)      )    col = Pi_getBit(buf,1)        ;
  215.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,1) | 0x02 ;
  216.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,2) | 0x04 ;
  217.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,3) | 0x08 ;
  218.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,4) | 0x10 ;
  219.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,5) | 0x20 ;
  220.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,6) | 0x40 ;
  221.     else                                col = Pi_getBit(buf,7) | 0x80 ;
  222.     
  223.     col &= 0xff;
  224.     
  225.     /* 色テーブルのシフト */
  226.     p   = ColTbl+ precol*256 + col ;
  227.     precol = *p;
  228.     
  229.     for( ; col ; col--,p-- )
  230.         *p = *(p-1);
  231.     *p = precol;
  232.     
  233.     return precol;
  234. }
  235.  
  236. int     Pi_getColor16( buf )
  237. char    *buf;
  238. {
  239.     register unsigned int     col;
  240.     char    *p;
  241.     
  242.          if( Pi_getBit(buf,1) == 1 )    col = Pi_getBit(buf,1)     ;
  243.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,1) | 2 ;
  244.     else if( Pi_getBit(buf,1) == 0 )    col = Pi_getBit(buf,2) | 4 ;
  245.     else                                 col = Pi_getBit(buf,3) | 8 ;
  246.     
  247.     /* 色テーブルのシフト */
  248.     
  249.     p   = ColTbl + precol*16 + col ;
  250.     precol = *p ;
  251.     for( ; col>0 ; col--,p-- )
  252.         *p = *(p-1);
  253.     *p = precol;
  254.     
  255.     return precol;
  256. }
  257.  
  258. void    Pi_initColorTable(col)
  259. int     col;
  260. {
  261.     int     i, j;
  262.     
  263.     for( i=0; i<col; i++ )
  264.         for( j=0; j<col; j++ )
  265.             ColTbl[ j + i*col ] = ((i + col-j) & (col-1));
  266.     
  267. }
  268. /*
  269.     0fedcba987654321
  270.     10fedcba98765432
  271.     210fedcba9876543
  272.       :
  273. */
  274.  
  275. /**************************************/
  276.  
  277.  
  278. int     Pi_readHeader( head, fp )
  279. PiHeader    *head;
  280. FILE        *fp;
  281. {
  282.     int     i=0;
  283.     
  284.     if( fgetc(fp)!= 'P' || fgetc(fp)!= 'i' )
  285.         return ERROR;
  286.     
  287.     while( fgetc(fp) != 0x1a && ferror(fp)==0 );
  288.     while( fgetc(fp) != 0x00 && ferror(fp)==0 );
  289.     if( ferror(fp) )    return ERROR;
  290.     
  291.     head->mode        = (char)fgetc( fp );
  292.     head->n            = (char)fgetc( fp );
  293.     head->m            = (char)fgetc( fp );
  294.     head->pix        = (char)fgetc( fp );
  295.     
  296.     fread( head->name ,1,4 ,fp );
  297.     
  298.     head->mdat_len    = (fgetc( fp )<<8) + (char)fgetc( fp );
  299.     for( i=0; i< head->mdat_len ; i++ )
  300.         fgetc( fp );
  301.     
  302.     head->x            = (short)(fgetc( fp )<<8 | (char)fgetc( fp ) );
  303.     head->y            = (short)(fgetc( fp )<<8 | (char)fgetc( fp ) );
  304.     
  305. //    printf("(x,y)=(%d,%d),pix=%d\r\n",head->x,head->y,head->pix);
  306.     
  307.     return ferror(fp);
  308. }
  309.  
  310.  
  311. long    getFileSize( fp )
  312. FILE    *fp;
  313. {
  314.     unsigned long    from,to;
  315.     
  316.     from = ftell(fp);
  317.     fseek( fp, 0, SEEK_END );
  318.     to = ftell(fp);
  319.     fseek( fp, from, SEEK_SET );
  320.     
  321.     return (to-from);
  322. }
  323.  
  324. /*******************************************************************/
  325.  
  326. void    Pi_setPalette( pal, col, fp )
  327. char    *pal;
  328. int     col;
  329. FILE    *fp;
  330. {
  331.     int     i,j;
  332.     
  333.     DWORD( pal ) = col;
  334.     for( i=0,j=4; i<col; i++,j+=8 )
  335.     {
  336.         WORD( pal+j ) = i ;
  337.         pal[ j+5 ] = (char)fgetc( fp );    /* R */
  338.         pal[ j+6 ] = (char)fgetc( fp );    /* G */
  339.         pal[ j+4 ] = (char)fgetc( fp );    /* B */
  340.     }
  341.     
  342. }
  343.  
  344. void Pi_setDefaultPalette( pal,col )
  345. char    *pal;
  346. int     col;
  347. {
  348.     int     i,j;
  349.     
  350.     DWORD( pal ) = col;
  351.     
  352.     if( col==16 )    /* TOWNSのdefaultと同じ */
  353.         for( i=0,j=4; i<16; i++,j+=8 )
  354.         {    WORD( pal+ j ) = (unsigned short)i;
  355.             
  356.             pal[ j+5 ] = (i & 2) * ( ((i & 8) | 7 )<<3 );
  357.             pal[ j+6 ] = (i & 4) * ( ((i & 8) | 7 )<<2 );
  358.             pal[ j+4 ] = (i & 1) * ( ((i & 8) | 7 )<<4 );
  359.         }
  360.     else            /* TOWNSのdefaultよりちょっと暗い */
  361.         for( i=0,j=4; i<256; i++,j+=8 )
  362.         {    WORD( pal+ j ) = (unsigned short)i;
  363.             
  364.             pal[ j+5 ] = (((i>>2 ) & 7) << 5);    /* R */
  365.             pal[ j+6 ] = (((i>>5 ) & 7) << 5);    /* G */
  366.             pal[ j+4 ] = (( i      & 3) << 6);    /* B */
  367.         }
  368.     
  369. }
  370.  
  371.  
  372.  
  373. /*******************************************************************/
  374. /**  プラグイン呼び出し **/
  375.  
  376. #define    FNAME    (pi_data->fname)
  377.  
  378. int APL_exec()
  379. {
  380.     FILE    *fp;
  381.     char    *buf,*mem,    *pal,*image;
  382.     int     col;
  383.     long     l;
  384.     PiHeader    head;
  385.     
  386.     if( (fp = fopen( FNAME , "rb" )) == NULL )
  387.         return PI_ERROR_FILE_OPEN;
  388.     
  389.     /** ヘッダ読み込み **/
  390.     if( Pi_readHeader( &head, fp ) )
  391.     {    fclose( fp );
  392.         return ERROR;
  393.     }
  394. //    printf("size=(%d,%d)", head.x, head.y );
  395.     
  396.     
  397.     if( head.pix > pi_imge->pix )        /* 減色処理などはしない */
  398.         return ERROR;
  399.     
  400.     if( head.pix < 8 )    col = 16;
  401.                 else    col = 256;
  402.     
  403.     /** パレット情報読み取り **/
  404.     if( (pal=(char*)PI_MALLOC( 4+col*8 ))==NULL )
  405.     {    fclose( fp );
  406.         return PI_ERROR_NO_MEMORY;
  407.     }
  408.     
  409.     if( head.mode & 0x80 )    /* パレットなし */
  410.         Pi_setDefaultPalette( pal,col );
  411.     else
  412.         Pi_setPalette( pal, col, fp );
  413.     
  414.     /***/
  415.     if( (l=getFileSize(fp))< 0
  416.         || (mem=(char *)PI_MALLOC( l + col*col ))==NULL )
  417.     {    fclose(fp);
  418.         PI_FREE( pal );
  419.         return PI_ERROR_NO_MEMORY;
  420.     }
  421.     buf    = mem;
  422.     ColTbl = mem+l;
  423.     Pi_initColorTable( col );
  424.     
  425.     if( fread( buf, 1, l, fp )< l )        /* 一気に読み込み */
  426.     {    fclose(fp);
  427.         PI_FREE( pal );
  428.         PI_FREE( mem );
  429.         return PI_ERROR_FILE_OPEN;
  430.     }
  431.     fclose( fp );
  432.     /***/
  433.     
  434.     Pi_maxBit = l*8;
  435.     
  436.     /***  展開用メモリ確保 **********************************************/
  437.     /* 16色モードの場合横16ドット単位、256色モードの場合横32ドット単位    */
  438.     /* でメモリを確保し、乙女座に渡さなくてはならない。                    */
  439.     /********************************************************************/
  440.     
  441.     /* 256色として展開する */
  442.     if( (image=PI_MALLOC( ((head.x+31) & 0xffe0) * (head.y+2)+32 ))==NULL )
  443.     {    
  444.         PI_FREE( pal );
  445.         PI_FREE( mem );
  446.         return PI_ERROR_NO_MEMORY;
  447.     }
  448. #if 1
  449.     /** データ展開 **/
  450.     if( Pi_decode( image, buf, &head ) )
  451.     {
  452.         PI_FREE( pal );
  453.         PI_FREE( mem );
  454.         
  455.         return ERROR;
  456.     }
  457. #endif
  458.     
  459.     PI_FREE(mem);
  460.     
  461.     pi_imge->image    = image;
  462.     pi_imge->clut    = pal;
  463.     pi_imge->pix    = head.pix;
  464.     pi_imge->size.x = head.x ;
  465.     pi_imge->size.y = head.y ;
  466.     
  467.     if( head.pix == 8 )    conv_vram256( image, &head );
  468.     if( head.pix == 4 )    conv_vram16 ( image, &head );
  469.     
  470.     return NOERR;
  471. }
  472.  
  473.  
  474.  
  475. /***** 展開したバッファを TOWNS の VRAM に合うよう変換する *****/
  476.  
  477. void conv_vram( image, head )
  478. char        *image;
  479. PiHeader    *head;
  480. {
  481.     int     Width = (head->x+31)& 0xffe0 ;
  482.     int     y;
  483.     char    *p = image + head->x * 2 ;
  484.     
  485.     for( y=head->y-1; y>0 ; y-=2 )
  486.     {    _rmemcpy( p+Width*(y  ), p+head->x*(y  ), head->x );
  487.         _rmemcpy( p+Width*(y-1), p+head->x*(y-1), head->x );
  488.     }
  489.     if( y==0 )
  490.         _rmemcpy( p+Width*(0  ), p+head->x*(0  ), head->x );
  491.     
  492. }
  493.  
  494. int conv_vram256( char *image,PiHeader *head )
  495. {
  496.     int     Width;
  497.     
  498.     Width = (head->x +31)& 0xffe0;    /* 256色の場合は32ドット単位 */
  499.     
  500.     if( Width != head->x )
  501.         conv_vram( image, head );
  502.     
  503.     /* 上 2 ラインは必要ない */
  504.     memcpy( image, image+(head->x*2), (Width*head->y) );
  505.     
  506.     return NOERR;
  507. }
  508.  
  509. int conv_vram16( char *image,PiHeader *head )
  510. {
  511.     int     x,y,Width;
  512.     char    *p,*pp;
  513.     
  514.     Width = (head->x+31)& 0xffe0;        /* 16色は横16ドット単位 */
  515.     
  516.     if( head->x != Width )
  517.         conv_vram( image, head );
  518.     
  519.     p = image + head->x*2 ;
  520.     pp= image ;
  521.     for( y=0 ; y<head->y ; y++ )
  522.     {    
  523.         for(x=0; x< Width ; x+=8 )        /* ループ展開すれば少しは速い? */
  524.         {    *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
  525.             *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
  526.             *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
  527.             *pp++ = (*p++ & 0x0f) | (*p++ & 0x0f)<<4 ;
  528.         }
  529.     }
  530.     return NOERR;
  531. }
  532.  
  533.