1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 	Macintosh interface for TiMidity
21 	by T.Nogami	<t-nogami@happy.email.ne.jp>
22 
23     mac_mag.c
24     Macintosh mag loader
25 */
26 
27 /*
28  *X mag loader By Takanori Watanabe. Based on Mac mag loader.
29  */
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif /* HAVE_CONFIG_H */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/param.h>
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39 #include "timidity.h"
40 #include "common.h"
41 #include "x_mag.h"
42 #include "controls.h"
43 #include "wrd.h"
44 #define BUFSIZE 512
45 static const char *MAGSIG="MAKI02  ";
46 
47 #define READSHORT(p) ((int)*(uint8*)((p)+1)*256+(int)*(uint8 *)(p))
48 #define READLONG(p) (\
49 		     (int)*(uint8*)((p)+3)*256*256*256+\
50 		     (int)*(uint8*)((p)+2)*256*256+\
51 		     (int)*(uint8*)((p)+1)*256+\
52 		     (int)*(uint8 *)(p)\
53 		     )
54 #define MAGHDRLEN 31
55 
56 static void mag_delete(magdata *mg);
57 
58 static magdata *top=NULL;
59 struct magfilehdr{
60   char machine;
61   char mflag;
62   char scrmode;
63   char xorig[2];
64   char yorig[2];
65   char xend[2];
66   char yend[2];
67   char flagaoff[4];
68   char flagboff[4];
69   char flagbsize[4];
70   char pxloff[4];
71   char pxlsize[4];
72 };
read_flag_1line(magdata * mh,uint8 * flag)73 static int read_flag_1line(magdata * mh,uint8 *flag )
74 {
75   int		x, flagA,flagB,j;
76   j=0;
77   for( x=0; x<=mh->xend-(mh->xorig/8*8); ){
78     flagA= mh->flagadata[mh->flagapos/8] & (0x80 >> (mh->flagapos & 0x07) );
79     mh->flagapos++;
80     if( flagA ){
81       flagB= mh->flagbdata[mh->flagbpos++];
82     }else{
83       flagB= 0;
84     }
85     flag[x] ^= flagB>>4;	 x+=4;j++;
86     flag[x] ^= flagB & 0x0F; x+=4;j++;
87   }
88   return j;
89 }
90 
91 /*This Function Requires Blank XImage*/
pho_load_pixel(XImage * image,XColor * pallet,char * filename)92 Bool pho_load_pixel(XImage *image,XColor *pallet,char *filename){
93   int i,j,k,l;
94   static const int shift[4]={0,2,1,3};/*B,R,G,E*/
95   struct timidity_file *fp;
96   char buffer[640/8];
97 
98   if((fp=wrd_open_file(filename))==NULL)
99     return False;
100   for(l=0;l<4;l++){
101     for(i=0;i<400;i++){
102       if(tf_read(buffer,sizeof(buffer),1,fp)==0){
103 	goto close;
104       }
105       for(j=0;j<sizeof(buffer);j++){
106 	for(k=0;k<8;k++)
107 	  if((buffer[j]<<k)&0x80)
108 	    XPutPixel(image,j*8+k,i,XGetPixel(image,j*8+k,i)
109 		      |pallet[1<<shift[l]].pixel);
110 	  else
111 	    XPutPixel(image,j*8+k,i,XGetPixel(image,j*8+k,i)
112 		      |pallet[0].pixel);
113       }
114     }
115   }
116  close:
117   close_file(fp);
118   return True;
119 }
120 
mag_load_pixel(XImage * image,XColor * pallet,magdata * mh)121 void mag_load_pixel(XImage *image,XColor *pallet,magdata *mh)
122 {
123   int 		x,y,i, dx,dy,pxlpos,w,j,repl;
124   uint8 flag[640];
125   long pixels;
126   const int	DX[]={0,-4,-8,-16,  0,-4,  0,-4,-8,  0,-4,-8,  0,-4,-8, 0},
127   DY[]={0, 0, 0,  0, -1,-1, -2,-2,-2, -4,-4,-4, -8,-8,-8, -16};
128   memset(flag,0,640);
129   mh->flagapos=mh->flagbpos=pxlpos=0;
130   w=image->width;
131   for( y=0; y<=mh->yend-mh->yorig; y++ ){
132     repl=read_flag_1line( mh,flag );
133     x=0;
134     for( j=0; j<repl; j++ ){
135       if( flag[x]==0 ){
136 	pixels=mh->pxldata[pxlpos]*256+mh->pxldata[pxlpos+1];
137 	pxlpos+=2;
138 	for( i=3; i>=0; i-- ){
139 	  if(x+i < w)
140 	    XPutPixel(image,x+i, y, pallet[pixels & 0x000F].pixel);
141 	  pixels >>= 4;
142 	}
143       } else {
144 	dx=DX[flag[x]];
145 	dy=DY[flag[x]];
146 	for(i=0;i<4;i++) {
147 	  if(x+i < w)
148 	    XPutPixel(image,x+i,y,XGetPixel(image,x+dx+i,y+dy));
149 	}
150       }
151       x+=4;
152     }
153   }
154 }
155 
mag_deletetab(void)156 void mag_deletetab(void)
157 {
158   if(top!=NULL){
159     mag_delete(top);
160   }
161   top=NULL;
162 }
mag_delete(magdata * mg)163 static void mag_delete(magdata *mg){
164   if(mg->next!=NULL)
165     mag_delete(mg->next);
166   free(mg->filename);
167   free(mg->flagadata);
168   free(mg->flagbdata);
169   free(mg->pxldata);
170   free(mg);
171 }
mag_search(char * filename)172 magdata *mag_search(char *filename)
173 {
174   magdata *m;
175   for(m=top;m!=NULL;m=m->next)
176     if(strcmp(filename,m->filename)==0)
177       return m;
178   return NULL;
179 }
mag_create(char * file)180 magdata *mag_create(char *file)
181 {
182 
183   struct timidity_file *fp=NULL;
184   int i;
185   uint8 buffer[BUFSIZE];
186   int *pal;
187   magdata mg,*res;
188   struct magfilehdr mfh;
189   int len,c,header_pos;
190   char *flaga=NULL,*flagb=NULL,*pixels=NULL;
191   if((res=mag_search(file))){
192     return res;
193   }
194   mg.filename=safe_malloc(strlen(file)+2);
195   strcpy(mg.filename,file);
196   fp=wrd_open_file(file);
197   if(fp==NULL){
198     goto error;
199   }
200   header_pos=0;
201   while((c=tf_getc(fp))!=0){
202     len=strlen(MAGSIG);
203     if(header_pos<len)
204       buffer[header_pos]=c;
205     else if(header_pos==len){
206       if(memcmp(MAGSIG,buffer,len)!=0){
207 	ctl->cmsg(CMSG_INFO,VERB_VERBOSE,"BAD SIGNATURE\n");
208 	goto error;
209       }
210     }
211     header_pos++;
212   }
213   /*READ FHDR*/
214   {
215     if(tf_read(&mfh,sizeof(mfh),1,fp)==0){
216       fprintf(stderr,"FOO!\n");
217       goto error;
218     }
219     mg.machine=mfh.machine;
220     mg.mflag=mfh.mflag;
221     mg.scrmode=mfh.scrmode;
222     mg.xorig=READSHORT(mfh.xorig);
223     mg.yorig=READSHORT(mfh.yorig);
224     mg.xend=READSHORT(mfh.xend);
225     mg.yend=READSHORT(mfh.yend);
226     mg.flagaoff=READLONG(mfh.flagaoff);
227     mg.flagboff=READLONG(mfh.flagboff);
228     mg.flagbsize=READLONG(mfh.flagbsize);
229     mg.pxloff=READLONG(mfh.pxloff);
230     mg.pxlsize=READLONG(mfh.pxlsize);
231   }
232   /*READ PALLET*/
233   pal=mg.pal+1;
234   for(i=0;i<PALSIZE;i++){
235     if(tf_read(buffer,1,3,fp)<3){
236       exit(-1);
237     }
238 #if 0
239     pal[i]=buffer[0]/16+buffer[1]/16*256+buffer[2]/16*16;
240 #else
241     pal[i]=buffer[0]/16*16+buffer[1]/16*256+buffer[2]/16;
242 #endif
243   }
244 
245   {
246     int flaga_size,res;
247     flaga_size=mg.flagboff-mg.flagaoff;
248     if(tf_seek(fp,mg.flagaoff+header_pos,SEEK_SET)==-1)
249       goto error;
250     flaga=safe_malloc(flaga_size+100);
251     if((res=tf_read(flaga,1,flaga_size,fp))<flaga_size)
252       goto error;
253     mg.flagadata=flaga;
254   }
255   {
256     flagb=safe_malloc(mg.flagbsize+100);
257     if(tf_seek(fp,mg.flagboff+header_pos,SEEK_SET)==-1)
258       goto error;
259     if(tf_read(flagb,1,mg.flagbsize,fp)<mg.flagbsize)
260       goto error;
261     mg.flagbdata=flagb;
262   }
263   {
264     pixels=safe_malloc(mg.pxlsize+100);
265     if(tf_seek(fp,mg.pxloff+header_pos,SEEK_SET)==-1)
266       goto error;
267     if(tf_read(pixels,1,mg.pxlsize,fp)<mg.pxlsize)
268       goto error;
269     mg.pxldata=pixels;
270   }
271   res=safe_malloc(sizeof(magdata));
272 
273   *res=mg;
274   close_file(fp);
275   res->next=top;
276   top=res;
277   return res;
278  error:
279   if(fp!=NULL)
280   {
281     close_file(fp);
282     ctl->cmsg(CMSG_INFO,VERB_VERBOSE,"Mag error: %s\n", file);
283   }
284   free(mg.filename);
285   if(flaga != NULL)
286       free(flaga);
287   if(flagb != NULL)
288       free(flagb);
289   if(pixels != NULL)
290       free(pixels);
291   return NULL;
292 }
293