ocp-0.1.21/0000755000175000001440000000000011655541771011425 5ustar stianusersocp-0.1.21/playogg/0000755000175000001440000000000011655541750013064 5ustar stianusersocp-0.1.21/playogg/oggplay.h0000644000175000001440000000213611655541726014704 0ustar stianusers#ifndef __OGG_H #define __OGG_H struct ogginfo { uint32_t pos; uint32_t len; uint32_t rate; uint8_t stereo; uint8_t bit16; int bitrate; }; extern int __attribute__ ((visibility ("internal"))) oggOpenPlayer(FILE *); extern void __attribute__ ((visibility ("internal"))) oggClosePlayer(void); extern void __attribute__ ((visibility ("internal"))) oggIdle(void); extern void __attribute__ ((visibility ("internal"))) oggSetLoop(uint8_t s); extern char __attribute__ ((visibility ("internal"))) oggLooped(void); extern void __attribute__ ((visibility ("internal"))) oggPause(uint8_t p); extern void __attribute__ ((visibility ("internal"))) oggSetAmplify(uint32_t amp); extern void __attribute__ ((visibility ("internal"))) oggSetSpeed(uint16_t sp); extern void __attribute__ ((visibility ("internal"))) oggSetVolume(uint8_t vol, int8_t bal, int8_t pan, uint8_t opt); extern void __attribute__ ((visibility ("internal"))) oggGetInfo(struct ogginfo *); extern uint32_t __attribute__ ((visibility ("internal"))) oggGetPos(void); extern void __attribute__ ((visibility ("internal"))) oggSetPos(uint32_t pos); #endif ocp-0.1.21/playogg/oggplay.c0000644000175000001440000004062711655541726014706 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * OGGPlay - Player for Ogg Vorbis files * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb040911 Stian Skjelstad * -first release * -ss040916 Stian Skjelstad * -fixed problem regarding random-sound in the first buffer-run * -ss040916 Stian Skjelstad * -fixed the signess problem around PANPROC */ #include "config.h" #include #include #include #include #include #include "types.h" #include "stuff/imsrtns.h" #include "stuff/timer.h" #include "stuff/poll.h" #include "dev/player.h" #include "dev/deviplay.h" #include "dev/plrasm.h" #include "oggplay.h" static int current_section; static int stereo; /* 32 bit booleans are fast */ static int bit16; static int signedout; static uint32_t samprate; static uint8_t reversestereo; /* static unsigned long amplify; TODO */ static unsigned long voll,volr; static int pan; static int srnd; static uint16_t *buf16=NULL; static uint32_t bufpos; static uint32_t buflen; static void *plrbuf; /*static uint32_t amplify;*/ static OggVorbis_File ov; static int oggstereo; static int oggrate; static uint32_t oggpos; static uint32_t ogglen; static uint8_t *oggbuf=NULL; static uint32_t oggbuflen; static uint32_t oggbufpos; static uint32_t oggbuffpos; static int32_t oggbufread; static uint32_t oggbufrate; static int active; static int looped; static int donotloop; static uint32_t bufloopat; static int inpause; static volatile int clipbusy=0; #define PANPROC \ do { \ float _rs = rs, _ls = ls; \ if(pan==-64) \ { \ float t=_ls; \ _ls = _rs; \ _rs = t; \ } else if(pan==64) \ { \ } else if(pan==0) \ _rs=_ls=(_rs+_ls) / 2.0; \ else if(pan<0) \ { \ _ls = _ls / (-pan/-64.0+2.0) + _rs*(64.0+pan)/128.0; \ _rs = _rs / (-pan/-64.0+2.0) + _ls*(64.0+pan)/128.0; \ } else if(pan<64) \ { \ _ls = _ls / (pan/-64.0+2.0) + _rs*(64.0-pan)/128.0; \ _rs = _rs / (pan/-64.0+2.0) + _ls*(64.0-pan)/128.0; \ } \ rs = _rs * volr / 256.0; \ ls = _ls * voll / 256.0; \ } while(0) static void oggIdler(void) { size_t clean; if ((ogglen==oggbuflen)||!active) return; clean=(oggbufpos+oggbuflen-oggbufread)%oggbuflen; if (clean<8) return; clean-=8; while (clean) { size_t read=clean; long result; if ((ov_pcm_tell(&ov)<<(1+oggstereo))!=oggpos) #ifdef HAVE_OV_PCM_SEEK_LAP ov_pcm_seek_lap(&ov, oggpos>>(1+oggstereo)); #else ov_pcm_seek(&ov, oggpos>>(1+oggstereo)); #endif if ((oggbufread+read)>oggbuflen) read=oggbuflen-oggbufread; if ((oggpos+read)>=ogglen) { read=ogglen-oggpos; bufloopat=oggbufread+read; } if (read>0x10000) read=0x10000; #ifndef WORDS_BIGENDIAN result=ov_read(&ov, (char *)oggbuf+oggbufread, read, 0, 2, 1, ¤t_section); #else result=ov_read(&ov, (char *)oggbuf+oggbufread, read, 1, 2, 1, ¤t_section); #endif if (result<=0) /* broken data... we can survive */ { memsetw(oggbuf+oggbufread, (uint16_t)0x8000, read>>1); result=read; } else { int16_t rs, ls; int samples=result>>1; int16_t *buffer=(int16_t *)(oggbuf+oggbufread); if (oggstereo) { samples>>=1; while (samples) { rs=buffer[0]; ls=buffer[1]; PANPROC; buffer[0]=rs; if (srnd) buffer[1]=ls^0xffff; else buffer[1]=ls; samples--; buffer+=2; } } else while (samples) { rs=buffer[0]; ls=buffer[0]; PANPROC; buffer[0]=((rs+ls)>>1); samples--; buffer++; } } oggbufread=(oggbufread+result)%oggbuflen; oggpos=(oggpos+result)%ogglen; clean-=result; } } void __attribute__ ((visibility ("internal"))) oggIdle(void) { uint32_t bufplayed; uint32_t bufdelta; uint32_t pass2; int quietlen=0; uint32_t toloop; if (clipbusy++) { clipbusy--; return; } bufplayed=plrGetBufPos()>>(stereo+bit16); bufdelta=(buflen+bufplayed-bufpos)%buflen; if (!bufdelta) { clipbusy--; if (plrIdle) plrIdle(); return; } oggIdler(); if (oggbuflen!=ogglen) { uint32_t towrap=imuldiv((((oggbuflen+oggbufread-oggbufpos-1)%oggbuflen)>>(oggstereo+1)), 65536, oggbufrate); if (bufdelta>towrap) /*quietlen=bufdelta-towrap;*/ bufdelta=towrap; } if (inpause) quietlen=bufdelta; toloop=imuldiv(((bufloopat-oggbufpos)>>(1+oggstereo)), 65536, oggbufrate); if (looped) toloop=0; bufdelta-=quietlen; if (bufdelta>=toloop) { looped=1; if (donotloop) { quietlen+=bufdelta-toloop; bufdelta=toloop; } } if (bufdelta) { uint32_t i; if (oggbufrate==0x10000) { if (oggstereo) { uint32_t o=0; while (o>2; oggbufpos+=w; if (oggbufpos>=oggbuflen) oggbufpos-=oggbuflen; } } else { uint32_t o=0; while (o>1; oggbufpos+=w; if (oggbufpos>=oggbuflen) oggbufpos-=oggbuflen; } } } else if (oggstereo) { int32_t oggm1, c0, c1, c2, c3, ls, rs, vm1,v1,v2; uint32_t ogg1, ogg2; for (i=0; i=oggbuflen) ogg1-=oggbuflen; ogg2=oggbufpos+8; if (ogg2>=oggbuflen) ogg2-=oggbuflen; c0 = *(uint16_t *)(oggbuf+oggbufpos)^0x8000; vm1= *(uint16_t *)(oggbuf+oggm1)^0x8000; v1 = *(uint16_t *)(oggbuf+ogg1)^0x8000; v2 = *(uint16_t *)(oggbuf+ogg2)^0x8000; c1 = v1-vm1; c2 = 2*vm1-2*c0+v1-v2; c3 = c0-vm1-v1+v2; c3 = imulshr16(c3,oggbuffpos); c3 += c2; c3 = imulshr16(c3,oggbuffpos); c3 += c1; c3 = imulshr16(c3,oggbuffpos); ls = c3+c0; if (ls<0) ls=0; if (ls>65535) ls=65535; c0 = *(uint16_t *)(oggbuf+oggbufpos+2)^0x8000; vm1= *(uint16_t *)(oggbuf+oggm1+2)^0x8000; v1 = *(uint16_t *)(oggbuf+ogg1+2)^0x8000; v2 = *(uint16_t *)(oggbuf+ogg2+2)^0x8000; c1 = v1-vm1; c2 = 2*vm1-2*c0+v1-v2; c3 = c0-vm1-v1+v2; c3 = imulshr16(c3,oggbuffpos); c3 += c2; c3 = imulshr16(c3,oggbuffpos); c3 += c1; c3 = imulshr16(c3,oggbuffpos); rs = c3+c0; if (rs<0) rs=0; if (rs>65535) rs=65535; buf16[2*i]=(uint16_t)ls^0x8000; buf16[2*i+1]=(uint16_t)rs^0x8000; oggbuffpos+=oggbufrate; oggbufpos+=(oggbuffpos>>16)*4; oggbuffpos&=0xFFFF; if (oggbufpos>=oggbuflen) oggbufpos-=oggbuflen; } } else { int32_t oggm1, c0, c1, c2, c3, vm1,v1,v2; uint32_t ogg1, ogg2; for (i=0; i=oggbuflen) ogg1-=oggbuflen; ogg2=oggbufpos+4; if (ogg2>=oggbuflen) ogg2-=oggbuflen; c0 = *(uint16_t *)(oggbuf+oggbufpos)^0x8000; vm1= *(uint16_t *)(oggbuf+oggm1)^0x8000; v1 = *(uint16_t *)(oggbuf+ogg1)^0x8000; v2 = *(uint16_t *)(oggbuf+ogg2)^0x8000; c1 = v1-vm1; c2 = 2*vm1-2*c0+v1-v2; c3 = c0-vm1-v1+v2; c3 = imulshr16(c3,oggbuffpos); c3 += c2; c3 = imulshr16(c3,oggbuffpos); c3 += c1; c3 = imulshr16(c3,oggbuffpos); c3 += c0; if (c3<0) c3=0; if (c3>65535) c3=65535; buf16[i]=(uint16_t)c3^0x8000; oggbuffpos+=oggbufrate; oggbufpos+=(oggbuffpos>>16)*2; oggbuffpos&=0xFFFF; if (oggbufpos>=oggbuflen) oggbufpos-=oggbuflen; } } if ((bufpos+bufdelta)>buflen) pass2=bufpos+bufdelta-buflen; else pass2=0; bufdelta-=pass2; if (bit16) { if (stereo) { if (reversestereo) { int16_t *p=(int16_t *)plrbuf+2*bufpos; int16_t *b=(int16_t *)buf16; if (signedout) { for (i=0; i=buflen) bufpos-=buflen; } bufdelta=quietlen; if (bufdelta) { if ((bufpos+bufdelta)>buflen) pass2=bufpos+bufdelta-buflen; else pass2=0; if (bit16) { plrClearBuf((uint16_t *)plrbuf+(bufpos<=buflen) bufpos-=buflen; } plrAdvanceTo(bufpos<<(stereo+bit16)); if (plrIdle) plrIdle(); clipbusy--; } void __attribute__ ((visibility ("internal"))) oggSetAmplify(uint32_t amp) { /* amplify=amp; float v[9]; float ampf=(float)vols[9]*(amplify/65536.0)/65536.0; int i; for (i=0; i<9; i++) v[i]=ampf*vols[i]; rawogg.ioctl(ampegdecoder::ioctlsetstereo, v, 4*9); */ } static int close_func(void *datasource) { return 0; } int __attribute__ ((visibility ("internal"))) oggOpenPlayer(FILE *oggf) { struct vorbis_info *vi; if (!plrPlay) return 0; fseek(oggf, 0, SEEK_SET); if(ov_open(oggf, &ov, NULL, -1) < 0) return -1; /* we don't bother to do more exact */ ov.callbacks.close_func=close_func; vi=ov_info(&ov,-1); oggstereo=vi->channels>=2; oggrate=vi->rate; plrSetOptions(oggrate, (PLR_SIGNEDOUT|PLR_16BIT)|((oggstereo)?PLR_STEREO:0)); stereo=!!(plrOpt&PLR_STEREO); bit16=!!(plrOpt&PLR_16BIT); signedout=!!(plrOpt&PLR_SIGNEDOUT); reversestereo=!!(plrOpt&PLR_REVERSESTEREO); samprate=plrRate; oggbufrate=imuldiv(65536, oggrate, samprate); ogglen=ov_pcm_total(&ov, -1)<<(1+oggstereo); if (!ogglen) return 0; oggbuflen=16384; if (oggbuflen>ogglen) { oggbuflen=ogglen; bufloopat=oggbuflen; } else bufloopat=0x40000000; oggbuf=malloc(oggbuflen); if (!oggbuf) return 0; ogglen=ogglen&~((1<<(oggstereo+1))-1); oggbufpos=0; oggbuffpos=0; current_section=0; #ifdef WORDS_BIGENDIAN if ((oggbufread=oggpos=ov_read(&ov, (char *)oggbuf, oggbuflen, 1, 2, 1, ¤t_section))<0) #else if ((oggbufread=oggpos=ov_read(&ov, (char *)oggbuf, oggbuflen, 0, 2, 1, ¤t_section))<0) #endif oggbufread=oggpos=0; if (!plrOpenPlayer(&plrbuf, &buflen, plrBufSize)) return 0; inpause=0; looped=0; voll=256; volr=256; pan=64; srnd=0; oggSetVolume(64, 0, 64, 0); /* oggSetAmplify(amplify); TODO */ buf16=malloc(sizeof(uint16_t)*buflen*2); if (!buf16) { plrClosePlayer(); free(oggbuf); return 0; } bufpos=0; if (!pollInit(oggIdle)) { plrClosePlayer(); return 0; } active=1; return 1; } void __attribute__ ((visibility ("internal"))) oggClosePlayer(void) { active=0; pollClose(); plrClosePlayer(); free(oggbuf); free(buf16); oggbuf=NULL; buf16=NULL; ov_clear(&ov); } char __attribute__ ((visibility ("internal"))) oggLooped(void) { return looped; } void __attribute__ ((visibility ("internal"))) oggSetLoop(uint8_t s) { donotloop=!s; } void __attribute__ ((visibility ("internal"))) oggPause(uint8_t p) { inpause=p; } void __attribute__ ((visibility ("internal"))) oggSetSpeed(uint16_t sp) { if (sp<32) sp=32; oggbufrate=imuldiv(256*sp, oggrate, samprate); } void __attribute__ ((visibility ("internal"))) oggSetVolume(uint8_t vol_, int8_t bal_, int8_t pan_, uint8_t opt) { pan=pan_; volr=voll=vol_*4; if (bal_<0) volr=(volr*(64+bal_))>>6; else voll=(voll*(64-bal_))>>6; srnd=opt; } uint32_t __attribute__ ((visibility ("internal"))) oggGetPos(void) { if (ogglen==oggbuflen) return oggbufpos>>(oggstereo+1); else return ((oggpos+ogglen-oggbuflen+((oggbufpos-oggbufread+oggbuflen)%oggbuflen))%ogglen)>>(oggstereo+1); } void __attribute__ ((visibility ("internal"))) oggGetInfo(struct ogginfo *i) { static int lastsafe=0; i->pos=oggGetPos(); i->len=ogglen>>(oggstereo+1); i->rate=oggrate; i->stereo=oggstereo; i->bit16=1; if ((i->bitrate=ov_bitrate_instant(&ov))<0) i->bitrate=lastsafe; else lastsafe=i->bitrate; i->bitrate/=1000; } void __attribute__ ((visibility ("internal"))) oggSetPos(uint32_t pos) { pos=((pos<<(1+oggstereo))+ogglen)%ogglen; if (ogglen==oggbuflen) oggbufpos=pos; else { if (((pos+oggbuflen)>oggpos)&&(pos * * OGGPlay file type detection routines for fileselector * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040911 Stian Skjelstad * -first release */ #include "config.h" #include #include #include #include "types.h" #include "filesel/mdb.h" /* try to ignore utf8-characters... */ static char *_strncpy(char *dest, const char *src, size_t n) { while (n) { if (*src&0x80) { src++; continue; } *dest=*src; n--; if (!*src) break; src++; dest++; } return dest; } static int oggReadMemInfo(struct moduleinfostruct *m, const char *buf, size_t len) { uint8_t offset; uint32_t length; uint32_t count; const char *ptr; unsigned int i; char const *bufend=buf+len; if (len<35) return 0; /* OggS Ogg data header */ if (*(uint32_t*)buf!=int32_little(0x5367674f)) return 0; /* Vorbis audio ? */ if ( (*(uint32_t*)(buf+28)!=int32_little(0x726f7601)) || (*(uint16_t *)(buf+32)!=int16_little(0x6962)) || (*(uint8_t *)(buf+34)!=0x73)) return 0; m->modtype=mtOGG; if (len<85) return 1; offset=((uint8_t *)buf)[84]; /* This is for sure an Ogg Vorbis sound stream */ ptr=(char *)buf+offset+85; if ((ptr+7)>bufend) return 1; if (strncmp(ptr, "\003vorbis", 7)) return 1; ptr+=7; if ((ptr+4)>bufend) return 1; length=int32_little(*(uint32_t *)ptr); ptr+=length+sizeof(uint32_t); if ((ptr+4)>bufend) return 1; count=int32_little(*(uint32_t *)ptr); ptr+=sizeof(uint32_t); for (i=0;ibufend) return 1; length=int32_little(*(uint32_t *)ptr); if ((ptr+4+length)>bufend) return 1; ptr+=sizeof(uint32_t); if(!strncasecmp(ptr, "title=", 6)) { unsigned int len=length-6; if (len>(sizeof(m->modname)-1)) len=sizeof(m->modname)-1; _strncpy(m->modname, ptr+6, len); m->modname[len]=0; } else if(!strncasecmp(ptr, "artist=", 7)) { unsigned int len=length-7; if (len>(sizeof(m->composer)-1)) len=sizeof(m->composer)-1; _strncpy(m->composer, ptr+7, len); m->composer[len]=0; } else if(!strncasecmp(ptr, "album=", 6)) { unsigned int len=length-6; if (len>(sizeof(m->comment)-1)) len=sizeof(m->comment)-1; _strncpy(m->comment, ptr+6, len); m->comment[len]=0; } ptr+=length; } return 1; } static int oggReadInfo(struct moduleinfostruct *m, FILE *f, const char *buf, size_t len) { return oggReadMemInfo(m, buf, len); } struct mdbreadinforegstruct oggReadInfoReg = {oggReadMemInfo, oggReadInfo, 0 MDBREADINFOREGSTRUCT_TAIL}; ocp-0.1.21/playogg/oggpplay.c0000644000175000001440000003373011655541726015063 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * OGGPlay interface routines * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040911 Stian Skjelstad * -first release * -ss040918 Stian Skjelstad * -added fade pause */ #include "config.h" #include #include #include #include #include #include "types.h" #include "filesel/pfilesel.h" #include "filesel/mdb.h" #include "stuff/poutput.h" #include "dev/player.h" #include "boot/plinkman.h" #include "boot/psetting.h" #include "stuff/sets.h" #include "stuff/compat.h" #include "stuff/err.h" #include "dev/deviplay.h" #include "cpiface/cpiface.h" #include "oggplay.h" #define _MAX_FNAME 8 #define _MAX_EXT 4 static FILE *oggfile; static uint32_t ogglen; static uint32_t oggrate; static uint32_t starttime; static uint32_t pausetime; static char currentmodname[_MAX_FNAME+1]; static char currentmodext[_MAX_EXT+1]; static char *modname; static char *composer; static int16_t vol; static int16_t bal; static int16_t pan; static char srnd; static uint32_t amp; static int16_t speed; static int16_t reverb; static int16_t chorus; static char finespeed=8; /* static char *membuf; this could be done with mmap magic */ static uint32_t pausefadestart; static uint8_t pausefaderelspeed; static int8_t pausefadedirect; static void startpausefade(void) { if (plPause) starttime=starttime+dos_clock()-pausetime; if (pausefadedirect) { if (pausefadedirect<0) plPause=1; pausefadestart=2*dos_clock()-DOS_CLK_TCK-pausefadestart; } else pausefadestart=dos_clock(); if (plPause) { plChanChanged=1; oggPause(plPause=0); pausefadedirect=1; } else pausefadedirect=-1; } static void dopausefade(void) { int16_t i; if (pausefadedirect>0) { i=((int32_t)dos_clock()-pausefadestart)*64/DOS_CLK_TCK; if (i<0) i=0; if (i>=64) { i=64; pausefadedirect=0; } } else { i=64-((int32_t)dos_clock()-pausefadestart)*64/DOS_CLK_TCK; if (i>=64) i=64; if (i<=0) { i=0; pausefadedirect=0; pausetime=dos_clock(); oggPause(plPause=1); plChanChanged=1; oggSetSpeed(speed); return; } } pausefaderelspeed=i; oggSetSpeed(speed*i/64); } static void oggDrawGStrings(uint16_t (*buf)[CONSOLE_MAX_X]) { struct ogginfo inf; uint32_t tim; int l; int p; oggGetInfo(&inf); tim=inf.len/inf.rate; l=(inf.len>>(10-inf.stereo-inf.bit16)); p=(inf.pos>>(10-inf.stereo-inf.bit16)); if (plScrWidth<128) { memset(buf[0]+80, 0, (plScrWidth-80)*sizeof(uint16_t)); memset(buf[1]+80, 0, (plScrWidth-80)*sizeof(uint16_t)); memset(buf[2]+80, 0, (plScrWidth-80)*sizeof(uint16_t)); writestring(buf[0], 0, 0x09, " vol: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 15); writestring(buf[0], 15, 0x09, " srnd: \xfa pan: l\xfa\xfa\xfam\xfa\xfa\xfar bal: l\xfa\xfa\xfam\xfa\xfa\xfar ", 41); writestring(buf[0], 56, 0x09, " spd: ---% \x1D ptch: ---% ", 24); writestring(buf[0], 6, 0x0F, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", (vol+4)>>3); writestring(buf[0], 22, 0x0F, srnd?"x":"o", 1); if (((pan+70)>>4)==4) writestring(buf[0], 34, 0x0F, "m", 1); else { writestring(buf[0], 30+((pan+70)>>4), 0x0F, "r", 1); writestring(buf[0], 38-((pan+70)>>4), 0x0F, "l", 1); } writestring(buf[0], 46+((bal+70)>>4), 0x0F, "I", 1); _writenum(buf[0], 62, 0x0F, speed*100/256, 10, 3); _writenum(buf[0], 75, 0x0F, speed*100/256, 10, 3); writestring(buf[1], 57, 0x09, "amp: ...% filter: ... ", 23); _writenum(buf[1], 62, 0x0F, amp*100/64, 10, 3); writestring(buf[1], 75, 0x0F, "off", 3); writestring(buf[1], 0, 0x09, " pos: ...% / ......k size: ......k len: ..:..", 57); _writenum(buf[1], 7, 0x0F, p*100/l, 10, 3); writenum(buf[1], 43, 0x0F, (tim/60)%60, 10, 2, 1); writestring(buf[1], 45, 0x0F, ":", 1); writenum(buf[1], 46, 0x0F, tim%60, 10, 2, 0); writenum(buf[1], 29, 0x0F, l, 10, 6, 1); writenum(buf[1], 14, 0x0F, p, 10, 6, 1); if (plPause) tim=(pausetime-starttime)/DOS_CLK_TCK; else tim=(dos_clock()-starttime)/DOS_CLK_TCK; writestring(buf[2], 0, 0x09, " ogg \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa: ............................... time: ..:.. ", 80); writestring(buf[2], 8, 0x0F, currentmodname, _MAX_FNAME); writestring(buf[2], 16, 0x0F, currentmodext, _MAX_EXT); writestring(buf[2], 22, 0x0F, modname, 31); if (plPause) writestring(buf[2], 57, 0x0C, " paused ", 8); else { writestring(buf[2], 57, 0x09, "kbps: ", 6); writenum(buf[2], 63, 0x0F, inf.bitrate, 10, 3, 1); } writenum(buf[2], 74, 0x0F, (tim/60)%60, 10, 2, 1); writestring(buf[2], 76, 0x0F, ":", 1); writenum(buf[2], 77, 0x0F, tim%60, 10, 2, 0); } else { memset(buf[0]+128, 0, (plScrWidth-128)*sizeof(uint16_t)); memset(buf[1]+128, 0, (plScrWidth-128)*sizeof(uint16_t)); memset(buf[2]+128, 0, (plScrWidth-128)*sizeof(uint16_t)); writestring(buf[0], 0, 0x09, " volume: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 30); writestring(buf[0], 30, 0x09, " surround: \xfa panning: l\xfa\xfa\xfa\xfa\xfa\xfa\xfam\xfa\xfa\xfa\xfa\xfa\xfa\xfar balance: l\xfa\xfa\xfa\xfa\xfa\xfa\xfam\xfa\xfa\xfa\xfa\xfa\xfa\xfar ", 72); writestring(buf[0], 102, 0x09, " speed: ---% \x1D pitch: ---% ", 30); writestring(buf[0], 12, 0x0F, "\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe", (vol+2)>>2); writestring(buf[0], 41, 0x0F, srnd?"x":"o", 1); if (((pan+68)>>3)==8) writestring(buf[0], 62, 0x0F, "m", 1); else { writestring(buf[0], 54+((pan+68)>>3), 0x0F, "r", 1); writestring(buf[0], 70-((pan+68)>>3), 0x0F, "l", 1); } writestring(buf[0], 83+((bal+68)>>3), 0x0F, "I", 1); _writenum(buf[0], 110, 0x0F, speed*100/256, 10, 3); _writenum(buf[0], 124, 0x0F, speed*100/256, 10, 3); writestring(buf[1], 0, 0x09, " position: ...% / ......k size: ......k length: ..:.. opt: .....Hz, .. bit, ......", 92); _writenum(buf[1], 14, 0x0F, p*100/l, 10, 3); writenum(buf[1], 53, 0x0F, (tim/60)%60, 10, 2, 1); writestring(buf[1], 55, 0x0F, ":", 1); writenum(buf[1], 56, 0x0F, tim%60, 10, 2, 0); writenum(buf[1], 36, 0x0F, l, 10, 6, 1); writenum(buf[1], 21, 0x0F, p, 10, 6, 1); writenum(buf[1], 65, 0x0F, inf.rate, 10, 5, 1); writenum(buf[1], 74, 0x0F, 8<', "Jump forward (big)"); cpiKeyHelp(KEY_CTRL_RIGHT, "Jump forward (big)"); cpiKeyHelp(KEY_CTRL_UP, "Jump back (small)"); cpiKeyHelp(KEY_CTRL_DOWN, "Jump forward (small)"); cpiKeyHelp('-', "Decrease volume (small)"); cpiKeyHelp('+', "Increase volume (small)"); cpiKeyHelp('/', "Move balance left (small)"); cpiKeyHelp('*', "Move balance right (small)"); cpiKeyHelp(',', "Move panning against normal (small)"); cpiKeyHelp('.', "Move panning against reverse (small)"); cpiKeyHelp(KEY_F(2), "Decrease volume"); cpiKeyHelp(KEY_F(3), "Increase volume"); cpiKeyHelp(KEY_F(4), "Toggle surround on/off"); cpiKeyHelp(KEY_F(5), "Move panning against normal"); cpiKeyHelp(KEY_F(6), "Move panning against reverse"); cpiKeyHelp(KEY_F(7), "Move balance left"); cpiKeyHelp(KEY_F(8), "Move balance right"); cpiKeyHelp(KEY_F(9), "Decrease pitch speed"); cpiKeyHelp(KEY_F(11), "Decrease pitch speed"); cpiKeyHelp(KEY_F(10), "Increase pitch speed"); cpiKeyHelp(KEY_F(12), "Increase pitch speed"); if (plrProcessKey) plrProcessKey(key); return 0; case 'p': case 'P': startpausefade(); break; case KEY_CTRL_P: pausefadedirect=0; if (plPause) starttime=starttime+dos_clock()-pausetime; else pausetime=dos_clock(); plPause=!plPause; oggPause(plPause); break; case KEY_CTRL_UP: /* case 0x8D00: //ctrl-up */ oggSetPos(oggGetPos()-oggrate); break; case KEY_CTRL_DOWN: /* case 0x9100: //ctrl-down */ oggSetPos(oggGetPos()+oggrate); break; case '<': case KEY_CTRL_LEFT: /* case 0x7300: //ctrl-left */ oggSetPos(oggGetPos()-(ogglen>>5)); break; case '>': case KEY_CTRL_RIGHT: /* case 0x7400: //ctrl-right */ oggSetPos(oggGetPos()+(ogglen>>5)); break; /* case 0x7700: //ctrl-home TODO keys oggSetPos(0); break; */ case '-': if (vol>=2) vol-=2; oggSetVolume(vol, bal, pan, srnd); break; case '+': if (vol<=62) vol+=2; oggSetVolume(vol, bal, pan, srnd); break; case '/': if ((bal-=4)<-64) bal=-64; oggSetVolume(vol, bal, pan, srnd); break; case '*': if ((bal+=4)>64) bal=64; oggSetVolume(vol, bal, pan, srnd); break; case ',': if ((pan-=4)<-64) pan=-64; oggSetVolume(vol, bal, pan, srnd); break; case '.': if ((pan+=4)>64) pan=64; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(2): if ((vol-=8)<0) vol=0; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(3): if ((vol+=8)>64) vol=64; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(4): oggSetVolume(vol, bal, pan, srnd=srnd?0:2); break; case KEY_F(5): if ((pan-=16)<-64) pan=-64; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(6): if ((pan+=16)>64) pan=64; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(7): if ((bal-=16)<-64) bal=-64; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(8): if ((bal+=16)>64) bal=64; oggSetVolume(vol, bal, pan, srnd); break; case KEY_F(9): case KEY_F(11): if ((speed-=finespeed)<16) speed=16; oggSetSpeed(speed); break; case KEY_F(10): case KEY_F(12): if ((speed+=finespeed)>2048) speed=2048; oggSetSpeed(speed); break; /* case 0x5f00: // ctrl f2 TODO keys if ((amp-=4)<4) amp=4; oggSetAmplify(1024*amp); break; case 0x6000: // ctrl f3 TODO keys if ((amp+=4)>508) amp=508; oggSetAmplify(1024*amp); break; case 0x8900: // ctrl f11 TODO keys finespeed=(finespeed==8)?1:8; break; case 0x6a00: // alt f3 TODO keys normalize(); break; case 0x6900: // alt f2 TODO keys set.pan=pan; set.bal=bal; set.vol=vol; set.speed=speed; set.amp=amp; set.srnd=srnd; break; case 0x6b00: // alt f3 TODO keys pan=64; bal=0; vol=64; speed=256; amp=64; oggSetVolume(vol, bal, pan, srnd); oggSetSpeed(speed); oggSetAmplify(1024*amp); break; */ default: if (plrProcessKey) { int ret=plrProcessKey(key); if (ret==2) cpiResetScreen(); if (ret) return 1; } return 0; } return 1; } static int oggIsLooped(void) { if (pausefadedirect) dopausefade(); oggSetLoop(fsLoopMods); oggIdle(); if (plrIdle) plrIdle(); return !fsLoopMods&&oggLooped(); } static void oggCloseFile(void) { oggClosePlayer(); } static int oggOpenFile(const char *path, struct moduleinfostruct *info, FILE *oggf) { char _modname[NAME_MAX+1]; char _modext[NAME_MAX+1]; struct ogginfo inf; if (!oggf) return -1; _splitpath(path, 0, 0, _modname, _modext); strncpy(currentmodname, _modname, _MAX_FNAME); _modname[_MAX_FNAME]=0; strncpy(currentmodext, _modext, _MAX_EXT); _modext[_MAX_EXT]=0; modname=info->modname; composer=info->composer; fprintf(stderr, "loading %s%s...\n", _modname, _modext); oggfile=oggf; plIsEnd=oggIsLooped; plProcessKey=oggProcessKey; plDrawGStrings=oggDrawGStrings; plGetMasterSample=plrGetMasterSample; plGetRealMasterVolume=plrGetRealMasterVolume; if (!oggOpenPlayer(oggfile)) return -1; starttime=dos_clock(); plPause=0; normalize(); pausefadedirect=0; oggGetInfo(&inf); ogglen=inf.len; oggrate=inf.rate; return errOk; } struct cpifaceplayerstruct oggPlayer = {oggOpenFile, oggCloseFile}; struct linkinfostruct dllextinfo = {"playogg", "OpenCP Ogg Vorbis Player (c) 1994-09 Stian Skjelstad, Niklas Beisert & Tammo Hinrichs", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/playogg/Makefile0000644000175000001440000000216411655541726014532 0ustar stianusersTOPDIR=../ include $(TOPDIR)Rules.make all: oggtype.o playogg$(LIB_SUFFIX) clean: rm -f *.o *$(LIB_SUFFIX) install: $(CP) playogg$(LIB_SUFFIX) "$(DESTDIR)$(LIBDIR)" uninstall: rm -f "$(DESTDIR)$(LIBDIR)/playogg$(LIB_SUFFIX)" playogg_so=oggplay.o oggpplay.o playogg$(LIB_SUFFIX): $(playogg_so) $(CC) $(SHARED_FLAGS) $(LDFLAGS) -o $@ $^ $(OGG_LIBS) $(MATH_LIBS) $(VORBIS_LIBS) $(VORBISFILE_LIBS) oggtype.o: oggtype.c \ ../config.h \ ../types.h \ ../filesel/mdb.h $(CC) oggtype.c -o $@ -c oggplay.o: oggplay.c \ ../config.h \ ../types.h \ ../stuff/poll.h \ ../stuff/timer.h \ ../dev/player.h \ ../dev/deviplay.h \ ../dev/plrasm.h \ ../stuff/imsrtns.h \ oggplay.h $(CC) oggplay.c -o $@ $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS) -c oggpplay.o: oggpplay.c \ ../config.h \ ../types.h \ ../filesel/pfilesel.h \ ../filesel/mdb.h \ ../stuff/poutput.h \ ../dev/player.h \ ../boot/psetting.h \ ../boot/plinkman.h \ oggplay.h \ ../stuff/sets.h \ ../stuff/compat.h \ ../stuff/err.h \ ../dev/deviplay.h \ ../cpiface/cpiface.h $(CC) oggpplay.c -o $@ $(OGG_CFLAGS) $(VORBIS_CFLAGS) $(VORBISFILE_CFLAGS) -c ocp-0.1.21/SUID0000644000175000001440000000042311655541726012113 0ustar stianusersWhen Open Cubic Player is ran ssetuid, the kickstart program (the ocp executable) will not allow the libocp.so to be symlinked. TODO: Use the global configuration when ran setuid and not ~/.ocp/ocp.ini ? if (getuid()==0)&&(geteuid()==0) a seteuid(getuid()); will be issued ocp-0.1.21/medialib/0000755000175000001440000000000011655541750013170 5ustar stianusersocp-0.1.21/medialib/Makefile0000644000175000001440000000115211655541726014632 0ustar stianusersTOPDIR=../ include $(TOPDIR)Rules.make all: medialib$(LIB_SUFFIX) medialib_so=medialib.o medialib$(LIB_SUFFIX): $(medialib_so) $(CC) $(SHARED_FLAGS) -o $@ $^ clean: rm -f *.o *$(LIB_SUFFIX) install: $(CP) medialib$(LIB_SUFFIX) "$(DESTDIR)$(LIBDIR)" uninstall: rm -f "$(DESTDIR)$(LIBDIR)/medialib$(LIB_SUFFIX)" medialib.o: medialib.c \ ../config.h \ ../types.h \ ../boot/plinkman.h \ ../boot/psetting.h \ ../filesel/dirdb.h \ ../filesel/modlist.h \ ../filesel/pfilesel.h \ ../stuff/err.h \ ../stuff/poutput.h \ ../stuff/framelock.h \ ../filesel/mdb.h \ ../filesel/adb.h $(CC) medialib.c -o $@ -c ocp-0.1.21/medialib/medialib.c0000644000175000001440000003206711655541726015115 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * MEDIALIBRARY filebrowser * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss050430 Stian Skjelstad * -first release */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "types.h" #include "boot/plinkman.h" #include "filesel/dirdb.h" #include "filesel/modlist.h" #include "filesel/mdb.h" #include "filesel/adb.h" #include "filesel/pfilesel.h" #include "boot/psetting.h" #include "stuff/err.h" #include "stuff/poutput.h" #include "stuff/framelock.h" static struct mdbreaddirregstruct mlReadDirReg; static struct dmDrive *dmMEDIALIB; static int mlDrawBox(void) { unsigned int mlTop=plScrHeight/2-2; unsigned int i; displayvoid(mlTop+1, 5, plScrWidth-10); displayvoid(mlTop+2, 5, plScrWidth-10); displayvoid(mlTop+3, 5, plScrWidth-10); displaystr(mlTop, 4, 0x04, "\xda", 1); for (i=5;i<(plScrWidth-5);i++) displaystr(mlTop, i, 0x04, "\xc4", 1); displaystr(mlTop, plScrWidth-5, 0x04, "\xbf", 1); displaystr(mlTop+1, 4, 0x04, "\xb3", 1); displaystr(mlTop+2, 4, 0x04, "\xb3", 1); displaystr(mlTop+3, 4, 0x04, "\xb3", 1); displaystr(mlTop+1, plScrWidth-5, 0x04, "\xb3", 1); displaystr(mlTop+2, plScrWidth-5, 0x04, "\xb3", 1); displaystr(mlTop+3, plScrWidth-5, 0x04, "\xb3", 1); displaystr(mlTop+4, 4, 0x04, "\xc0", 1); for (i=5;i<(plScrWidth-5);i++) displaystr(mlTop+4, i, 0x04, "\xc4", 1); displaystr(mlTop+4, plScrWidth-5, 0x04, "\xd9", 1); return mlTop; } static int mlSubScan(const uint32_t dirdbnode, int mlTop) { struct modlist *ml = modlist_create(); struct modlistentry *mle; unsigned int i; char npath[PATH_MAX+1]; dirdbGetFullName(dirdbnode, npath, DIRDB_FULLNAME_NOBASE|DIRDB_FULLNAME_ENDSLASH); displaystr(mlTop+2, 5, 0x0f, npath, plScrWidth-10); fsReadDir(ml, dmFILE, dirdbnode, "*", RD_SUBNOSYMLINK|RD_PUTSUBS/*|(fsScanArcs?RD_ARCSCAN:0)*/); if (ekbhit()) { uint16_t key=egetch(); if (key==27) return -1; } for (i=0;inum;i++) { mle=modlist_get(ml, i); if (mle->flags&MODLIST_FLAG_DIR) { if (strcmp(mle->name, "..")) if (strcmp(mle->name, ".")) if (strcmp(mle->name, "/")) { /* dirdbGetFullName(mle->dirdbfullpath, npath, DIRDB_FULLNAME_NOBASE|DIRDB_FULLNAME_ENDSLASH); if (mlSubScan(npath, mlTop))*/ if (mlSubScan(mle->dirdbfullpath, mlTop)) return -1; } } else if (mle->flags&MODLIST_FLAG_FILE) { if (!mdbInfoRead(mle->fileref)) mdbScan(mle); dirdbMakeMdbAdbRef(mle->dirdbfullpath, mle->fileref, mle->adb_ref); } } modlist_free(ml); return 0; } static int mlScan(const uint32_t dirdbnode) { int mlTop=mlDrawBox(); dirdbTagSetParent(dirdbnode); displaystr(mlTop+1, 5, 0x0b, "Scanning filesystem, current directory:", 39); displaystr(mlTop+3, 5, 0x0b, "-- Abort with escape --", 23); if (mlSubScan(dirdbnode, mlTop)) { dirdbTagCancel(); return -1; } dirdbTagRemoveUntaggedAndSubmit(); dirdbFlush(); return 0; } static FILE *mlSourcesAdd(struct modlistentry *entry) { unsigned int mlTop=mlDrawBox(); int editpath=0; /* these are for editing the path */ char str[PATH_MAX+6]; unsigned int curpos; unsigned int cmdlen; int insmode=1; unsigned int scrolled=0; strcpy(str, "file:/"); curpos=strlen(str); cmdlen=strlen(str); displaystr(mlTop+3, 5, 0x0b, "Abort with escape, or finish selection by pressing enter", 56); while (1) { uint16_t key; displaystr(mlTop+1, 5, (editpath?0x8f:0x0f), str+scrolled, plScrWidth-10); if (editpath) setcur(mlTop+1, 5+curpos-scrolled); displaystr(mlTop+2, 5, (editpath?0x0f:0x8f), "current file: directory", plScrWidth-10); while (!ekbhit()) framelock(); key=egetch(); if ((key>=0x20)&&(key<=0xFF)) { if (editpath) { if (insmode) { if (cmdlen<(PATH_MAX+5)) { memmove(str+curpos+1, str+curpos, cmdlen-curpos+1); str[curpos]=key; curpos++; cmdlen++; } } else if (curpos==cmdlen) { if (cmdlen<(PATH_MAX+5)) { str[curpos++]=key; str[curpos]=0; cmdlen++; } } else str[curpos++]=key; } } else switch (key) { case 27: setcurshape(0); return NULL; case KEY_LEFT: if (editpath) if (curpos) curpos--; break; case KEY_RIGHT: if (editpath) if (curposdrivename, "file:")) { /*char currentpath[PATH_MAX+1];*/ /*dirdbGetFullName(_dmDrives->currentpath, currentpath, DIRDB_FULLNAME_NOBASE|DIRDB_FULLNAME_ENDSLASH);*/ mlScan(_dmDrives->currentpath); break; } _dmDrives=_dmDrives->next; } } else { uint32_t node; if (str[0]==0) return NULL; node=dirdbResolvePathAndRef(str); mlScan(node); dirdbUnref(node); } setcurshape(0); fsRescanDir(); return NULL; case KEY_UP: case KEY_DOWN: if ((editpath^=1)) setcurshape((insmode?1:2)); else setcurshape(0); break; } while ((curpos-scrolled)>=(plScrWidth-10)) scrolled+=8; while (((signed)curpos-(signed)scrolled)<0) scrolled-=8; } } static int mlReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { struct modlistentry entry; uint32_t dmadd, dmall, dmsearch, dmparent; if (drive!=dmMEDIALIB) return 1; dmadd=dirdbFindAndRef(drive->basepath, "addfiles"); dmall=dirdbFindAndRef(drive->basepath, "listall"); dmsearch=dirdbFindAndRef(drive->basepath, "search"); dmparent=dirdbGetParentAndRef(path); if (path==drive->basepath) { if (!(opt&RD_PUTSUBS)) return 1; entry.drive=drive; entry.flags=MODLIST_FLAG_DIR; entry.fileref=0xffffffff; entry.adb_ref=0xffffffff; entry.Read=0; entry.ReadHeader=0; entry.ReadHandle=0; strcpy(entry.shortname, "all"); fs12name(entry.shortname, "all"); strcpy(entry.name, "all"); entry.dirdbfullpath=dmall; modlist_append(ml, &entry); strcpy(entry.shortname, "search"); strcpy(entry.name, "search"); fs12name(entry.shortname, "search"); entry.dirdbfullpath=dmsearch; modlist_append(ml, &entry); strcpy(entry.shortname, "addfiles"); strcpy(entry.name, "addfiles"); fs12name(entry.shortname, "addfiles"); entry.dirdbfullpath=dmadd; entry.flags=MODLIST_FLAG_FILE|MODLIST_FLAG_VIRTUAL; entry.ReadHandle=mlSourcesAdd; modlist_append(ml, &entry); goto out; } if (path==dmall) { int first=1; uint32_t dirdbnode; uint32_t mdbref; uint32_t adbref; while (!dirdbGetMdbAdb(&dirdbnode, &mdbref, &adbref, &first)) { char cachefile[NAME_MAX+1]; dirdbGetname(dirdbnode, cachefile); fs12name(entry.shortname, cachefile); strncpy(entry.name, cachefile, NAME_MAX); entry.name[NAME_MAX]=0; entry.drive=dmFILE; entry.dirdbfullpath=dirdbnode; /*dirdbResolvePathAndRef(files[i].name);*/ entry.flags=MODLIST_FLAG_FILE; entry.fileref=mdbref; entry.adb_ref=adbref; if (adbref==DIRDB_NO_ADBREF) { entry.Read=dosfile_Read; entry.ReadHeader=dosfile_ReadHeader; entry.ReadHandle=dosfile_ReadHandle; } else { entry.Read=adb_Read; entry.ReadHeader=adb_ReadHeader; entry.ReadHandle=adb_ReadHandle; } modlist_append(ml, &entry); /* dirdbUnref(entry.dirdbfullpath);*/ } goto out; } if (path==dmsearch) { unsigned int mlTop=mlDrawBox(); char str[NAME_MAX]; unsigned int curpos; unsigned int cmdlen; int insmode=1; unsigned int scrolled=0; displaystr(mlTop+1, 5, 0x0b, "Give me something to crunch!!", 29); displaystr(mlTop+3, 5, 0x0b, "-- Finish with enter --", 23); str[0]=0; curpos=0; cmdlen=0; setcurshape(1); while (1) { uint16_t key; displaystr(mlTop+2, 5, 0x8f, str+scrolled, plScrWidth-10); setcur(mlTop+2, 5+curpos-scrolled); while (!ekbhit()) framelock(); key=egetch(); if ((key>=0x20)&&(key<=0xFF)) { if (insmode) { if ((cmdlen+1)=(plScrWidth-10)) scrolled+=8; while (((signed)curpos-(signed)scrolled)<0) scrolled-=8; } } out: dirdbUnref(dmsearch); dirdbUnref(dmall); if (dmparent!=DIRDB_NOPARENT) dirdbUnref(dmparent); return 1; } static int mlint(void) { mdbRegisterReadDir(&mlReadDirReg); dmMEDIALIB=RegisterDrive("medialib:"); return errOk; } static void mlclose(void) { mdbUnregisterReadDir(&mlReadDirReg); } static struct mdbreaddirregstruct mlReadDirReg = {mlReadDir MDBREADDIRREGSTRUCT_TAIL}; char *dllinfo = ""; struct linkinfostruct dllextinfo = {"medialib", "OpenCP medialib (c) 2005-09 Stian Skjelstad", DLLVERSION, 0, Init: mlint, Close: mlclose, PreInit:0, LateInit: 0, PreClose:0, LateClose: 0}; ocp-0.1.21/filesel/0000755000175000001440000000000011655541750013045 5ustar stianusersocp-0.1.21/filesel/adb.c0000644000175000001440000004054311655541726013750 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Archive DataBase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040823 Stian Skjelstad * -Make sure that the adb_ReadHandle does not survive a fork * -ss040918 Stian Skjelstad * -Add "Scanning archive" message to the console * -ss050124 Stian Skjelstad * -fnmatch into place */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "dirdb.h" #include "boot/plinkman.h" #include "stuff/poutput.h" #include "boot/psetting.h" #include "modlist.h" #include "mdb.h" #include "pfilesel.h" #include "stuff/compat.h" static struct adbregstruct *adbPackers = 0; static char adbDirty; static struct arcentry *adbData; static uint32_t adbNum; static uint32_t adbFindArc; static uint32_t adbFindPos; const char adbsigv1[16] = "CPArchiveCache\x1B\x00"; const char adbsigv2[16] = "CPArchiveCache\x1B\x01"; struct __attribute__((packed)) adbheader { char sig[16]; uint32_t entries; }; void adbRegister(struct adbregstruct *r) { r->next=adbPackers; adbPackers=r; } void adbUnregister(struct adbregstruct *r) { struct adbregstruct *root=adbPackers; if (root==r) { adbPackers=r->next; return; } while (root) { if (root->next==r) { root->next=root->next->next; return; } if (!root->next) return; root=root->next; } } char adbInit(void) { char path[PATH_MAX+1]; int f; struct adbheader header; int old=0; unsigned int i; adbDirty=0; adbData=0; adbNum=0; if ((strlen(cfConfigDir)+10)>=PATH_MAX) return 1; /* path is too long */ strcpy(path, cfConfigDir); strcat(path, "CPARCS.DAT"); if ((f=open(path, O_RDONLY))<0) return 1; fprintf(stderr, "Loading %s .. ", path); if (read(f, &header, sizeof(header))!=sizeof(header)) { fprintf(stderr, "No header\n"); close(f); return 1; } if (!memcmp(header.sig, adbsigv1, 16)) { old=1; fprintf(stderr, "(Old format) "); } else if (memcmp(header.sig, adbsigv2, 16)) { fprintf(stderr, "Invalid header\n"); close(f); return 1; } adbNum=uint32_little(header.entries); if (!adbNum) { fprintf(stderr, "Cache empty\n"); close(f); return 1; } adbData=malloc(sizeof(struct arcentry)*adbNum); if (!adbData) return 0; if (old) { #define OLD_ARC_PATH_MAX 63 struct __attribute__((packed)) oldarcentry { uint8_t flags; uint32_t parent; char name[OLD_ARC_PATH_MAX+1]; /* some stupid archives needs full path, which can be long */ uint32_t size; } oldentry; for (i=0;i=PATH_MAX) return; /* path is too long */ strcpy(path, cfConfigDir); strcat(path, "CPARCS.DAT"); if ((f=open(path, O_WRONLY|O_CREAT, S_IREAD|S_IWRITE))<0) { perror("open(CPARCS.DAT"); return; } lseek(f, 0, SEEK_SET); memcpy(header.sig, adbsigv2, 16); header.entries=uint32_little(adbNum); while (1) { ssize_t res; res = write(f, &header, sizeof(header)); if (res < 0) { if (errno==EAGAIN) continue; if (errno==EINTR) continue; fprintf(stderr, __FILE__ " write() to %s failed: %s\n", path, strerror(errno)); exit(1); } else if (res != sizeof(header)) { fprintf(stderr, __FILE__ " write() to %s returned only partial data\n", path); exit(1); } else break; } i=0; while (iflags&ADB_ARC) adbData[i].parent=i; adbDirty=1; return 1; } uint32_t adbFind(const char *arcname) { uint32_t i; size_t len=strlen(arcname)+1; for (i=0; i=254) { retval=E2BIG; goto fail; } argv[++argc]=0; } } else if ((*cmd)=='%') { cmd++; switch (*cmd) { default: case 0: retval=EINVAL; goto fail; case 'a': case 'A': if (!argv[argc]) { if (!(argv[argc]=malloc(strlen(arc)+1))) { retval=ENOMEM; goto fail; } strcpy(argv[argc], arc); } else { char *tmp; if (!(tmp=realloc(argv[argc], strlen(argv[argc])+strlen(arc)+1))) { retval=ENOMEM; goto fail; } strcat(argv[argc], arc); } break; case 'n': case 'N': if (!argv[argc]) { if (!(argv[argc]=malloc(strlen(name)+1))) { retval=ENOMEM; goto fail; } strcpy(argv[argc], name); } else { char *tmp; if (!(tmp=realloc(argv[argc], strlen(argv[argc])+strlen(name)+1))) { retval=ENOMEM; goto fail; } strcat(argv[argc], name); } break; case 'd': case 'D': if (!argv[argc]) { if (!(argv[argc]=malloc(strlen(dir)+1))) { retval=ENOMEM; goto fail; } strcpy(argv[argc], dir); } else { char *tmp; if (!(tmp=realloc(argv[argc], strlen(argv[argc])+strlen(dir)+1))) { retval=ENOMEM; goto fail; } strcat(argv[argc], dir); } break; case '%': if (!argv[argc]) { if (!(argv[argc]=malloc(2))) { retval=ENOMEM; goto fail; } argv[argc][0]='%'; argv[argc][1]=0; } else { char *tmp; int len; if (!(tmp=realloc(argv[argc], (len=strlen(argv[argc]))+2))) { retval=ENOMEM; goto fail; } argv[argc]=tmp; argv[argc][len++]='%'; argv[argc][len]=0; } break; } } else { if (!argv[argc]) { if (!(argv[argc]=malloc(2))) { retval=ENOMEM; goto fail; } argv[argc][0]=*cmd; argv[argc][1]=0; } else { char *tmp; int len; if (!(tmp=realloc(argv[argc], (len=strlen(argv[argc]))+2))) { retval=ENOMEM; goto fail; } argv[argc]=tmp; argv[argc][len++]=*cmd; argv[argc][len]=0; } } cmd++; } if (argv[argc]) argv[++argc]=0; if ((child=fork())) { if (child<0) { retval=errno; goto fail; } while (waitpid(child, &retval, 0)!=child) { if (errno!=EINTR) { retval=errno; goto fail; } } } else { execvp(argv[0], argv); exit(errno); } fail: for (count=0;count<=argc;count++) if (argv[count]) free(argv[count]); return retval; } static int isarchive(const char *ext) { struct adbregstruct *packers; for (packers=adbPackers; packers; packers=packers->next) if (!strcasecmp(ext, packers->ext)) return 1; return 0; } int isarchivepath(const char *p) { char path[PATH_MAX+1]; char ext[NAME_MAX+1]; /* struct stat st; */ strcpy(path, p); if (*p) if (path[strlen(path)-1]=='/') path[strlen(path)-1]=0; /* if (stat(path, &st)) return 0; if (!S_ISREG(st.st_mode)) return 0; */ _splitpath(path, 0, 0, 0, ext); return isarchive(ext); } static signed char adbFindNext(char *findname, uint32_t *findlen, uint32_t *adb_ref) { uint32_t i; for (i=adbFindPos; iARC_PATH_MAX) return -1; strcpy(arcname, name); strcat(arcname, ext); ar=adbFind(arcname); if ((ar==0xFFFFFFFF)||(arclen!=(ar!=0xffffffff?adbData[ar].size:0))) { if (ar!=0xFFFFFFFF) for (i=0; inext) if (!strcasecmp(ext, packers->ext)) { conRestore(); if (!packers->Scan(path)) return -1; else break; } if (!packers) return 1; } ar=adbFind(arcname); } adbFindArc=ar; adbFindPos=0; return adbFindNext(findname, findlen, adb_ref); } FILE *adb_ReadHandle(struct modlistentry *entry) { char dir[PATH_MAX+1]; int fd; char path[PATH_MAX+1]; char temppath[PATH_MAX+1]; char ext[NAME_MAX+1]; char npath[PATH_MAX+1]; struct arcentry *this/*, *parent*/; this=&adbData[entry->adb_ref]; dirdbGetFullName(entry->dirdbfullpath, npath, DIRDB_FULLNAME_NOBASE); _splitpath(npath, NULL, dir, NULL, NULL); /* TODO, logic here should work / for / and stat for dir/file */ _makepath(path, 0, dir, 0, 0); path[strlen(path)-1]=0; /* Remove / suffix */ if (!isarchivepath(path)) return 0; if ((strlen(cfTempDir)+strlen("ocptmpXXXXXX"))>PATH_MAX) return 0; _splitpath(path, 0, 0, 0, ext); strcpy(temppath, cfTempDir); strcat(temppath, "ocptmpXXXXXX"); if ((fd=mkstemp(temppath))<0) { perror("adc.c: mkstemp()"); return 0; } /*fcntl(fd, F_SETFD, 1<next) if (!strcasecmp(ext, packers->ext)) { if (!packers->Call(adbCallGet, path, this->name, fd)) { close(fd); unlink(temppath); fprintf(stderr, "adb.c: Failed to fetch file\n"); return 0; } else { lseek(fd, 0, SEEK_SET); unlink(temppath); return fdopen(fd, "r"); } } } fprintf(stderr, "adc.c: No packer found?\n"); close(fd); return 0; } int adb_ReadHeader(struct modlistentry *entry, char *mem, size_t *size) { FILE *f=adb_ReadHandle(entry); int res; if (!f) return -1; res=fread(mem, 1, *size, f); *size=res; fclose(f); return 0; } int adb_Read(struct modlistentry *entry, char **mem, size_t *size) { FILE *f=adb_ReadHandle(entry); int res; if (!f) return -1; *mem=malloc(*size=(1024*1024*128)); res=fread(mem, 1, *size, f); if (!(*size=res)) { free(*mem); *mem=NULL; } else { *mem=realloc(*mem, *size); } fclose(f); return 0; } static int arcReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { char _path[PATH_MAX+1]; struct modlistentry m; if (drive!=dmFILE) return 1; dirdbGetFullName(path, _path, DIRDB_FULLNAME_NOBASE); /* dmGetPath(path, dirref); */ if (isarchivepath(_path)) { /* dmGetPath(path, dirref); path[strlen(path)-1]=0; */ size_t flength; int tf; uint32_t size, adb_ref; signed char done; char newfilepath[ARC_PATH_MAX+1]; #ifndef FNM_CASEFOLD char *mask_upper; char *iterate; if ((mask_upper = strdup(mask))) { for (iterate = mask_upper; *iterate; iterate++) *iterate = toupper(*iterate); } else { perror("adb.c: strdup() failed"); return 1; } #endif if ((tf=open(_path, O_RDONLY))<0) if (tf<0) { #ifndef FNM_CASEFOLD free(mask_upper); #endif return 1; } flength=filelength(tf); close(tf); for (done=adbFindFirst(_path, flength, newfilepath, &size, &adb_ref); !done; done=adbFindNext(newfilepath, &size, &adb_ref)) { char name[NAME_MAX+1]; char ext[NAME_MAX+1]; char npath[PATH_MAX+1]; char *tmp=rindex(newfilepath, '/'); if (!tmp) tmp=newfilepath; else tmp++; #ifndef FNM_CASEFOLD { char *tmp_upper; if ((tmp_upper = strdup(tmp))) { for (iterate = tmp_upper; *iterate; iterate++) *iterate = toupper(*iterate); } else { perror("adb.c: strdup() failed"); continue; } if (fnmatch(mask_upper, tmp_upper, 0)) { free(tmp_upper); continue; } free(tmp_upper); } #else if (fnmatch(mask, tmp, FNM_CASEFOLD)) continue; #endif _splitpath(newfilepath, 0, 0, name, ext); strcpy(m.name, newfilepath); m.drive=drive; _makepath(npath, 0, _path, name, ext); m.dirdbfullpath=dirdbResolvePathWithBaseAndRef(drive->basepath, npath); if ((strlen(name)+strlen(ext)) * * *.M3u file-reader/parser * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss051231 Stian Skjelstad * -first release */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "dirdb.h" #include "gendir.h" #include "mdb.h" #include "modlist.h" #include "pfilesel.h" #include "playlist.h" #include "stuff/compat.h" static int m3uReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { char *s1, *s2; #if 0 char *s3; #endif char newpath[PATH_MAX+1]; char *readbuffer; char *buftail; int buftail_n; int fd; struct stat st; #ifndef FNM_CASEFOLD char *mask_upper; char *iterate; #endif if (drive!=dmFILE) return 1; dirdbGetFullName(path, newpath, DIRDB_FULLNAME_NOBASE); /* no file: */ /* Does the file end in .M3U ? */ s1=newpath+strlen(newpath)-4; if (s1(1024*1024)) { fprintf(stderr, "[M3U] File too big\n"); close(fd); return 1; } readbuffer=malloc(st.st_size); if (read(fd, readbuffer, st.st_size)!=st.st_size) { close(fd); return 1; } close(fd); buftail=readbuffer; buftail_n=st.st_size; #ifndef FNM_CASEFOLD if ((mask_upper = strdup(mask))) { for (iterate = mask_upper; *iterate; iterate++) *iterate = toupper(*iterate); } else { perror("pfsm3u.c: strdup() failed"); return 1; } #endif while (buftail_n>0) { /* find new-line */ s1=memchr(buftail, '\n', buftail_n); s2=memchr(buftail, '\r', buftail_n); if (!s1) { if (!s2) break; s1=s2; } else if (s2) if (s2 /* FILE * */ struct moduleinfostruct; extern int fsGetNextFile(char *path, struct moduleinfostruct *info, FILE **); /* info comes from external buffer */ extern int fsGetPrevFile(char *path, struct moduleinfostruct *info, FILE **); /* info comes from external buffer */ extern int fsFilesLeft(void); extern signed int fsFileSelect(void); /* extern char fsAddFiles(const char *); use the playlist instead..*/ extern int fsPreInit(void); extern int fsInit(void); extern void fsClose(void); extern int fsFPS; /* see stuff/framelock.c */ extern int fsFPSCurrent; /* see stuff/framelock.c */ extern int fsListScramble; extern int fsListRemove; extern int fsLoopMods; extern int fsScanNames; extern int fsScanArcs; extern int fsScanInArc; extern int fsScanMIF; extern int fsScrType; extern int fsEditWin; extern int fsColorTypes; extern int fsInfoMode; extern int fsPutArcs; extern int fsWriteModInfo; extern const char *(fsTypeNames[256]); /* type description */ extern void fsRegisterExt(const char *ext); extern int fsIsModule(const char *ext); struct preprocregstruct { void (*Preprocess)(const char *path, struct moduleinfostruct *info, FILE **f); struct preprocregstruct *next; }; #define PREPROCREGSTRUCT_TAIL ,0 struct filehandlerstruct { int (*Process)(const char *path, struct moduleinfostruct *m, FILE **f); }; typedef enum { interfaceReturnContinue=0, interfaceReturnNextAuto=1, interfaceReturnQuit=2, interfaceReturnNextManuel=3, interfaceReturnPrevManuel=6, interfaceReturnCallFs=4, interfaceReturnDosShell=5 } interfaceReturnEnum; struct interfacestruct { int (*Init)(const char *path, struct moduleinfostruct *info, FILE **f); interfaceReturnEnum (*Run)(void); void (*Close)(void); const char *name; struct interfacestruct *next; }; #define INTERFACESTRUCT_TAIL ,0 extern void plRegisterInterface(struct interfacestruct *interface); extern void plUnregisterInterface(struct interfacestruct *interface); extern struct interfacestruct *plFindInterface(const char *name); extern struct preprocregstruct *plPreprocess; extern void plRegisterPreprocess(struct preprocregstruct *r); extern void plUnregisterPreprocess(struct preprocregstruct *r); #define RD_PUTSUBS 1 #define RD_ARCSCAN 2 #define RD_SUBNOSYMLINK 4 #define RD_PUTRSUBS 16 #if 0 struct modlist; extern char *dmGetPath(char *path, unsigned short ref); extern unsigned short dmGetPathReference(const char *p); extern unsigned short dmGetDriveDir(int drv); #endif #if 0 extern char mifMemRead(const char *name, unsigned short size, char *ptr); #endif struct dmDrive { char drivename[13]; /*char currentpath[PATH_MAX+1];*/ uint32_t basepath; uint32_t currentpath; struct dmDrive *next; }; extern struct dmDrive *dmDrives; extern struct dmDrive *RegisterDrive(const char *dmDrive); extern struct dmDrive *dmFindDrive(const char *dmDrive); /* to get the correct drive from a given string */ extern struct dmDrive *dmFILE; void fsConvFileName12(char *c, const char *f, const char *e); void convfilename12wc(char *c, const char *f, const char *e); int fsMatchFileName12(const char *a, const char *b); extern void fsSetup(void); extern void fsRescanDir(void); extern void fsForceRemove(const char *path); struct modlistentry; extern int dosfile_Read(struct modlistentry *entry, char **mem, size_t *size); /* used by medialib */ extern int dosfile_ReadHeader(struct modlistentry *entry, char *mem, size_t *size); /* used by medialib */ extern FILE *dosfile_ReadHandle(struct modlistentry *entry); #endif ocp-0.1.21/filesel/dirdb.h0000644000175000001440000000243511655541726014311 0ustar stianusers#ifndef _DIRDB_H #define _DIRDB_H #define DIRDB_NOPARENT 0xffffffff #define DIRDB_NO_MDBREF 0xffffffff #define DIRDB_NO_ADBREF 0xffffffff extern const char dirdbsigv1[60]; extern const char dirdbsigv2[60]; extern void dirdbFlush(void); /* removes all nodes that hasn't been ref'ed yet aswell */ #define DIRDB_FULLNAME_NOBASE 1 #define DIRDB_FULLNAME_ENDSLASH 2 extern void dirdbGetFullName(uint32_t node, char *name /* PATH_MAX+1, ends not with a / */, int flags); extern void dirdbGetname(uint32_t node, char *name /*NAME_MAX+1*/); extern void dirdbUnref(uint32_t node); extern void dirdbRef(uint32_t node); extern uint32_t dirdbFindAndRef(uint32_t parent, const char *name /* NAME_MAX + 1 */); extern uint32_t dirdbResolvePathWithBaseAndRef(uint32_t base, const char *name /* PATH_MAX + 1 */); extern uint32_t dirdbResolvePathAndRef(const char *name /*PATH_MAX + 1 */); extern int dirdbInit(void); extern void dirdbClose(void); extern uint32_t dirdbGetParentAndRef(uint32_t node); extern void dirdbTagSetParent(uint32_t node); extern void dirdbMakeMdbAdbRef(uint32_t node, uint32_t mdbref, uint32_t adbref); extern void dirdbTagCancel(void); extern void dirdbTagRemoveUntaggedAndSubmit(void); extern int dirdbGetMdbAdb(uint32_t *dirdbnode, uint32_t *mdbnode, uint32_t *adbref, int *first); #endif ocp-0.1.21/filesel/mdb.h0000644000175000001440000000653111655541726013770 0ustar stianusers#ifndef _MDB_H #define _MDB_H #include /* FILE * */ struct __attribute__((packed)) moduleinfostruct { #define MDB_USED 1 #define MDB_DIRTY 2 #define MDB_BLOCKTYPE 12 #define MDB_VIRTUAL 16 #define MDB_BIGMODULE 32 #define MDB_PLAYLIST 64 /* handle as dir */ uint8_t flags1; #define MDB_GENERAL 0 /* sorry dudes, but I upgraded the references to 32 bit */ uint8_t modtype; /* 1 */ uint32_t comref; /* 5 */ uint32_t compref; /* 9 */ uint32_t futref; /* 13 */ char name[12]; /* 25 */ uint32_t size; /* 29 */ char modname[32]; /* 61 */ uint32_t date; /* 65 */ uint16_t playtime; /* 67 */ uint8_t channels; /* 68 */ uint8_t moduleflags; /* 69 */ uint8_t flags2; /* 70 */ #define MDB_COMPOSER 4 char composer[32]; char style[31]; uint8_t flags3; char unusedfill1[6]; #define MDB_COMMENT 8 char comment[63]; uint8_t flags4; char unusedfill2[6]; #define MDB_FUTURE 12 char dum[63]; char unusedfill3[6]; }; enum { mtMOD=0, mtMODd=1, mtMODt=2, mtM31=3, mtM15=6, mtM15t=7, mtWOW=8, mtS3M=9, mtXM=10, mtMTM=11, mt669=12, mtULT=13, mtDMF=14, mtOKT=15, mtMID=16, mtCDA=17, mtMIDd=18, mtPTM=19, mtMED=20, mtMDL=21, mtAMS=22, mtINP=23, mtDEVp=24, mtDEVs=25, mtDEVw=26, mtIT=27, mtWAV=28, mtVOC=29, mtMPx=30, mtSID=31, mtMXM=32, mtMODf=33, mtWMA=34, mtOGG=35, mtOPL=36, mtAY=37, mtFLAC=38, mtYM=39, mtPLS=128, mtM3U=129, mtANI=130, mtUnRead=0xFF }; enum { mdbEvInit, mdbEvDone }; struct mdbreadinforegstruct /* this is to test a file, and give it a tag..*/ { int (*ReadMemInfo)(struct moduleinfostruct *m, const char *buf, size_t len); int (*ReadInfo)(struct moduleinfostruct *m, FILE *f, const char *buf, size_t len); void (*Event)(int mdbEv); struct mdbreadinforegstruct *next; }; #define MDBREADINFOREGSTRUCT_TAIL ,0 struct modlist; struct modlistentry; struct dmDrive; struct mdbreaddirregstruct { int (*ReadDir)(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt); struct mdbreaddirregstruct *next; }; #define MDBREADDIRREGSTRUCT_TAIL ,0 extern int fsReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt); extern const char *mdbGetModTypeString(unsigned char type); extern int mdbGetModuleType(uint32_t fileref); extern uint8_t mdbReadModType(const char *str); extern int mdbInfoRead(uint32_t fileref); extern int mdbReadMemInfo(struct moduleinfostruct *m, const char *buf, int len); extern int mdbReadInfo(struct moduleinfostruct *m, FILE *f); extern int mdbWriteModuleInfo(uint32_t fileref, struct moduleinfostruct *m); extern void mdbScan(struct modlistentry *m); extern int mdbInit(void); extern void mdbUpdate(void); extern void mdbClose(void); extern uint32_t mdbGetModuleReference(const char *name, uint32_t size); extern int mdbGetModuleInfo(struct moduleinfostruct *m, uint32_t fileref); extern void mdbRegisterReadDir(struct mdbreaddirregstruct *r); extern void mdbUnregisterReadDir(struct mdbreaddirregstruct *r); extern void mdbRegisterReadInfo(struct mdbreadinforegstruct *r); extern void mdbUnregisterReadInfo(struct mdbreadinforegstruct *r); #if 0 /* these two are super-set by modlist itself */ extern int mdbAppend(struct modlist *m, const struct modlistentry *f); extern int mdbAppendNew(struct modlist *m, const struct modlistentry *f); #endif extern const char mdbsigv1[60]; #endif ocp-0.1.21/filesel/adb.h0000644000175000001440000000247011655541726013752 0ustar stianusers#ifndef _ADB_H #define _ADB_H enum { adbCallGet, adbCallDelete, adbCallMoveTo, adbCallMoveFrom, adbCallPut }; struct adbregstruct { const char *ext; int (*Scan)(const char *path); int (*Call)(const int act, const char *apath, const char *fullname, const int fd); struct adbregstruct *next; }; #define ADBREGSTRUCT_TAIL ,0 #define ARC_PATH_MAX 127 struct __attribute__((packed)) arcentry { #define ADB_USED 1 #define ADB_DIRTY 2 #define ADB_ARC 4 uint8_t flags; uint32_t parent; char name[ARC_PATH_MAX+1]; /* some stupid archives needs full path, which can be long */ uint32_t size; }; extern char adbInit(void); extern void adbUpdate(void); extern void adbClose(void); extern int adbCallArc(const char *cmd, const char *arc, const char *name, const char *dir); extern int adbAdd(const struct arcentry *a); extern uint32_t adbFind(const char *arcname); extern int isarchivepath(const char *p); extern const char adbsigv1[16]; extern const char adbsigv2[16]; extern void adbRegister(struct adbregstruct *r); extern void adbUnregister(struct adbregstruct *r); #include struct modlistentry; extern FILE *adb_ReadHandle(struct modlistentry *entry); extern int adb_ReadHeader(struct modlistentry *entry, char *mem, size_t *size); extern int adb_Read(struct modlistentry *entry, char **mem, size_t *size); #endif ocp-0.1.21/filesel/pfilesel.c0000644000175000001440000035273011655541726015031 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * the File selector ][ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb980510 Niklas Beisert * -first release * -kb980717 Tammo Hinrichs * -changed some INI lookups to dllinfo lookups * -fixed Long Filename lookup code a bit * -no other changes, i won't touch this monster * -fd981206 Felix Domke * -edited for new binfile * -no other changes, i won't touch this monster * (we REALLY have to split up theis file!) * -doj20020418 Dirk Jagdmann * -added screenshot * -ss040831 Stian Skjelstad * -removed modlist->pathtothis, use curdirpath instead * -updated fsEditPath and fsEditViewPath * -ss040914 Stian Skjelstad * -dirty hack to stop scanning files in arcs when moving the arrows * -ss040915 Stian Skjelstad * -Make sure that the dosfile_ReadHandle does not survive a fork * -ss040918 Stian Skjelstad * -Make sure console is sane when we are done scanning a directory * -ss040918 Stian Skjelstad * -setcurshape has new logic * -ss050118 Stian Skjelstad * -navigation in playlist * -ss050124 Stian Skjelstad * -fnmatch into place * -minor changes to make filemask work * -050528 Reinaert Albrecht * -recursive directory support (RD_PUTRSUBS) */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "boot/psetting.h" #include "cphlpfs.h" #include "dirdb.h" #include "gendir.h" #include "mdb.h" #include "cpiface/cpiface.h" #include "pfilesel.h" #include "playlist.h" #include "stuff/compat.h" #include "stuff/framelock.h" #include "stuff/poutput.h" #include "modlist.h" static char fsScanDir(int pos); static struct modlist *currentdir=NULL; static struct modlist *playlist=NULL; char curdirpath[PATH_MAX+1]="file:/"; uint32_t dirdbcurdirpath=DIRDB_NOPARENT; char curmask[NAME_MAX+1]="*"; struct dmDrive *dmDrives=0; struct dmDrive *dmCurDrive=0; struct dmDrive *dmFILE; struct preprocregstruct *plPreprocess = 0; static void fsSavePlayList(const struct modlist *ml); struct dmDrive *RegisterDrive(const char *dmDrive) { struct dmDrive *ref = dmDrives; while (ref) { if (!strcmp(ref->drivename, dmDrive)) return ref; ref = ref->next; } ref=calloc(1, sizeof(struct dmDrive)); strcpy(ref->drivename, dmDrive); ref->basepath=dirdbFindAndRef(DIRDB_NOPARENT, ref->drivename); ref->currentpath=ref->basepath; dirdbRef(ref->currentpath); ref->next=dmDrives; dmDrives=ref; return ref; } struct dmDrive *dmFindDrive(const char *drivename) /* to get the correct drive from a given string */ { struct dmDrive *cur=dmDrives; while (cur) { if (!strncasecmp(cur->drivename, drivename, strlen(cur->drivename))) return cur; cur=cur->next; } return NULL; } int dosfile_Read(struct modlistentry *entry, char **mem, size_t *size) { int fd; ssize_t result; char path[PATH_MAX+1]; dirdbGetFullName(entry->dirdbfullpath, path, DIRDB_FULLNAME_NOBASE); if (!(*size=_filelength(path))) return -1; if ((fd=open(path, O_RDONLY))<0) return -1; *mem=malloc(*size); redo: result=read(fd, *mem, *size); if (result<0) { if (errno==EAGAIN) goto redo; if (errno==EINTR) goto redo; free(*mem); close(fd); return -1; } if (result!=(ssize_t)*size) /* short read ???? */ { free(*mem); close(fd); return -1; } close(fd); return 0; } int dosfile_ReadHeader(struct modlistentry *entry, char *mem, size_t *size) /* size is prefilled with max data, and mem is preset*/ { int fd, result; char path[PATH_MAX+1]; dirdbGetFullName(entry->dirdbfullpath, path, DIRDB_FULLNAME_NOBASE); if (!(*size=_filelength(path))) return -1; if ((fd=open(path, O_RDONLY))<0) return -1; redo: result=read(fd, mem, *size); if (result<0) { if (errno==EAGAIN) goto redo; if (errno==EINTR) goto redo; close(fd); return -1; } *size=result; close(fd); return 0; } FILE *dosfile_ReadHandle(struct modlistentry *entry) { FILE *retval; char path[PATH_MAX+1]; dirdbGetFullName(entry->dirdbfullpath, path, DIRDB_FULLNAME_NOBASE); if ((retval=fopen(path, "r"))) fcntl(fileno(retval), F_SETFD, 1<basepath, path); fs12name(retval.shortname, childpath); #ifdef HAVE_STRUCT_DIRENT_D_TYPE if (d_type==DT_DIR) { if (!(opt&(RD_PUTRSUBS|RD_PUTSUBS))) goto out; retval.flags=MODLIST_FLAG_DIR; if (strlen(path)d_name, ".")) if (strcmp(de->d_name, "..")) if (((strlen(path)+strlen(de->d_name)+4)d_name, 0); if (isarchivepath(newpath)) { if ((opt&RD_PUTSUBS)&&(fsPutArcs/*||!(opt&RD_ARCSCAN)*/)) { #ifdef HAVE_STRUCT_DIRENT_D_TYPE dosReadDirChild(ml, ml, drive, path, de->d_name, de->d_type, mask, opt); #else dosReadDirChild(ml, ml, drive, path, de->d_name, 0, mask, opt); #endif } if (fsScanArcs) { uint32_t dirdbnewpath = dirdbFindAndRef(dirdbpath, de->d_name); if (!(fsReadDir(tl, drive, dirdbnewpath, mask, opt&~(RD_PUTRSUBS|RD_PUTSUBS)))) { dirdbUnref(dirdbnewpath); closedir(dir); modlist_sort(tl); modlist_append_modlist(ml, tl); modlist_free(tl); return 0; } dirdbUnref(dirdbnewpath); } } else { #ifdef HAVE_STRUCT_DIRENT_D_TYPE dosReadDirChild(tl, ml, drive, path, de->d_name, de->d_type, mask, opt); #else dosReadDirChild(tl, ml, drive, path, de->d_name, 0, mask, opt); #endif } } closedir(dir); } modlist_sort(tl); modlist_append_modlist(ml, tl); modlist_free(tl); return 1; } /* TODO's * * ReadDir stuff * dmDrive stuff * * rename currentdir to viewlist again: */ static char fsTypeCols[256]; /* colors */ const char *(fsTypeNames[256]) = {0}; /* type description */ static char **moduleextensions=0; void fsRegisterExt(const char *ext) { if (moduleextensions) { int n=0; char **e; for (e=moduleextensions; *e; e++, n++) if (!strcasecmp(ext, *e)) return; moduleextensions=realloc(moduleextensions, (n+2)*sizeof(char *)); moduleextensions[n]=strdup(ext); moduleextensions[n+1]=0; } else { moduleextensions=malloc(2*sizeof(char *)); moduleextensions[0]=strdup(ext); moduleextensions[1]=0; } } /* This function tells if a file ends with a valid extension or not */ int fsIsModule(const char *ext) { char **e; if (*ext++!='.') return 0; for (e=moduleextensions; *e; e++) if (!strcasecmp(ext, *e)) return 1; return 0; } static int initRootDir(const char *sec) { int count; char currentpath[PATH_MAX+1]; uint32_t newcurrentpath; dmFILE = RegisterDrive("file:"); currentdir=modlist_create(); playlist=modlist_create(); if (!getcwd(currentpath, PATH_MAX)) { perror(__FILE__ ", getcwd() failed, setting to /"); currentpath[0]='/'; currentpath[1]=0; } newcurrentpath = dirdbResolvePathWithBaseAndRef(dmFILE->basepath, currentpath); dirdbUnref(dmFILE->currentpath); dmFILE->currentpath = newcurrentpath; dmCurDrive=dmFILE; for (count=0;;count++) { char buffer[32]; const char *filename; sprintf(buffer, "file%d", count); if (!(filename=cfGetProfileString2(sec, "CommandLine_Files", buffer, NULL))) break; fsAddPlaylist(playlist, currentpath, "*", 0, filename); } for (count=0;;count++) { char buffer[32]; const char *filename; uint32_t dirdbfullpath; sprintf(buffer, "playlist%d", count); if (!(filename=cfGetProfileString2(sec, "CommandLine_Files", buffer, NULL))) break; dirdbfullpath = dirdbFindAndRef(dmFILE->currentpath, filename); fsReadDir(playlist, dmFILE, dirdbfullpath, "*", 0); /* ignore errors */ dirdbUnref(dirdbfullpath); } /* change dir */ gendir(currentpath, cfGetProfileString2(sec, "fileselector", "path", "."), currentpath); newcurrentpath = dirdbResolvePathWithBaseAndRef(dmFILE->basepath, currentpath); dirdbUnref(dmFILE->currentpath); dmFILE->currentpath = newcurrentpath; dirdbcurdirpath=dmFILE->currentpath; dirdbGetFullName(dirdbcurdirpath, curdirpath, DIRDB_FULLNAME_ENDSLASH); dirdbRef(dmFILE->currentpath); return 1; } static void doneRootDir(void) { if (currentdir) { modlist_free(currentdir); currentdir=NULL; } if (playlist) { modlist_free(playlist); playlist=NULL; } } static struct modlistentry *nextplay=NULL; typedef enum {NextPlayNone, NextPlayBrowser, NextPlayPlaylist} NextPlay; static NextPlay isnextplay = NextPlayNone; /* These guys has with rendering todo and stuff like that */ static unsigned short dirwinheight; static char quickfind[12]; static char quickfindpos; static short editpos=0; static short editmode=0; static unsigned int scanposf, scanposp; int fsListScramble=1; int fsListRemove=1; int fsLoopMods=1; int fsScanNames=1; int fsScanArcs=0; int fsScanInArc=1; int fsScanMIF=1; int fsScrType=0; int fsEditWin=1; int fsColorTypes=1; int fsInfoMode=0; int fsPutArcs=1; int fsWriteModInfo=1; static int fsPlaylistOnly=0; int fsFilesLeft(void) { return (isnextplay!=NextPlayNone)||playlist->num; } static char fsScanDir(int pos) { unsigned int op=0; switch (pos) { case 0: op=0; break; case 1: op=currentdir->pos; break; case 2: op=currentdir->pos?(currentdir->pos-1):0; break; } modlist_remove(currentdir, 0, currentdir->num); if (!fsReadDir(currentdir, dmCurDrive, dirdbcurdirpath, curmask, RD_PUTSUBS|(fsScanArcs?RD_ARCSCAN:0))) return 0; modlist_sort(currentdir); currentdir->pos=(op>=currentdir->num)?(currentdir->num-1):op; quickfindpos=0; scanposf=fsScanNames?0:~0; adbUpdate(); return 1; } void fsRescanDir(void) { fsScanDir(1); conSave(); } int fsGetPrevFile(char *path, struct moduleinfostruct *info, FILE **file) { struct modlistentry *m; int retval=0; int pick; switch (isnextplay) { default: return fsGetNextFile(path, info, file); case NextPlayNone: if (!playlist->num) { fprintf(stderr, "BUG in pfilesel.c: fsGetNextFile() invalid NextPlayPlaylist #2\n"); return retval; } if (fsListScramble) return fsGetNextFile(path, info, file); if (playlist->pos) playlist->pos--; else playlist->pos = playlist->num - 1; if (playlist->pos) pick = playlist->pos-1; else pick = playlist->num - 1; m=modlist_get(playlist, pick); break; } mdbGetModuleInfo(info, m->fileref); dirdbGetFullName(m->dirdbfullpath, path, 0); if (!(info->flags1&MDB_VIRTUAL)) /* this should equal to if (m->ReadHandle) */ { if (!(*file=m->ReadHandle(m))) goto errorout; /* strcpy(path, m->fullname); WTF WTF TODO */ /* arc's change the path */ } else *file=NULL; if (!mdbInfoRead(m->fileref)&&*file) { mdbReadInfo(info, *file); fseek(*file, 0, SEEK_SET); mdbWriteModuleInfo(m->fileref, info); mdbGetModuleInfo(info, m->fileref); } retval=1; errorout: if (fsListRemove) modlist_remove(playlist, pick, 1); return retval; } int fsGetNextFile(char *path, struct moduleinfostruct *info, FILE **file) { struct modlistentry *m; unsigned int pick=0; int retval=0; switch (isnextplay) { case NextPlayBrowser: m=nextplay; break; case NextPlayPlaylist: if (!playlist->num) { fprintf(stderr, "BUG in pfilesel.c: fsGetNextFile() invalid NextPlayPlaylist #1\n"); return retval; } pick = playlist->pos; m=modlist_get(playlist, pick); break; case NextPlayNone: if (!playlist->num) { fprintf(stderr, "BUG in pfilesel.c: fsGetNextFile() invalid NextPlayPlaylist #2\n"); return retval; } if (fsListScramble) pick=rand()%playlist->num; else pick = playlist->pos; m=modlist_get(playlist, pick); break; default: fprintf(stderr, "BUG in pfilesel.c: fsGetNextFile() Invalid isnextplay\n"); return retval; } mdbGetModuleInfo(info, m->fileref); dirdbGetFullName(m->dirdbfullpath, path, 0); if (!(info->flags1&MDB_VIRTUAL)) /* this should equal to if (m->ReadHandle) */ { if (!(*file=m->ReadHandle(m))) goto errorout; /* strcpy(path, m->fullname); WTF WTF TODO */ /* arc's change the path */ } else *file=NULL; if (!mdbInfoRead(m->fileref)&&*file) { mdbReadInfo(info, *file); fseek(*file, 0, SEEK_SET); mdbWriteModuleInfo(m->fileref, info); mdbGetModuleInfo(info, m->fileref); } retval=1; errorout: switch (isnextplay) { case NextPlayBrowser: isnextplay = NextPlayNone; break; case NextPlayPlaylist: isnextplay = NextPlayNone; /* and then run the same as bellow :-p */ case NextPlayNone: if (fsListRemove) modlist_remove(playlist, pick, 1); else { if (!fsListScramble) if ( (pick=playlist->pos+1)>=playlist->num) pick=0; playlist->pos=pick; } } return retval; } void fsForceRemove(const char *path) { uint32_t handle; handle = dirdbResolvePathAndRef(path); if (handle == DIRDB_NO_MDBREF) return; modlist_remove_all_by_path(playlist, handle); dirdbUnref(handle); } int fsPreInit(void) { int i; const char *sec=cfGetProfileString(cfConfigSec, "fileselsec", "fileselector"); const char *modexts; int extnum; if (!adbInit()) /* archive database cache */ return 0; if (!mdbInit()) return 0; if (!dirdbInit()) return 0; /* this on the other hand is VERY nice */ for (i=0; i<256; i++) { char secname[20]; sprintf(secname, "filetype %d", i); fsTypeCols[i]=cfGetProfileInt(secname, "color", 7, 10); fsTypeNames[i]=cfGetProfileString(secname, "name", ""); } /* what are these????? dmTree=0; dmReloc=0; dmMaxNodes=0; dmNumNodes=0; */ modexts=cfGetProfileString2(sec, "fileselector", "modextensions", "MOD XM S3M MID MTM DMF ULT 669 NST WOW OKT PTM AMS MDL"); extnum=cfCountSpaceList(modexts, 3); for (i=0; icurrentpath); /* due to curpath */ if (dmCurDrive) dirdbUnref(dmCurDrive->currentpath); /* due to curpath */ { struct dmDrive *drive = dmDrives, *next; while (drive) { next=drive->next; dirdbUnref(drive->basepath); dirdbUnref(drive->currentpath); free(drive); drive=next; } dmDrives=0; } dirdbClose(); } static void displayfile(const unsigned int y, const unsigned int x, const unsigned int width, /* TODO const*/ struct modlistentry *m, const unsigned char sel) { unsigned char col; unsigned short sbuf[CONSOLE_MAX_X-15]; struct moduleinfostruct mi; if (width == 14) { unsigned short _sbuf[14]; if (sel==2) writestring(_sbuf, 0, 0x07, "\x1A \x1B", 14); else writestring(_sbuf, 0, (sel==1)?0x8F:0x0F, "", 14); writestring(_sbuf, 1, (sel==1)?0x8F:0x0F, m->shortname, 12); displaystrattr(y, x, _sbuf, 14); return; } if (m->flags&MODLIST_FLAG_FILE) { col=0x07; mdbGetModuleInfo(&mi, m->fileref); if (mi.flags1&MDB_PLAYLIST) { col=0x0f; m->flags|=MODLIST_FLAG_DIR; /* TODO, register in dirdb as both DIR and FILE */ } } else { memset(&mi, 0, sizeof(mi)); col=0x0f; } if (sel==1) col|=0x80; writestring(sbuf, 0, col, "", width); if (sel==2) { writestring(sbuf, 0, 0x07, "->", 2); writestring(sbuf, width-2, 0x07, "<-", 2); } if (fsInfoMode==4) { if (!(m->flags&(MODLIST_FLAG_DIR|MODLIST_FLAG_DRV|MODLIST_FLAG_ARC))) { if (mi.modtype==0xFF) col&=~0x08; else if (fsColorTypes) { col&=0xF8; col|=fsTypeCols[mi.modtype&0xFF]; } } writestring(sbuf, 2, col, m->name, width-13); if (mi.flags1&MDB_PLAYLIST) writestring(sbuf, width-7, col, "", 5); else if (m->flags&MODLIST_FLAG_DIR) writestring(sbuf, width-7, col, "", 5); else if (m->flags&MODLIST_FLAG_DRV) writestring(sbuf, width-7, col, "", 5); else if (m->flags&MODLIST_FLAG_ARC) writestring(sbuf, width-7, col, "", 5); else { if (mi.size<1000000000) writenum(sbuf, width-11, (mi.flags1&MDB_BIGMODULE)?((col&0xF0)|0x0C):col, mi.size, 10, 9, 1); else writenum(sbuf, width-10, col, mi.size, 16, 8, 0); } } else { writestring(sbuf, 2, col, m->shortname, 12); if (mi.flags1&MDB_PLAYLIST) writestring(sbuf, 16, col, "", 5); else if (m->flags&MODLIST_FLAG_DIR) writestring(sbuf, 16, col, "", 5); else if (m->flags&MODLIST_FLAG_DRV) writestring(sbuf, 16, col, "", 5); else if (m->flags&MODLIST_FLAG_ARC) writestring(sbuf, 16, col, "", 5); else { if (mi.modtype==0xFF) col&=~0x08; else if (fsColorTypes) { col&=0xF8; col|=fsTypeCols[mi.modtype&0xFF]; } if (width>=117) /* 132 or bigger screen this will imply */ { if (fsInfoMode&1) { if (mi.comment[0]) writestring(sbuf, 16, col, mi.comment, 63); if (mi.style[0]) writestring(sbuf, 84, col, mi.style, 31); } else { if (mi.modname[0]) writestring(sbuf, 16, col, mi.modname, 32); if (mi.channels) writenum(sbuf, 50, col, mi.channels, 10, 2, 1); if (mi.playtime) { writenum(sbuf, 53, col, mi.playtime/60, 10, 3, 1); writestring(sbuf, 56, col, ":", 1); writenum(sbuf, 57, col, mi.playtime%60, 10, 2, 0); } if (mi.composer[0]) writestring(sbuf, 61, col, mi.composer, 32); if (mi.date) { if (mi.date&0xFF) { writestring(sbuf, 96, col, ".", 3); writenum(sbuf, 94, col, mi.date&0xFF, 10, 2, 1); } if (mi.date&0xFFFF) { writestring(sbuf, 99, col, ".", 3); writenum(sbuf, 97, col, (mi.date>>8)&0xFF, 10, 2, 1); } if (mi.date>>16) { writenum(sbuf, 100, col, mi.date>>16, 10, 4, 1); if (!((mi.date>>16)/100)) writestring(sbuf, 101, col, "'", 1); } } if (mi.size<1000000000) writenum(sbuf, 106, (mi.flags1&MDB_BIGMODULE)?((col&0xF0)|0x0C):col, mi.size, 10, 9, 1); else writenum(sbuf, 107, col, mi.size, 16, 8, 0); } } else switch (fsInfoMode) { case 0: writestring(sbuf, 16, col, mi.modname, 32); if (mi.channels) writenum(sbuf, 50, col, mi.channels, 10, 2, 1); if (mi.size<1000000000) writenum(sbuf, 54, (mi.flags1&MDB_BIGMODULE)?((col&0xF0)|0x0C):col, mi.size, 10, 9, 1); else writenum(sbuf, 55, col, mi.size, 16, 8, 0); break; case 1: if (mi.composer[0]) writestring(sbuf, 16, col, mi.composer, 32); if (mi.date) { if (mi.date&0xFF) { writestring(sbuf, 55, col, ".", 3); writenum(sbuf, 53, col, mi.date&0xFF, 10, 2, 1); } if (mi.date&0xFFFF) { writestring(sbuf, 58, col, ".", 3); writenum(sbuf, 56, col, (mi.date>>8)&0xFF, 10, 2, 1); } if (mi.date>>16) { writenum(sbuf, 59, col, mi.date>>16, 10, 4, 1); if (!((mi.date>>16)/100)) writestring(sbuf, 60, col, "'", 1); } } break; case 2: if (mi.comment[0]) writestring(sbuf, 16, col, mi.comment, 47); break; case 3: if (mi.style[0]) writestring(sbuf, 16, col, mi.style, 31); if (mi.playtime) { writenum(sbuf, 57, col, mi.playtime/60, 10, 3, 1); writestring(sbuf, 60, col, ":", 1); writenum(sbuf, 61, col, mi.playtime%60, 10, 2, 0); } break; } } } displaystrattr(y, x, sbuf, width); } static void fsShowDir(unsigned int firstv, unsigned int selectv, unsigned int firstp, unsigned int selectp, int selecte, const struct modlistentry *mle, int playlistactive) { unsigned int i; unsigned int vrelpos= ~0; unsigned int prelpos= ~0; uint16_t sbuf[CONSOLE_MAX_X]; unsigned int len; char temppath[PATH_MAX*2+1]; const char *tmppos; char npath[PATH_MAX+1]; if (currentdir->num>dirwinheight) vrelpos=dirwinheight*currentdir->pos/currentdir->num; if (playlist->num>dirwinheight) prelpos=dirwinheight*playlist->pos/playlist->num; make_title("file selector ]["); displayvoid(1, 0, plScrWidth); strcpy(temppath, curdirpath); strcat(temppath, curmask); len=strlen(temppath); if (selectv==(unsigned)~0) { displaystr(1, 0, 0x0f, "playlist://", plScrWidth); } else { if (len>plScrWidth) { displaystr(1, 0, 0x0F, temppath+len-plScrWidth, plScrWidth); } else { displaystr(1, 0, 0x0F, temppath, len); } } fillstr(sbuf, 0, 0x07, 0xc4, CONSOLE_MAX_X); if (!playlistactive) fillstr(sbuf, plScrWidth-15, 0x07, 0xc2, 1); displaystrattr(2, 0, sbuf, plScrWidth); if (fsEditWin||(selecte>=0)) { int first=dirwinheight+3; /* char longfile[270]; struct modinfoentry *m1=0, *m2=0, *m3=0; */ const char *modtype=""; /* longptr mle->fullpath mle.name mle->shortname char *longptr; */ struct moduleinfostruct mi; if (mle->flags&MODLIST_FLAG_FILE) { mdbGetModuleInfo(&mi, mle->fileref); modtype=mdbGetModTypeString(mi.modtype); } else { memset(&mi, 0, sizeof(mi)); } fillstr(sbuf, 0, 0x07, 0xc4, CONSOLE_MAX_X); if (!playlistactive) fillstr(sbuf, plScrWidth-15, 0x07, 0xc1, 1); displaystrattr(first, 0, sbuf, plScrWidth); if (plScrWidth>=132) { writestring(sbuf, 0, 0x07, " \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa title: ", 42); fillstr(sbuf, 42, 0x07, 0xfa, plScrWidth - 100); writestring(sbuf, plScrWidth - 59, 0x07, " type: \xfa\xfa\xfa\xfa channels: \xfa\xfa playtime: \xfa\xfa\xfa:\xfa\xfa ", 59); writestring(sbuf, 2, 0x0F, mle->shortname, 12); if (mle->flags&MODLIST_FLAG_FILE) { writenum(sbuf, 15, 0x0F, mi.size, 10, 10, 1); if (mi.flags1&MDB_BIGMODULE) writestring(sbuf, 25, 0x0F, "!", 1); } if (mi.modname[0]) { /* we pad up here */ int w=plScrWidth - 100; int l=sizeof(mi.modname); if (l>w) l=w; writestring(sbuf, 42, 0x0F, mi.modname, l); writestring(sbuf, 42+l, 0x0F, "", w-l); } if (selecte==0) markstring(sbuf, 42, plScrWidth - 100); if (*modtype) writestring(sbuf, plScrWidth - 46, 0x0F, modtype, 4); if (selecte==1) markstring(sbuf, plScrWidth - 46, 4); if (mi.channels) writenum(sbuf, plScrWidth - 27, 0x0F, mi.channels, 10, 2, 1); if (selecte==2) markstring(sbuf, plScrWidth - 27, 2); if (mi.playtime) { writenum(sbuf, plScrWidth - 9, 0x0F, mi.playtime/60, 10, 3, 1); writestring(sbuf, plScrWidth - 6, 0x0F, ":", 1); writenum(sbuf, plScrWidth - 5, 0x0F, mi.playtime%60, 10, 2, 0); } if (selecte==3) markstring(sbuf, plScrWidth - 9, 6); displaystrattr(first+1, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " composer: ", 42); fillstr(sbuf, 42, 0x07, 0xfa, plScrWidth - 100); writestring(sbuf, plScrWidth - 58, 0x07, " style: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa ", 58); if (mi.composer[0]) { /* we pad up here */ int w=plScrWidth - 100; int l=sizeof(mi.composer); if (l>w) l=w; writestring(sbuf, 42, 0x0F, mi.composer, l); writestring(sbuf, 42+l, 0x0F, "", w-l); } if (selecte==4) markstring(sbuf, 42, plScrWidth - 100); if (mi.style[0]) writestring(sbuf, plScrWidth - 46, 0x0F, mi.style, 31); if (selecte==5) markstring(sbuf, plScrWidth - 46, 31); displaystrattr(first+2, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " date: \xfa\xfa.\xfa\xfa.\xfa\xfa\xfa\xfa comment: ", 66); fillstr(sbuf, 66, 0x07, 0xfa, plScrWidth - 69); writestring(sbuf, plScrWidth - 3, 0x07, " ", 3); if (mi.date) { if (mi.date&0xFF) { writestring(sbuf, 44, 0x0F, ".", 3); writenum(sbuf, 42, 0x0F, mi.date&0xFF, 10, 2, 1); } if (mi.date&0xFFFF) { writestring(sbuf, 47, 0x0F, ".", 3); writenum(sbuf, 45, 0x0F, (mi.date>>8)&0xFF, 10, 2, 1); } if (mi.date>>16) { writenum(sbuf, 48, 0x0F, mi.date>>16, 10, 4, 1); if (!((mi.date>>16)/100)) writestring(sbuf, 49, 0x0F, "'", 1); } } if (selecte==6) markstring(sbuf, 42, 10); if (mi.comment[0]) { /* we pad up here */ int w=plScrWidth - 69; int l=sizeof(mi.comment); if (l>w) l=w; writestring(sbuf, 66, 0x0F, mi.comment, l); writestring(sbuf, 66+l, 0x0F, "", w-l); } if (selecte==7) markstring(sbuf, 66, plScrWidth - 69); displaystrattr(first+3, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " long: ", plScrWidth); dirdbGetFullName(mle->dirdbfullpath, npath, 0); tmppos=npath; if (strlen(tmppos)>=(plScrWidth - 10)) tmppos+=strlen(tmppos)-(plScrWidth - 10); writestring(sbuf, 10, 0x0F, tmppos, plScrWidth - 10); displaystrattr(first+4, 0, sbuf, plScrWidth); } else { writestring(sbuf, 0, 0x07, " \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa.\xfa\xfa\xfa \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa title: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa", plScrWidth - 13 ); writestring(sbuf, plScrWidth - 13 , 0x07, " type: \xfa\xfa\xfa\xfa ", 80); writestring(sbuf, 2, 0x0F, mle->shortname, 12); if (mle->flags&MODLIST_FLAG_FILE) { writenum(sbuf, 15, 0x0F, mi.size, 10, 10, 1); if (mi.flags1&MDB_BIGMODULE) writestring(sbuf, 25, 0x0F, "!", 1); } if (mi.modname[0]) { int w=plScrWidth - 48; int l=sizeof(mi.modname); if (l>w) l=w; writestring(sbuf, 35, /*(selecte==0)?0x8F:*/0x0F, mi.modname, l); writestring(sbuf, 35+l, /*(selecte==0)?0x8F:*/0x0F, "", w-l); } if (selecte==0) markstring(sbuf, 35, plScrWidth - 48); if (*modtype) writestring(sbuf, plScrWidth - 5, /*(selecte==1)?0x8F:*/0x0F, modtype, 4); if (selecte==1) markstring(sbuf, plScrWidth - 5, 4); displaystrattr(first+1, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " composer: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa", plScrWidth - 35); writestring(sbuf, plScrWidth - 35, 0x07, " date: \xfa\xfa.\xfa\xfa.\xfa\xfa\xfa\xfa ", 35); if (mi.date) { if (mi.date&0xFF) { writestring(sbuf, plScrWidth - 20, 0x0F, ".", 3); writenum(sbuf, plScrWidth - 22, 0x0F, mi.date&0xFF, 10, 2, 1); } if (mi.date&0xFFFF) { writestring(sbuf, plScrWidth - 17, 0x0F, ".", 3); writenum(sbuf, plScrWidth - 19, 0x0F, (mi.date>>8)&0xFF, 10, 2, 1); } if (mi.date>>16) { writenum(sbuf, plScrWidth - 16, 0x0F, mi.date>>16, 10, 4, 1); if (!((mi.date>>16)/100)) writestring(sbuf, plScrWidth - 15, 0x0F, "'", 1); } } if (selecte==6) markstring(sbuf, plScrWidth - 22, 10); if (mi.composer[0]) { /* we pad up here */ int w=plScrWidth - 47; int l=sizeof(mi.composer); if (l>w) l=w; writestring(sbuf, 13, 0x0F, mi.composer, l); writestring(sbuf, 13+l, 0x0F, "", w-l); } if (selecte==4) markstring(sbuf, 13, plScrWidth - 47); displaystrattr(first+2, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " style: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa", plScrWidth - 35); writestring(sbuf, plScrWidth - 35, 0x07, " playtime: \xfa\xfa\xfa:\xfa\xfa channels: \xfa\xfa ", 35); if (mi.channels) writenum(sbuf, plScrWidth - 3, 0x0F, mi.channels, 10, 2, 1); if (selecte==2) markstring(sbuf, plScrWidth - 3, 2); if (mi.playtime) { writenum(sbuf, plScrWidth - 22, 0x0F, mi.playtime/60, 10, 3, 1); writestring(sbuf, plScrWidth - 19, 0x0F, ":", 1); writenum(sbuf, plScrWidth - 18, 0x0F, mi.playtime%60, 10, 2, 0); } if (selecte==3) markstring(sbuf, plScrWidth - 22, 6); if (mi.style[0]) { /* we pad up here */ int w=plScrWidth - 49; int l=sizeof(mi.style); if (l>w) l=w; writestring(sbuf, 13, 0x0F, mi.style, l); writestring(sbuf, 13+l, 0x0F, "", w-l); } if (selecte==5) markstring(sbuf, 13, plScrWidth - 49); displaystrattr(first+3, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " comment: \xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa", plScrWidth - 4); writestring(sbuf, plScrWidth - 4, 0x07, " ", 4); if (mi.comment[0]) { /* we pad up here */ int w=plScrWidth - 17; int l=sizeof(mi.comment); if (l>w) l=w; writestring(sbuf, 13, 0x0F, mi.comment, l); writestring(sbuf, 13+l, 0x0F, "", w-l); } if (selecte==7) markstring(sbuf, 13, plScrWidth - 17); displaystrattr(first+4, 0, sbuf, plScrWidth); writestring(sbuf, 0, 0x07, " long: ", plScrWidth); dirdbGetFullName(mle->dirdbfullpath, npath, 0); tmppos=npath; if (strlen(tmppos)>=(plScrWidth - 9)) tmppos+=strlen(tmppos)-(plScrWidth - 9); writestring(sbuf, 9, 0x0F, tmppos, plScrWidth - 9); displaystrattr(first+5, 0, sbuf, plScrWidth); } } fillstr(sbuf, 0, 0x17, 0, CONSOLE_MAX_X); writestring(sbuf, 0, 0x17, " quickfind: [\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa] press F1 for help, or ALT-C for basic setup ", 74); writestring(sbuf, 13, 0x1F, quickfind, quickfindpos); displaystrattr(plScrHeight-1, 0, sbuf, plScrWidth); for (i=0; i=currentdir->num)) displayvoid(i+3, 0, plScrWidth-15); else { m=modlist_get(currentdir, firstv+i); displayfile(i+3, 0, plScrWidth-15, m, ((firstv+i)!=selectv)?0:(selecte<0)?1:2); } if (/*((firstp+i)<0)||*/((firstp+i)>=playlist->num)) displayvoid(i+3, plScrWidth-14, 14); else { m=modlist_get(playlist, firstp+i); displayfile(i+3, plScrWidth-14, 14, m, ((firstp+i)!=selectp)?0:(selecte<0)?1:2); } displaystr(i+3, plScrWidth-15, 0x07, (i==vrelpos)?(i==prelpos)?"\xdb":"\xdd":(i==prelpos)?"\xde":"\xb3", 1); } else { if (/*((firstp+i)<0)||*/((firstp+i)>=playlist->num)) displayvoid(i+3, 0, plScrWidth); else { m=modlist_get(playlist, firstp+i); displayfile(i+3, 0, plScrWidth, m, ((firstp+i)!=selectp)?0:(selecte<0)?1:2); } } } } void fsSetup(void) { int stored = 0; uint16_t c; int LastCurrent; plSetTextMode(fsScrType); while (1) { const char *fsInfoModes[]= {"name and size","composer","comment","style and playtime","long filenames"}; uint16_t sbuf[128]; const char *modename = plGetDisplayTextModeName(); make_title("file selector setup"); displaystr(1, 0, 0x07, "1: screen mode: ",17); displaystr(1, 17, 0x0f, modename, 64); /*displaystr(1, 0, 0x07, "1: screen mode (if driver supports it TODO): ", 45); displaystr(1, 45, 0x0F, (fsScrType&4)?"132x":" 80x", 4); displaystr(1, 49, 0x0F, ((fsScrType&3)==0)?"25":((fsScrType&3)==1)?"30":((fsScrType&3)==2)?"50":"60", 69);*/ displaystr(2, 0, 0x07, "2: scramble module list order: ", 32); displaystr(2, 32, 0x0F, fsListScramble?"on":"off", 48); displaystr(3, 0, 0x07, "3: remove modules from playlist when played: ", 46); displaystr(3, 46, 0x0F, fsListRemove?"on":"off", 34); displaystr(4, 0, 0x07, "4: loop modules: ", 18); displaystr(4, 18, 0x0F, fsLoopMods?"on":"off", 62); displaystr(5, 0, 0x07, "5: scan module informatin: ", 28); displaystr(5, 28, 0x0F, fsScanNames?"on":"off", 52); displaystr(6, 0, 0x04, "6: scan module information files: ", 35); displaystr(6, 35, 0x0F, fsScanMIF?"on":"off", 45); displaystr(7, 0, 0x07, "7: scan archive contents: ", 27); displaystr(7, 27, 0x0F, fsScanArcs?"on":"off", 53); displaystr(8, 0, 0x07, "8: scan module information in archives: ", 41); displaystr(8, 41, 0x0F, fsScanInArc?"on":"off", 39); displaystr(9, 0, 0x07, "9: save module information to disk: ", 37); displaystr(9, 37, 0x0F, fsWriteModInfo?"on":"off", 42); displaystr(10, 0, 0x07, "A: edit window: ", 17); displaystr(10, 17, 0x0F, fsEditWin?"on":"off", 63); displaystr(11, 0, 0x07, "B: module type colors: ", 24); displaystr(11, 24, 0x0F, fsColorTypes?"on":"off", 56); displaystr(12, 0, 0x07, "C: module information display mode: ", 37); displaystr(12, 37, 0x0F, fsInfoModes[fsInfoMode], 43); displaystr(13, 0, 0x07, "D: put archives: ", 18); displaystr(13, 18, 0x0F, fsPutArcs?"on":"off", 43); fillstr(sbuf, 0, 0x00, 0, 128); writestring(sbuf, 0, 0x07, "+-: Target framerate: ", 22); writenum(sbuf, 22, 0x0f, fsFPS, 10, 3, 1); writestring(sbuf, 25, 0x07, ", actual framerate: ", 20); writenum(sbuf, 45, 0x0f, LastCurrent=fsFPSCurrent, 10, 3, 1); displaystrattr(14, 0, sbuf, 128); displaystr(16, 0, 0x07, "ALT-S (or CTRL-S if in X) to save current setup to ocp.ini", 58); displaystr(plScrHeight-1, 0, 0x17, " press the number of the item you wish to change and ESC when done", plScrWidth); displaystr(17, 0, 0x03, (stored?"ocp.ini saved":""), 13); while (!ekbhit()&&(LastCurrent==fsFPSCurrent)) framelock(); if (!ekbhit()) continue; c=egetch(); switch (c) { case '1': stored = 0; _plDisplaySetupTextMode(); break; /*case '1': stored = 0; fsScrType=(fsScrType+1)&7; break;*/ case '2': stored = 0; fsListScramble=!fsListScramble; break; case '3': stored = 0; fsListRemove=!fsListRemove; break; case '4': stored = 0; fsLoopMods=!fsLoopMods; break; case '5': stored = 0; fsScanNames=!fsScanNames; break; case '6': stored = 0; fsScanMIF=!fsScanMIF; break; case '7': stored = 0; fsScanArcs=!fsScanArcs; break; case '8': stored = 0; fsScanInArc=!fsScanInArc; break; case '9': stored = 0; fsWriteModInfo=!fsWriteModInfo; break; case 'a': case 'A': stored = 0; fsEditWin=!fsEditWin; break; case 'b': case 'B': stored = 0; fsColorTypes=!fsColorTypes; break; case 'c': case 'C': stored = 0; fsInfoMode=(fsInfoMode+1)%5; break; case 'd': case 'D': stored = 0; fsPutArcs=!fsPutArcs; break; case '+': if (fsFPS<1000) fsFPS++; break; case '-': if (fsFPS>1) fsFPS--; break; case KEY_CTRL_S: case KEY_ALT_S: { const char *sec=cfGetProfileString(cfConfigSec, "fileselsec", "fileselector"); cfSetProfileInt(cfScreenSec, "screentype", fsScrType, 10); cfSetProfileBool(sec, "randomplay", fsListScramble); cfSetProfileBool(sec, "playonce", fsListRemove); cfSetProfileBool(sec, "loop", fsLoopMods); cfSetProfileBool(sec, "scanmodinfo", fsScanNames); cfSetProfileBool(sec, "scanmdz", fsScanMIF); cfSetProfileBool(sec, "scanarchives", fsScanArcs); cfSetProfileBool(sec, "scaninarcs", fsScanInArc); cfSetProfileBool(sec, "writeinfo", fsWriteModInfo); cfSetProfileBool(sec, "editwin", fsEditWin); cfSetProfileBool(sec, "typecolors", fsColorTypes); /*cfSetProfileInt(sec, "", fsInfoMode);*/ cfSetProfileBool(sec, "putarchives", fsPutArcs); cfSetProfileInt("screen", "fps", fsFPS, 10); cfStoreConfig(); stored = 1; break; } case 27: return; case KEY_ALT_K: cpiKeyHelp('1', "Toggle option 1"); cpiKeyHelp('2', "Toggle option 2"); cpiKeyHelp('3', "Toggle option 3"); cpiKeyHelp('4', "Toggle option 4"); cpiKeyHelp('5', "Toggle option 5"); cpiKeyHelp('6', "Toggle option 6"); cpiKeyHelp('7', "Toggle option 7"); cpiKeyHelp('8', "Toggle option 8"); cpiKeyHelp('9', "Toggle option 9"); cpiKeyHelp('a', "Toggle option A"); cpiKeyHelp('b', "Toggle option B"); cpiKeyHelp('c', "Toggle option C"); cpiKeyHelp('d', "Toggle option D"); cpiKeyHelp('A', "Toggle option A"); cpiKeyHelp('B', "Toggle option B"); cpiKeyHelp('C', "Toggle option C"); cpiKeyHelp('D', "Toggle option D"); cpiKeyHelp('+', "Increase FPS"); cpiKeyHelp('-', "Decrease FPS"); cpiKeyHelp(KEY_ALT_S, "Store settings to ocp.ini"); cpiKeyHelp(KEY_CTRL_S, "Store settings to ocp.ini (avoid this key if in curses)"); cpiKeyHelpDisplay(); break; } } } static struct moduleinfostruct mdbEditBuf; static unsigned char fsEditModType(unsigned char oldtype) { unsigned char index[256]; int length=0; int curindex=0; int i; const char *temp; int done=0; const int Height=20; const int iHeight=Height-1; const int Width=15; int Top=(plScrHeight-Height)/2; int Left=(plScrWidth-Width)/2; const int Mid = 5; int editcol=0; for (i=0;i<256;i++) { temp=mdbGetModTypeString(i); if ((temp[0])||(i==mtUnRead)) { index[length]=i; if (i==oldtype) curindex=length; length++; } } for (i=0;iiHeight) { if (curindex<=(iHeight/2)) offset=0; else if (curindex>=(length-iHeight/2)) offset=length-iHeight; else offset=curindex-iHeight/2; } else { offset=0; } for (i=1;i<16;i++) { unsigned char col; char buffer[9]; col=i; if (editcol==i) col|=0x80; snprintf(buffer, sizeof(buffer), "color % 2d", i); displaystr(Top+i, Left+Mid+1, col, buffer, 9); } for (i=0;i=length) break; if ((!editcol)&&((offset+i)==curindex)) col=0x80; else col=0; col|=fsTypeCols[index[offset+i]&0xFF]; displaystr(Top+i+1, Left+1, col, mdbGetModTypeString(index[offset+i]), 4); } framelock(); while (ekbhit()) { switch(egetch()) { case KEY_RIGHT: editcol = fsTypeCols[index[curindex]&0xFF]; break; case KEY_LEFT: if (editcol) { char secname[20]; fsTypeCols[index[curindex]&0xff]=editcol; snprintf(secname, sizeof(secname), "filetype %d", index[curindex]); cfSetProfileInt(secname, "color", editcol, 10); cfStoreConfig(); editcol=0; } break; case KEY_UP: if (editcol) { if (editcol>1) editcol--; } else { if (curindex) curindex--; } break; case KEY_DOWN: if (editcol) { if (editcol<15) editcol++; } else { if ((curindex+1)=sizeof(str)) l=sizeof(str)-1; strcpy(str, s); str[l]=0; curpos=strlen(p); cmdlen=strlen(p); setcurshape(1); while (1) { displaystr(y, x, 0x8F, p+scrolled, w); setcur(y, x+curpos-scrolled); while (!ekbhit()) framelock(); while (ekbhit()) { uint16_t key=egetch(); if ((key>=0x20)&&(key<=0xFF)) { if (insmode) { if (cmdlen=w) scrolled+=8; /* while ((curpos-scrolled)<0) scrolled-=8; */ } } } static void fsEditChan(int y, int x, uint8_t *chan) { int curpos=0; char str[3]; convnum(*chan, str, 10, 2, 0); setcurshape(2); while (1) { displaystr(y, x, 0x8F, str, 2); setcur(y, x+curpos); while (!ekbhit()) framelock(); while (ekbhit()) { uint16_t key=egetch(); switch (key) { case ' ': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (key==' ') key='0'; if ((curpos==0)&&(key>='4')) break; if (curpos==0) str[1]='0'; if ((curpos==1)&&(str[0]=='3')&&(key>'2')) break; if (curpos<2) str[curpos]=key; case KEY_RIGHT: curpos="\x01\x02\x02"[curpos]; break; case KEY_BACKSPACE: case KEY_LEFT: curpos="\x00\x00\x01"[curpos]; if (key==KEY_BACKSPACE) str[curpos]='0'; break; case KEY_ESC: setcurshape(0); return; case _KEY_ENTER: *chan=(str[0]-'0')*10+str[1]-'0'; setcurshape(0); return; case KEY_ALT_K: cpiKeyHelp(KEY_RIGHT, "Move cursor right"); cpiKeyHelp(KEY_LEFT, "Move cursor left"); cpiKeyHelp(KEY_BACKSPACE, "Move cursor right"); cpiKeyHelp(KEY_ESC, "Cancel changes"); cpiKeyHelp(_KEY_ENTER, "Submit changes"); cpiKeyHelpDisplay(); break; } } } } static void fsEditPlayTime(int y, int x, uint16_t *playtime) { char str[7]; int curpos; convnum((*playtime)/60, str, 10, 3, 0); str[3]=':'; convnum((*playtime)%60, str+4, 10, 2, 0); curpos=(str[0]!='0')?0:(str[1]!='0')?1:2; setcurshape(2); while (1) { displaystr(y, x, 0x8F, str, 6); setcur(y, x+curpos); while (!ekbhit()) framelock(); while (ekbhit()) { uint16_t key=egetch(); switch (key) { case ' ': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (key==' ') key='0'; if ((curpos==4)&&(key>'5')) break; if (curpos<6) str[curpos]=key; case KEY_RIGHT: curpos="\x01\x02\x04\x05\x05\x06\x06"[curpos]; break; case KEY_BACKSPACE: case KEY_LEFT: /*left*/ curpos="\x00\x00\x01\x02\x02\x04\x05"[curpos]; if (key==8) str[curpos]='0'; break; case KEY_ESC: setcurshape(0); return; case _KEY_ENTER: *playtime=((((str[0]-'0')*10+str[1]-'0')*10+str[2]-'0')*6+str[4]-'0')*10+str[5]-'0'; setcurshape(0); return; case KEY_ALT_K: cpiKeyHelp(KEY_RIGHT, "Move cursor right"); cpiKeyHelp(KEY_LEFT, "Move cursor left"); cpiKeyHelp(KEY_BACKSPACE, "Move cursor right"); cpiKeyHelp(KEY_ESC, "Cancel changes"); cpiKeyHelp(_KEY_ENTER, "Submit changes"); cpiKeyHelpDisplay(); break; } } } } static void fsEditDate(int y, int x, uint32_t *date) { char str[11]; int curpos=0; convnum((*date)&0xFF, str, 10, 2, 0); str[2]='.'; convnum(((*date)>>8)&0xFF, str+3, 10, 2, 0); str[5]='.'; convnum((*date)>>16, str+6, 10, 4, 0); setcurshape(2); while (1) { displaystr(y, x, 0x8F, str, 10); setcur(y, x+curpos); while (!ekbhit()) framelock(); while (ekbhit()) { uint16_t key=egetch(); switch (key) { case '\'': if (curpos==6) { str[6]=str[7]='0'; curpos=8; } break; case ' ': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (key==' ') key='0'; if ((curpos==0)&&(key>='4')) break; if (curpos==0) str[1]='0'; if ((curpos==1)&&(str[0]=='3')&&(key>'1')) break; if ((curpos==3)&&(key>'1')) break; if (curpos==3) str[4]='0'; if ((curpos==4)&&(str[3]=='1')&&(key>'2')) break; if (curpos<10) str[curpos]=key; case KEY_RIGHT: curpos="\x01\x03\x03\x04\x06\x06\x07\x08\x09\x0A\x0A"[curpos]; break; case KEY_BACKSPACE: case KEY_LEFT: curpos="\x00\x00\x01\x01\x03\x04\x04\x06\x07\x08\x09"[curpos]; if (key==KEY_BACKSPACE) str[curpos]='0'; break; case KEY_ESC: setcurshape(0); return; case _KEY_ENTER: *date=((str[0]-'0')*10+str[1]-'0')|(((str[3]-'0')*10+str[4]-'0')<<8)|(((((str[6]-'0')*10+str[7]-'0')*10+str[8]-'0')*10+str[9]-'0')<<16); setcurshape(0); return; case KEY_ALT_K: cpiKeyHelp(KEY_RIGHT, "Move cursor right"); cpiKeyHelp(KEY_LEFT, "Move cursor left"); cpiKeyHelp(KEY_BACKSPACE, "Move cursor right"); cpiKeyHelp(KEY_ESC, "Cancel changes"); cpiKeyHelp(_KEY_ENTER, "Submit changes"); cpiKeyHelpDisplay(); break; } } } } static int fsEditFileInfo(struct modlistentry *fileref) { if (!mdbGetModuleInfo(&mdbEditBuf, fileref->fileref)) return 1; if (plScrWidth>=132) switch (editpos) { case 0: fsEditString(plScrHeight-5, 42, plScrWidth - 100, sizeof(mdbEditBuf.modname), mdbEditBuf.modname); break; case 1: mdbEditBuf.modtype = fsEditModType(mdbEditBuf.modtype); break; case 2: fsEditChan(plScrHeight-5, plScrWidth - 27, &mdbEditBuf.channels); break; case 3: fsEditPlayTime(plScrHeight-5, plScrWidth - 9, &mdbEditBuf.playtime); break; case 4: fsEditString(plScrHeight-4, 42, plScrWidth - 100, sizeof(mdbEditBuf.composer), mdbEditBuf.composer); break; case 5: fsEditString(plScrHeight-4, plScrWidth - 46, 31, sizeof(mdbEditBuf.style), mdbEditBuf.style); break; case 6: fsEditDate(plScrHeight-3, 42, &mdbEditBuf.date); break; case 7: fsEditString(plScrHeight-3, 66, plScrWidth - 69, sizeof(mdbEditBuf.comment), mdbEditBuf.comment); break; } else switch (editpos) { case 0: fsEditString(plScrHeight-6, 35, plScrWidth - 48, sizeof(mdbEditBuf.modname), mdbEditBuf.modname); break; case 1: /*fsEditString(plScrHeight-6, plScrWidth - 5, 4, 4, typeidx);*/ mdbEditBuf.modtype = fsEditModType(mdbEditBuf.modtype); break; case 2: fsEditChan(plScrHeight-4, plScrWidth - 3, &mdbEditBuf.channels); break; case 3: fsEditPlayTime(plScrHeight-4, plScrWidth - 22, &mdbEditBuf.playtime); break; case 4: fsEditString(plScrHeight-5, 13, plScrWidth - 47, sizeof(mdbEditBuf.composer), mdbEditBuf.composer); break; case 5: fsEditString(plScrHeight-4, 13, plScrWidth - 49, sizeof(mdbEditBuf.style), mdbEditBuf.style); break; case 6: fsEditDate(plScrHeight-5, plScrWidth - 22, &mdbEditBuf.date); break; case 7: fsEditString(plScrHeight-3, 13, plScrWidth - 17, sizeof(mdbEditBuf.comment), mdbEditBuf.comment); break; } /* if (editpos==1) { typeidx[4]=0; mdbEditBuf.modtype=mdbReadModType(typeidx); }*/ if (!mdbWriteModuleInfo(fileref->fileref, &mdbEditBuf)) return 0; return 1; } static char fsEditViewPath(void) { char path[PATH_MAX+NAME_MAX+1]; /*char *p=path;*/ snprintf(path, sizeof(path), "%s%s", curdirpath, curmask); if (fsEditString(1, 0, plScrWidth, sizeof(path), path)) { struct dmDrive *drives=dmDrives; char _drive[NAME_MAX+1]; char _path[PATH_MAX+1]; char _name[NAME_MAX+1]; char _ext[NAME_MAX+1]; uint32_t newcurrentpath; _splitpath(path, _drive, _path, _name, _ext); while (drives) { if (strcasecmp(_drive, drives->drivename)) { drives=drives->next; continue; } dmCurDrive=drives; if (strlen(_path)) { newcurrentpath = dirdbResolvePathWithBaseAndRef(dmCurDrive->basepath, _path); dirdbUnref(dirdbcurdirpath); dirdbUnref(dmCurDrive->currentpath); dirdbcurdirpath = dmCurDrive->currentpath = newcurrentpath; } dirdbGetFullName(dirdbcurdirpath, curdirpath, DIRDB_FULLNAME_ENDSLASH); dirdbRef(dirdbcurdirpath); if (strlen(curdirpath)+strlen(_name)+strlen(_ext)<=PATH_MAX) { strcpy(curmask, _name); strcat(curmask, _ext); } break; } if (!fsScanDir(0)) return 0; } return 1; } signed int fsFileSelect(void) { int win=0; unsigned long i; int curscanned=0; struct modlistentry *m; plSetTextMode(fsScrType); fsScrType=plScrType; isnextplay=NextPlayNone; quickfindpos=0; if (fsPlaylistOnly) return 0; while (1) { int firstv, firstp; uint16_t c; struct modlist *curlist; dirwinheight=plScrHeight-4; if (fsEditWin||editmode) dirwinheight-=(plScrWidth>=132)?5:6; if (!playlist->num) { win=0; playlist->pos=0; } else { if (playlist->pos>=playlist->num) playlist->pos=playlist->num-1; /* if (playlist->pos<0) playlist->pos=0; */ } if (!currentdir->num) { /* this should never happen */ currentdir->pos=0; } else { if (currentdir->pos>=currentdir->num) currentdir->pos=currentdir->num-1; /* if (currentdir->pos<0) currentdir->pos=0; */ } firstv=currentdir->pos-dirwinheight/2; if ((unsigned)(firstv+dirwinheight)>currentdir->num) firstv=currentdir->num-dirwinheight; if (firstv<0) firstv=0; firstp=playlist->pos-dirwinheight/2; if ((unsigned)(firstp+dirwinheight)>playlist->num) firstp=playlist->num-dirwinheight; if (firstp<0) firstp=0; if (!win) m=modlist_getcur(currentdir); else m=modlist_getcur(playlist); fsShowDir(firstv, win?(unsigned)~0:currentdir->pos, firstp, win?playlist->pos:(unsigned)~0, editmode?editpos:~0, m, win); if (!ekbhit()&&fsScanNames) { if (curscanned||(mdbInfoRead(m->fileref))) { while (((!win)||(scanposp>=playlist->num)) && (scanposfnum)) { struct modlistentry *scanm; if ((scanm=modlist_get(currentdir, scanposf++))) if ((scanm->flags&MODLIST_FLAG_FILE)&&(!(scanm->flags&MODLIST_FLAG_VIRTUAL))) if (!mdbInfoRead(scanm->fileref)) { mdbScan(scanm); break; } } while (((win)||(scanposf>=currentdir->num)) && (scanpospnum)) { struct modlistentry *scanm; if ((scanm=modlist_get(playlist, scanposp++))) if ((scanm->flags&MODLIST_FLAG_FILE)&&(!(scanm->flags&MODLIST_FLAG_VIRTUAL))) if (!mdbInfoRead(scanm->fileref)) { mdbScan(scanm); break; } } framelock(); } else { curscanned=1; if ((m->flags&MODLIST_FLAG_FILE)&&((!(m->flags&MODLIST_FLAG_VIRTUAL))||fsScanInArc)) /* dirty hack to stop scanning in .tar.gz while scrolling */ mdbScan(m); } continue; } c=egetch(); curscanned=0; #ifdef DOS32 if(c==0xF8) /* : screen shot */ { TextScreenshot(fsScrType); continue; } #endif if (((c>=32)&&(c<=255)&&(c!=KEY_CTRL_BS))||(c==KEY_BACKSPACE)) { if (c==KEY_BACKSPACE) { if (quickfindpos) quickfindpos--; if ((quickfindpos==8)&&(quickfind[8]=='.')) while (quickfindpos&&(quickfind[quickfindpos-1]==' ')) quickfindpos--; } else if (quickfindpos<12) { if ((c=='.')&&(quickfindpos&&(*quickfind!='.'))) { while (quickfindpos<9) quickfind[(int)quickfindpos++]=' '; quickfind[8]='.'; } else if (quickfindpos!=8) quickfind[(int)quickfindpos++]=toupper(c); } memcpy(quickfind+quickfindpos, " . "+quickfindpos, 12-quickfindpos); if (!quickfindpos) continue; if (!win) currentdir->pos=modlist_fuzzyfind(currentdir, quickfind); else playlist->pos=modlist_fuzzyfind(playlist, quickfind); continue; } quickfindpos=0; curlist=(win?playlist:currentdir); m=modlist_getcur(curlist); /* this is not actually needed, m should be preserved from above logic */ switch (c) { case KEY_ALT_K: cpiKeyHelp(KEY_ESC, "Exit"); cpiKeyHelp(KEY_CTRL_BS, "Stop filescanning"); cpiKeyHelp(KEY_ALT_S, "Stop filescanning"); cpiKeyHelp(KEY_TAB, "Toggle between filelist and playlist"); cpiKeyHelp(KEY_SHIFT_TAB, "Toggle between lists and editwindow"); cpiKeyHelp(KEY_ALT_E, "Toggle between lists and editwindow"); cpiKeyHelp(KEY_ALT_I, "Cycle file-list mode (fullname, title, time etc)"); cpiKeyHelp(KEY_ALT_C, "Show setup dialog"); cpiKeyHelp(KEY_ALT_P, "Save playlist"); cpiKeyHelp(KEY_F(1), "Show help"); cpiKeyHelp(KEY_ALT_R, "Rescan selected file"); cpiKeyHelp(KEY_ALT_Z, "Toggle resolution if possible (mode 0 and 7)"); cpiKeyHelp(KEY_ALT_ENTER, "Edit path"); cpiKeyHelp(KEY_CTRL_ENTER, "Edit path"); cpiKeyHelp(_KEY_ENTER, "Play selected file, or open selected directory/arc/playlist"); cpiKeyHelp(KEY_UP, "Move cursor up"); cpiKeyHelp(KEY_DOWN, "Move cursor down"); cpiKeyHelp(KEY_PPAGE, "Move cursor a page up"); cpiKeyHelp(KEY_NPAGE, "Move cursor a page down"); cpiKeyHelp(KEY_HOME, "Move cursor home"); cpiKeyHelp(KEY_END, "Move cursor end"); if (editmode) { cpiKeyHelp(KEY_RIGHT, "Move cursor right"); cpiKeyHelp(KEY_LEFT, "Move cursor left"); } else { cpiKeyHelp(KEY_INSERT, "Append file/directory into the playlist"); cpiKeyHelp(KEY_DELETE, "Remove file/directory from the playlist"); cpiKeyHelp(KEY_CTRL_RIGHT, "Append all files in current directory into the playlist"); cpiKeyHelp(KEY_CTRL_LEFT, "Remove all files in current directory from the playlist"); if (!win) { cpiKeyHelp(KEY_CTRL_UP, "Move the selected file up in playlist"); cpiKeyHelp(KEY_CTRL_DOWN, "Move the selected file down in the playlist"); cpiKeyHelp(KEY_CTRL_PGUP, "Move the selected file up one page in playlist"); cpiKeyHelp(KEY_CTRL_PGDN, "Move the selected file down one page in the playlist"); } } cpiKeyHelpDisplay(); break; case KEY_ESC: return 0; case KEY_ALT_R: if (m->flags&MODLIST_FLAG_FILE) { if (!mdbGetModuleInfo(&mdbEditBuf, m->fileref)) return -1; mdbEditBuf.modtype = mtUnRead; if (!mdbWriteModuleInfo(m->fileref, &mdbEditBuf)) return -1; } case KEY_CTRL_BS: case KEY_ALT_S: scanposp=~0; scanposf=~0; break; case KEY_TAB: win=!win; break; case KEY_SHIFT_TAB: case KEY_ALT_E: editmode=!editmode; break; case KEY_ALT_I: /* TODO-keys case KEY_ALT_TAB:*/ fsInfoMode=(fsInfoMode+1)%5; break; case KEY_ALT_C: fsSetup(); plSetTextMode(fsScrType); fsScrType=plScrType; break; case KEY_ALT_P: if (editmode) break; fsSavePlayList(playlist); break; case KEY_F(1): if (!fsHelp2()) return -1; plSetTextMode(fsScrType); break; case KEY_ALT_Z: fsScrType=(fsScrType==0)?7:0; plSetTextMode(fsScrType); break; case KEY_CTRL_ENTER: case KEY_ALT_ENTER: if (!fsEditViewPath()) return -1; break; case _KEY_ENTER: if (editmode) if (m->flags&MODLIST_FLAG_FILE) { if (!fsEditFileInfo(m)) return -1; break; } if (win) { if (!playlist->num) break; isnextplay=NextPlayPlaylist; return 1; } else { if (m->flags&(MODLIST_FLAG_DIR|MODLIST_FLAG_DRV|MODLIST_FLAG_ARC)) { uint32_t olddirpath; unsigned int i; olddirpath = dmCurDrive->currentpath; dirdbRef(olddirpath); dirdbUnref(dirdbcurdirpath); dirdbcurdirpath=m->dirdbfullpath; dirdbGetFullName(dirdbcurdirpath, curdirpath, DIRDB_FULLNAME_ENDSLASH); dirdbRef(dirdbcurdirpath); dmCurDrive=(struct dmDrive *)m->drive; dirdbUnref(dmCurDrive->currentpath); dmCurDrive->currentpath = m->dirdbfullpath; dirdbRef(dmCurDrive->currentpath); fsScanDir(0); for (i=0;inum;i++) { if (currentdir->files[i]->dirdbfullpath==olddirpath) break; } dirdbUnref(olddirpath); if (inum) currentdir->pos=i; } else if (m->flags&(MODLIST_FLAG_FILE|MODLIST_FLAG_VIRTUAL)) { nextplay=m; isnextplay=NextPlayBrowser; return 1; } } break; case KEY_UP: /*case 0x4800: // up*/ if (editmode) if (plScrWidth>=132) editpos="\x00\x01\x02\x03\x00\x01\x04\x05"[editpos]; else editpos="\x00\x01\x06\x06\x00\x04\x00\x05"[editpos]; else if (!win) { if (currentdir->pos) currentdir->pos--; } else { if (playlist->pos) playlist->pos--; } break; case KEY_DOWN: /*case 0x5000: // down*/ if (editmode) if (plScrWidth>=132) editpos="\x04\x05\x05\x05\x06\x07\x06\x07"[editpos]; else editpos="\x04\x06\x07\x07\x05\x07\x03\x07"[editpos]; else if (!win) { if ((currentdir->pos+1) < currentdir->num) currentdir->pos++; } else { if ((playlist->pos+1) < playlist->num) playlist->pos++; } break; case KEY_PPAGE: /*case 0x4900: //pgup*/ { int sub = editmode?1:dirwinheight; if (!win) { if (currentdir->pos < sub) currentdir->pos = 0; else currentdir->pos -= sub; } else { if (playlist->pos < sub) playlist->pos = 0; else playlist->pos -= sub; } } break; case KEY_NPAGE: { int add = editmode?1:dirwinheight; /*case 0x5100: //pgdn*/ if (!win) { if (currentdir->num <= (currentdir->pos + add)) currentdir->pos = currentdir->num - 1; else currentdir->pos += add; } else { if (playlist->num <= (playlist->pos + add)) playlist->pos = playlist->num - 1; else playlist->pos += add; } } break; case KEY_HOME: /*case 0x4700: //home*/ if (editmode) break; if (!win) currentdir->pos=0; else playlist->pos=0; break; case KEY_END: /*case 0x4F00: //end*/ if (editmode) break; if (!win) currentdir->pos=currentdir->num-1; else playlist->pos=playlist->num-1; break; case KEY_RIGHT: /*case 0x4D00: // right*/ if (editmode) { if (plScrWidth>=132) editpos="\x01\x02\x03\x03\x05\x05\x07\x07"[editpos]; else editpos="\x01\x01\x02\x02\x06\x03\x06\x07"[editpos]; } break; case KEY_INSERT: /*case 0x5200: // add*/ if (editmode) break; if (win) { /*if (!*/modlist_append(playlist, m)/*) return -1*/; /*playlist->pos=playlist->num-1; */ scanposp=fsScanNames?0:~0; } else { if (m->flags&MODLIST_FLAG_DIR) { if (!(fsReadDir(playlist, m->drive, m->dirdbfullpath, curmask, RD_PUTRSUBS))) return -1; } else if (m->flags&MODLIST_FLAG_FILE) { /*if (!*/modlist_append(playlist, m)/*) return -1*/; scanposp=fsScanNames?0:~0; } } break; case KEY_LEFT: /*case 0x4B00: // left*/ if (editmode) { if (plScrWidth>=132) editpos="\x00\x00\x01\x02\x04\x04\x06\x06"[editpos]; else editpos="\x00\x00\x03\x05\x04\x05\x04\x07"[editpos]; } break; case KEY_DELETE: /*case 0x5300: // del*/ if (editmode) break; if (win) modlist_remove(playlist, playlist->pos, 1); else { long f; if (m->flags&MODLIST_FLAG_DIR) { struct modlist *tl = modlist_create(); struct modlistentry *me; int f; if (!(fsReadDir(tl, m->drive, m->dirdbfullpath, curmask, RD_PUTRSUBS))) return -1; for (i=0;inum;i++) { me=modlist_get(tl, i); if ((f=modlist_find(playlist, me->dirdbfullpath))>=0) modlist_remove(playlist, f, 1); } modlist_free(tl); } else if (m->flags&MODLIST_FLAG_FILE) { f=modlist_find(playlist, m->dirdbfullpath); if (f!=-1) modlist_remove(playlist, f, 1); } } break; case KEY_CTRL_RIGHT: /* case 0x7400: //ctrl-right */ /* case 0x9200: //ctrl-insert TODO keys */ { if (editmode) break; for (i=0; inum; i++) { struct modlistentry *me; me=modlist_get(currentdir, i); if (me->flags&MODLIST_FLAG_FILE) { /*if (!*/modlist_append(playlist, me)/*) return -1*/; scanposp=fsScanNames?0:~0; } } break; } case KEY_CTRL_LEFT: /* case 0x7300: //ctrl-left */ /* case 0x9300: //ctrl-delete TODO keys */ if (editmode) break; modlist_remove(playlist, 0, playlist->num); break; /* case 0x2500: // alt-k TODO keys.... alt-k is now in use by key-helper if (editmode||win) break; if (m.fileref<=0xFFFC) if (fsQueryKill(m)) if (!fsScanDir(2)) return -1; break; #ifndef WIN32 case 0x3200: // alt-m TODO keys !!!!!!!! STRANGE THINGS HAPPENS IF YOU ENABLE HIS UNDER W32!! if (editmode||win) break; if (m.fileref<=0xFFFC) if (fsQueryMove(m)) if (!fsScanDir(1)) return -1; break; #endif case 0x3000: // alt-b TODO keys if (m.fileref<=0xFFFC) { mdbGetModuleInfo(mdbEditBuf, m.fileref); mdbEditBuf.flags1^=MDB_BIGMODULE; mdbWriteModuleInfo(m.fileref, mdbEditBuf); } break; case 0x1100: // alt-w TODO keys if (m.fileref<0xFFFC) fsSaveModInfo(m); break; case 0x1e00: // alt-a TODO keys if (editmode) break; fsSaveModInfoML(curlist); break; */ case KEY_CTRL_UP: /* case 0x8d00: //ctrl-up */ if (editmode||!win) break; if (!playlist->pos) break; modlist_swap(playlist, playlist->pos-1, playlist->pos); playlist->pos-=1; break; case KEY_CTRL_DOWN: /* case 0x9100: //ctrl-down */ if (editmode||!win) break; if ((playlist->pos+1)>=playlist->num) break; modlist_swap(playlist, playlist->pos, playlist->pos+1); playlist->pos++; break; case KEY_CTRL_PGUP: /* case 0x8400: //ctrl-pgup */ if (editmode||!win) break; i=(playlist->pos>dirwinheight)?dirwinheight:playlist->pos; modlist_swap(playlist, playlist->pos, playlist->pos-i); playlist->pos-=i; break; case KEY_CTRL_PGDN: /* case 0x7600: //ctrl-pgdown */ if (editmode||!win) break; i=((playlist->num-1-playlist->pos)>dirwinheight)?dirwinheight:(playlist->num-1-playlist->pos); modlist_swap(playlist, playlist->pos, playlist->pos+i); playlist->pos+=i; break; /* case 0x7700: //ctrl-home TODO keys if (editmode||!win) break; playlist.remove(playlist.pos, 1); playlist.insert(0, &m, 1); playlist.pos=0; break; case 0x7500: //ctrl-end TODO keys if (editmode||!win) break; playlist.remove(playlist.pos, 1); playlist.insert(playlist.num, &m, 1); playlist.pos=playlist.num-1; break;*/ } } /*return 0; the above while loop doesn't go to this point */ } static int stdReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { struct modlistentry m; struct dmDrive *d; if (opt&RD_PUTSUBS) { uint32_t dirdbparent = dirdbGetParentAndRef(path); if (path!=drive->basepath) { memset(&m, 0, sizeof(struct modlistentry)); m.drive=drive; strcpy(m.name, "/"); strcpy(m.shortname, "/"); m.flags=MODLIST_FLAG_DIR; m.dirdbfullpath=drive->basepath; modlist_append(ml, &m); if (dirdbparent!=DIRDB_NOPARENT) { memset(&m, 0, sizeof(struct modlistentry)); m.drive=drive; strcpy(m.name, ".."); strcpy(m.shortname, ".."); m.flags=MODLIST_FLAG_DIR; m.dirdbfullpath=dirdbparent; modlist_append(ml, &m); } } if (dirdbparent!=DIRDB_NOPARENT) dirdbUnref(dirdbparent); for (d=dmDrives;d;d=d->next) { memset(&m, 0, sizeof(struct modlistentry)); m.drive=d; strcpy(m.name, d->drivename); strncpy(m.shortname, d->drivename, 12); m.flags=MODLIST_FLAG_DRV; m.dirdbfullpath=d->currentpath; dirdbRef(m.dirdbfullpath); modlist_append(ml, &m); } } return 1; } static void fsSavePlayList(const struct modlist *ml) { char path[PATH_MAX+1]; int mlTop=plScrHeight/2-2; unsigned int i; char dr[NAME_MAX+1]; char di[PATH_MAX+1]; char fn[NAME_MAX+1]; char ext[NAME_MAX+1]; FILE *f; displayvoid(mlTop+1, 5, plScrWidth-10); displayvoid(mlTop+2, 5, plScrWidth-10); displayvoid(mlTop+3, 5, plScrWidth-10); displaystr(mlTop, 4, 0x04, "\xda", 1); for (i=5;i<(plScrWidth-5);i++) displaystr(mlTop, i, 0x04, "\xc4", 1); displaystr(mlTop, plScrWidth-5, 0x04, "\xbf", 1); displaystr(mlTop+1, 4, 0x04, "\xb3", 1); displaystr(mlTop+2, 4, 0x04, "\xb3", 1); displaystr(mlTop+3, 4, 0x04, "\xb3", 1); displaystr(mlTop+1, plScrWidth-5, 0x04, "\xb3", 1); displaystr(mlTop+2, plScrWidth-5, 0x04, "\xb3", 1); displaystr(mlTop+3, plScrWidth-5, 0x04, "\xb3", 1); displaystr(mlTop+4, 4, 0x04, "\xc0", 1); for (i=5;i<(plScrWidth-5);i++) displaystr(mlTop+4, i, 0x04, "\xc4", 1); displaystr(mlTop+4, plScrWidth-5, 0x04, "\xd9", 1); displaystr(mlTop+1, 5, 0x0b, "Store playlist, please give filename (.pls format):", 50); displaystr(mlTop+3, 5, 0x0b, "-- Abort with escape --", 23); _splitpath(curdirpath, dr, di, NULL, NULL); *fn=0; *ext=0; _makepath(path, dr, di, fn, ext); if (!fsEditString(mlTop+2, 5, plScrWidth-10, sizeof(path), path)) return; _splitpath(path, dr, di, fn, ext); if (!*ext) strcpy(ext, ".pls"); if (strcmp(dr, "file:")) { fprintf(stderr, "[filesel] file: is the only supported transport currently\n"); return; } _makepath(path, NULL, di, fn, ext); if (!(f=fopen(path, "w"))) { perror("fopen()"); /* TODO */ return; } fprintf(f, "[playlist]\n"); fprintf(f, "NumberOfEntries=%d\n", ml->num); for (i=0; inum; i++) { char npath[PATH_MAX+1]; struct modlistentry *m; fprintf(f, "File%d=",i+1); m=modlist_get(ml, i); if (m->drive==dmFILE) { dirdbGetFullName(m->dirdbfullpath, npath, 0); fputs(npath, f); } else { dirdbGetFullName(m->dirdbfullpath, npath, DIRDB_FULLNAME_NOBASE); genreldir(di, npath, path); fputs(path, f); } fprintf(f, "\n"); } fclose(f); fsScanDir(1); } #if 0 /* code for fullpath2 taken from bc3.1, converted and modified..., and redone for unix world.. anything left of the code??? */ static void reducepath(char *buf) { char c; char *src,*dst; src=dst=buf; while (1) { c=*src++; if (!c||(c=='/')) { if ((dst[-1]=='.')&&(dst[-2]=='/')) dst-=2; else if ((dst[-1]=='.')&&(dst[-2]=='.')&&(dst[-3]=='/')) { /*if (dst[-4]!=':') we don't have drive letters on this OS*/ { dst-=3; while (*--dst!='/'); } } if (!c) { if (dst[-1]=='/') dst--; /*if (dst[-1]==':') still no drive letters on this OS *dst++='\\';*/ *dst=0; break; } else *dst++='/'; } /*else *dst++=toupper(c); and we are case sentive */ } } /* We can't relay on files having 8:3 format in unix, so we have redone this part quite heavily static void convfilename12wc(char *c, const char *f, const char *e) { int i; for (i=0; i<8; i++) *c++=(*f=='*')?'?':*f?*f++:' '; for (i=0; i<4; i++) *c++=(*e=='*')?'?':*e?*e++:' '; for (i=0; i<12; i++) c[i-12]=toupper(c[i-12]); } void fsConv12FileName(char *f, const char *c) { int i; for (i=0; i<8; i++) if (c[i]==' ') break; else *f++=c[i]; for (i=8; i<12; i++) if (c[i]==' ') break; else *f++=c[i]; *f=0; } static void conv12filenamewc(char *f, const char *c) { char *f0=f; short i; for (i=0; i<8; i++) if (c[i]==' ') break; else *f++=c[i]; if (i==8) { for (i=7; i>=0; i--) if (c[i]!='?') break; if (++i<7) { f-=8-i; *f++='*'; } } for (i=8; i<12; i++) if (c[i]==' ') break; else *f++=c[i]; if (i==12) { for (i=11; i>=9; i--) if (c[i]!='?') break; if (++i<10) { f-=12-i; *f++='*'; } } *f=0; } int fsMatchFileName12(const char *a, const char *b) { int i; for (i=0; i<12; i++, a++, b++) if ((i!=8)&&(*b!='?')&&(*a!=*b)) break; return i==12; }*/ struct directorynode { char name[_MAX_NAME+1]; unsigned short parent; }; static struct directorynode *dmTree; static unsigned short *dmReloc; static unsigned short dmMaxNodes; static unsigned short dmNumNodes; static unsigned char dmCurDrive; static unsigned short dmDriveDirs[27]; static unsigned short dmGetPathReference(const char *p, const char *endp) { const char *stp; unsigned short v; char subdir[_MAX_NAME+1]; unsigned short *min; unsigned short num; unsigned short mn; if (endp[-1]=='/') endp--; stp=endp; while (((stp+_MAX_NAME-1)>endp)&&(stp>p)&&(stp[-1]!='/')) stp--; if (stp!=p) { v=dmGetPathReference(p, stp); if (v==0xFFFF) return 0xFFFF; } else v=0xFFFF; memcpy(subdir, stp, endp-stp); subdir[endp-stp]='\\'; subdir[endp-stp+1]=0; strupr(subdir); min=dmReloc; num=dmNumNodes; while (num) { int res=strcmp(subdir, dmTree[min[num>>1]].name); if (!res) { res=dmTree[min[num>>1]].parent-v; if (!res) return min[num>>1]; } if (res<0) num>>=1; else { min+=(num>>1)+1; num=(num-1)>>1; } } mn=min-dmReloc; if (dmNumNodes==dmMaxNodes) { void *n1, *n2; dmMaxNodes+=256; n1=realloc(dmTree, sizeof (*dmTree)*dmMaxNodes); n2=realloc(dmReloc, sizeof (*dmReloc)*dmMaxNodes); if (!n1||!n2) return 0xFFFF; dmTree=(directorynode *)n1; dmReloc=(unsigned short *)n2; } mymemmovew(dmReloc+mn+1, dmReloc+mn, dmNumNodes-mn); dmReloc[mn]=dmNumNodes; strcpy(dmTree[dmNumNodes].name, subdir); dmTree[dmNumNodes].parent=v; return dmNumNodes++; } unsigned short dmGetPathReference(const char *p) { return dmGetPathReference(p, p+strlen(p)); } static unsigned short dmGetParent(unsigned short ref) { return (dmTree[ref].parent==0xFFFF)?ref:dmTree[ref].parent; } static unsigned short dmGetRoot(unsigned short ref) { while (dmTree[ref].parent!=0xFFFF) ref=dmTree[ref].parent; return ref; } char *dmGetPathRel(char *path, unsigned short ref, unsigned short base) { if ((ref==0xFFFF)||(ref==base)) { *path=0; return path; } if (ref>=0xFFE0) { path[0]='@'+ref-0xFFE0; path[1]=':'; path[2]=0; return path; } dmGetPathRel(path, dmTree[ref].parent, base); strcat(path, dmTree[ref].name); return path; } char *dmGetPath(char *path, unsigned short ref) { return dmGetPathRel(path, ref, 0xFFFF); } static unsigned short dmConvertReference(unsigned short ref) { unsigned char *drv; char path[_MAX_PATH]; if (ref<0xFFE0) return ref; drv=ref-0xFFE0; if (dmDriveDirs[drv]<0xFFE0) return dmDriveDirs[drv]; if (drv) { unsigned int savedrive, dum; _dos_getdrive(&savedrive); _dos_setdrive(drv, &dum); if (!getcwd(path, _MAX_PATH)) { strcpy(path, "@:\\"); path[0]+=drv; } _dos_setdrive(savedrive, &dum); } else strcpy(path, "@:\\"); dmDriveDirs[drv]=dmGetPathReference(path); return dmDriveDirs[drv]; } static unsigned short dmChangeDir(unsigned short dir) { dir=dmConvertReference(dir); if (dir==0xFFFF) return 0xFFFF; char path[_MAX_PATH]; dmGetPath(path, dir); char drive[_MAX_DRIVE]; _splitpath(path, drive, 0, 0, 0); dmCurDrive=*drive-'@'; dmDriveDirs[dmCurDrive]=dir; return dir; } unsigned short dmGetDriveDir(int drv) { return dmDriveDirs[drv]; } static unsigned short dmGetCurDir() { return dmGetDriveDir(dmCurDrive); } static char dmFullPath(char *path) { char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char name[_MAX_FNAME]; char ext[_MAX_EXT]; strupr(path); _splitpath(path, drive, dir, name, ext); if (!*drive||(*drive<'@')||(*drive>'Z')) *drive='@'+dmCurDrive; drive[1]=':'; drive[2]=0; if (dir[0]!='\\') { char dir2[_MAX_DIR*2]; unsigned short dr=dmConvertReference(dmDriveDirs[drive[0]-'@']); if (dr==0xFFFF) return 0; dmGetPath(path, dr); _splitpath(path, 0, dir2, 0, 0); strcat(dir2, dir); strcpy(dir, dir2); } _makepath(path, drive, dir, name, ext); reducepath(path); return 1; } struct mifentry { #define MIF_USED 1 #define MIF_DIRTY 2 unsigned short flags; unsigned short size; char name[12]; }; static mifentry *mifData; static unsigned long mifNum; static char mifDirty; static char mifInit() { mifDirty=0; mifData=0; mifNum=0; char path[_MAX_PATH]; strcpy(path, cfConfigDir); strcat(path, "CPMDZTAG.DAT"); long f=open(path, O_RDONLY|O_BINARY); if (f<0) return 1; char sig[16]; if (read(f, sig, 16)!=16) { close(f); return 1; } if (memcmp(sig, "MDZTagList\x1A\x00", 12)) { close(f); return 1; } mifNum=*(unsigned long*)(sig+12); if (!mifNum) { close(f); return 1; } mifData=new mifentry[mifNum]; if (!mifData) return 0; if (read(f, mifData, mifNum*sizeof(*mifData))!=(mifNum*sizeof(*mifData))) { delete mifData; mifNum=0; mifData=0; close(f); return 1; } close(f); return 1; } static void mifUpdate() { if (!mifDirty||!fsWriteModInfo) return; mifDirty=0; char path[_MAX_PATH]; strcpy(path, cfConfigDir); strcat(path, "CPMDZTAG.DAT"); long f=open(path, O_WRONLY|O_BINARY|O_CREAT, S_IREAD|S_IWRITE); if (f<0) return; lseek(f, 0, SEEK_SET); write(f, "MDZTagList\x1A\x00", 12); write(f, &mifNum, 4); long i=0,j; while (iendp) return 1; if (memicmp(ptr, "MODINFO", 7)) return 1; ptr+=7; short ver=0; while (ptrcmdp) *cmdp++=*ptr++; else ptr++; *cmdp=0; while (ptrargp) *argp++=*ptr++; else ptr++; while (argp>arg) if (isspace(argp[-1])) argp--; else break; *argp=0; while (ptrgen.name); strcat(buf, "\r\nSIZE "); ultoa(m->gen.size, buf+strlen(buf), 10); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); if (m->gen.modtype!=0xFF) { strcpy(buf, " TYPE "); strcat(buf, mdbGetModTypeString(m->gen.modtype)); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } if (*m->gen.modname) { strcpy(buf, " TITLE "); strcat(buf, m->gen.modname); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } if (m->gen.channels) { strcpy(buf, " CHANNELS "); ultoa(m->gen.channels, buf+strlen(buf), 10); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } if (m->gen.playtime) { strcpy(buf, " PLAYTIME "); ultoa(m->gen.playtime/60, buf+strlen(buf), 10); strcat(buf, ":00"); buf[strlen(buf)-2]+=(m->gen.playtime%60)/10; buf[strlen(buf)-1]+=m->gen.playtime%10; strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } if (m->gen.date) { strcpy(buf, " CDATE "); ultoa(m->gen.date&0xFF, buf+strlen(buf), 10); strcat(buf, "."); ultoa((m->gen.date>>8)&0xFF, buf+strlen(buf), 10); strcat(buf, "."); ultoa(m->gen.date>>16, buf+strlen(buf), 10); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } if (m->gen.compref!=0xFFFF) { modinfoentry *m2=&mdbData[m->gen.compref]; if (*m2->comp.composer) { strcpy(buf, " COMPOSER "); strcat(buf, m2->comp.composer); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } if (*m2->comp.style) { strcpy(buf, " STYLE "); strcat(buf, m2->comp.style); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } } if ((m->gen.comref!=0xFFFF)&&*mdbData[m->gen.comref].comment) { strcpy(buf, " COMMENT "); strcat(buf, mdbData[m->gen.comref].comment); strcat(buf, "\r\n"); write(f, buf, strlen(buf)); } } struct modlist { modlistentry *files; signed long num; signed long max; signed long pos; long fuzfirst; unsigned short fuzval; char fuzmask[12]; modlist() { files=0; num=max=pos=0; } ~modlist() { delete files; } char insert(unsigned long before, const modlistentry *f, unsigned long n); char append(const modlistentry &f); void remove(unsigned long from, unsigned long n); void get(modlistentry *f, unsigned long from, unsigned long n) const; void getcur(modlistentry &f) const; /* char copy(modlist &dest, unsigned long to, unsigned long from, unsigned long n); */ void sort(); long find(const modlistentry &f); long fuzzyfind(const char *c); long fuzzyfindnext(); }; int fsReadDir(modlist &ml, unsigned short dirref, const char *mask, unsigned long opt); char modlist::insert(unsigned long before, const modlistentry *f, unsigned long n) { if (before>num) before=num; if ((num+n)>10000) return 1; if (pos>=before) pos+=n; if ((num+n)>max) { max=(num+n+255)&~255; void *t=realloc(files, sizeof(*files)*max); if (!t) return 0; files=(modlistentry *)t; } mymemmovep(files+before+n, files+before, num-before); mymemmovep(files+before, f, n); num+=n; return 1; } char modlist::append(const modlistentry &f) { return insert(num, &f, 1); } long modlist::find(const modlistentry &f) { long i; for (i=0; ifuzval) { fuzval=cur; fuzfirst=i; } } return fuzfirst; } long modlist::fuzzyfindnext() { long i; for (i=fuzfirst+1; inext) if (!readdirs->ReadDir(ml, dirref, mask, opt)) return 0; return 1; } static modlistentry nextplay; static unsigned char isnextplay; static modlist playlist; static modlist viewlist; static char curmask[12]; static char curdirpath[_MAX_PATH]; static short dirwinheight; static char quickfind[12]; static char quickfindpos; static unsigned long scanpos; static short editpos=0; static short editmode=0; static char fsExpandPath(char *dp, char *mask, const char *p) { char path[_MAX_PATH]; strcpy(path, p); if (!dmFullPath(path)) return 0; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char name[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath(path, drive, dir, name, ext); if (!(strchr(name, '*')||strchr(name, '?')||strchr(ext, '*')||strchr(ext, '?'))) { find_t fi; if (!_dos_findfirst(path, _A_RDONLY|_A_SUBDIR, &fi)&&((fi.attrib&_A_SUBDIR)||isarchive(ext))) { _makepath(dp, drive, dir, name, ext); memcpy(mask, curmask, 12); return 1; } if (!*ext) { _makepath(path, drive, dir, name, ".*"); if (!_dos_findfirst(path, _A_RDONLY, &fi)&&_dos_findnext(&fi)) { _splitpath(fi.name, 0, 0, 0, ext); if (isarchive(ext)) { _makepath(dp, drive, dir, name, ext); memcpy(mask, curmask, 12); return 1; } } } } char cmask[_MAX_NAME]; conv12filenamewc(cmask, curmask); _makepath(dp, drive, dir, 0, 0); if (!*name) _splitpath(cmask, 0, 0, name, 0); if (!*ext) _splitpath(cmask, 0, 0, 0, ext); convfilename12wc(mask, name, ext); return 1; } static char fsScanDir(int pos) { int op=0; switch (pos) { case 0: op=0; break; case 1: op=viewlist.pos; break; case 2: op=viewlist.pos?(viewlist.pos-1):0; break; } viewlist.remove(0, viewlist.num); if (!fsReadDir(viewlist, dmGetCurDir(), curmask, RD_PUTDSUBS|RD_PUTSUBS|(fsScanArcs?RD_ARCSCAN:0))) return 0; viewlist.sort(); viewlist.pos=(op>=viewlist.num)?(viewlist.num-1):op; quickfindpos=0; scanpos=fsScanNames?0:0xFFFFFFFF; dmGetPath(curdirpath, dmGetCurDir()); conv12filenamewc(curdirpath+strlen(curdirpath), curmask); adbUpdate(); return 1; } static void fsSaveModInfo(const modlistentry &m) { char path[_MAX_PATH]; dmGetPath(path, m.dirref); if (isarchivepath(path)) dmGetPath(path, dmGetParent(m.dirref)); char n[_MAX_NAME]; char fn[_MAX_FNAME]; fsConv12FileName(n, m.name); _splitpath(n, 0, 0, fn, 0); _makepath(n, 0, 0, fn, MIF_EXT); strcat(path, n); short f=open(path, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE); if (f<0) return; write(f, "MODINFO1\r\n\r\n", 12); mifAppendInfo(f, m.fileref); close(f); } static void fsSaveModInfoML(const modlist &ml) { char path[_MAX_PATH]; dmGetPath(path, dmGetCurDir()); if (!fsEditPath(path)) return; char dr[_MAX_DRIVE]; char di[_MAX_DIR]; char fn[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath(path, dr, di, fn, ext); if (!*ext) strcpy(ext, MIF_EXT); _makepath(path, dr, di, fn, ext); short f=open(path, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE); if (f<0) return; write(f, "MODINFO1\r\n\r\n", 12); long i; modlistentry m; for (i=0; i>=1; if (max<65536) break; } if (!buf) return 0; while (len) { int l=(len>max)?max:len; if (!fi.eread(buf, l)) return 0; if (!fo.ewrite(buf, l)) return 0; len-=l; } delete buf; fo.close(); fi.close(); unlink(src); return 1; } static int movetoarc(const char *dest, const char *src) { char path[_MAX_PATH]; char path2[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char name[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath(dest, drive, dir, name, ext); _makepath(path, drive, dir, 0, 0); _splitpath(src, drive, dir, 0, 0); _makepath(path2, drive, dir, name, ext); path[strlen(path)-1]=0; _splitpath(path, 0, 0, 0, ext); adbregstruct *packers; for (packers=adbPackers; packers; packers=packers->next) if (!stricmp(ext, packers->ext)) { if (stricmp(src, path2)) if (rename(src, path2)) return 0; conRestore(); int r=packers->Call(adbCallMoveTo, path, path2, ""); conSave(); plSetTextMode(fsScrType); return r; } return 0; } static int movefromarc(const char *dest, const char *src) { char path[_MAX_PATH]; char path2[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char name[_MAX_NAME]; char ext[_MAX_EXT]; _splitpath(src, drive, dir, fname, ext); _makepath(name, 0, 0, fname, ext); _makepath(path, drive, dir, 0, 0); _splitpath(dest, drive, dir, 0, 0); _makepath(path2, drive, dir, 0, 0); path[strlen(path)-1]=0; _splitpath(path, 0, 0, 0, ext); adbregstruct *packers; for (packers=adbPackers; packers; packers=packers->next) if (!stricmp(ext, packers->ext)) { conRestore(); int r=packers->Call(adbCallMoveFrom, path, name, path2); conSave(); plSetTextMode(fsScrType); if (!r) return 0; strcat(path2, name); if (stricmp(path2, dest)) if (rename(path2, dest)) return 0; return 1; } return 0; } static int movecrossarc(const char *dest, const char *src) { char spath[_MAX_PATH]; char dpath[_MAX_PATH]; char path[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char sname[_MAX_NAME]; char dname[_MAX_NAME]; char ext[_MAX_EXT]; char sext[_MAX_EXT]; char dext[_MAX_EXT]; _splitpath(src, drive, dir, fname, ext); _makepath(sname, 0, 0, fname, ext); _makepath(spath, drive, dir, 0, 0); _splitpath(dest, drive, dir, fname, ext); _makepath(dname, 0, 0, fname, ext); _makepath(dpath, drive, dir, 0, 0); spath[strlen(spath)-1]=0; dpath[strlen(dpath)-1]=0; _splitpath(spath, 0, 0, 0, sext); _splitpath(dpath, 0, 0, 0, dext); adbregstruct *spackers; for (spackers=adbPackers; spackers; spackers=spackers->next) if (!stricmp(sext, spackers->ext)) break; adbregstruct *dpackers; for (dpackers=adbPackers; dpackers; dpackers=dpackers->next) if (!stricmp(dext, dpackers->ext)) break; if (!spackers||!dpackers) return 0; conRestore(); if (!spackers->Call(adbCallMoveFrom, spath, sname, cfTempDir)) { conSave(); plSetTextMode(fsScrType); return 0; } strcpy(spath, cfTempDir); strcat(spath, sname); strcpy(path, cfTempDir); strcat(path, dname); if (stricmp(spath, path)) rename(spath, path); int r=dpackers->Call(adbCallMoveTo, dpath, path, ""); conSave(); plSetTextMode(fsScrType); return r; } static int fsQueryMove(modlistentry &m) { char path[_MAX_PATH]; char path2[_MAX_PATH]; int srctype=0; dmGetPath(path, m.dirref); if (isarchivepath(path)) srctype=1; if (m.fileref==0xFFFC) srctype=2; char name[_MAX_NAME]; fsConv12FileName(name, m.name); if (*fsDefMovePath) strcpy(path, fsDefMovePath); else dmGetPath(path, (m.fileref==0xFFFC)?dmGetParent(m.dirref):m.dirref); if (!fsEditPath(path)) return 0; dmFullPath(path); if (!*path) return 0; char ext[_MAX_EXT]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; find_t ft; if (path[strlen(path)-1]!='\\') { _splitpath(path, 0, 0, 0, ext); if (isarchive(ext)&&(srctype!=2)) strcat(path, "\\"); else #ifdef DOS32 if (!_dos_findfirst(path, _A_NORMAL|_A_SUBDIR, &ft)) if (ft.attrib&_A_SUBDIR) strcat(path, "\\"); #else if (!_dos_findfirst(path, _A_SUBDIR, &ft)) if (ft.attrib&_A_SUBDIR) strcat(path, "\\"); #endif } if (path[strlen(path)-1]=='\\') strcat(path, name); _splitpath(path, drive, dir, 0, 0); _makepath(path2, drive, dir, 0, 0); path2[strlen(path2)-1]=0; _splitpath(path2, 0, 0, 0, ext); int desttype=0; if (isarchive(ext)) #ifdef DOS32 if (_dos_findfirst(path2, _A_NORMAL|_A_SUBDIR, &ft)) #else if (_dos_findfirst(path2, _A_NORMAL, &ft)) #endif desttype=1; else if (!(ft.attrib&_A_SUBDIR)) desttype=1; if ((desttype==1)&&(srctype==2)) return 0; dmGetPath(path2, (m.fileref==0xFFFC)?dmGetParent(m.dirref):m.dirref); strcat(path2, name); if ((desttype==0)&&(srctype!=1)) return movefile(path, path2); if ((desttype==1)&&(srctype==0)) return movetoarc(path, path2); if ((desttype==0)&&(srctype==1)) return movefromarc(path, path2); if ((desttype==1)&&(srctype==1)) return movecrossarc(path, path2); return 0; } #endif static unsigned char fsQueryKill(modlistentry &m) { displaystr(1, 0, 0xF0, "are you sure you want to delete this file?", 80); while (!ekbhit()); if (toupper(egetch()&0xFF)!='Y') return 0; char path[_MAX_PATH]; char name[_MAX_NAME]; fsConv12FileName(name, m.name); dmGetPath(path, m.dirref); if ((m.fileref!=0xFFFC)&&isarchivepath(path)) { char ext[_MAX_EXT]; path[strlen(path)-1]=0; _splitpath(path, 0, 0, 0, ext); adbregstruct *packers; for (packers=adbPackers; packers; packers=packers->next) if (!strcmp(ext, packers->ext)) { conRestore(); packers->Call(adbCallDelete, path, name, ""); conSave(); plSetTextMode(fsScrType); } return 1; } else { if (m.fileref!=0xFFFC) strcat(path, name); else path[strlen(path)-1]=0; unlink(path); return 1; } /* remove from lists... */ } signed char fsFileSelect() { plSetTextMode(fsScrType); isnextplay=0; short win=0; quickfindpos=0; long i; char curscanned=0; modlistentry m; while (1) { dirwinheight=plScrHeight-4; if (fsEditWin||editmode) dirwinheight-=(plScrWidth==132)?5:6; if (!playlist.num) win=0; if (playlist.pos>=playlist.num) playlist.pos=playlist.num-1; if (playlist.pos<0) playlist.pos=0; if (viewlist.pos>=viewlist.num) viewlist.pos=viewlist.num-1; if (viewlist.pos<0) viewlist.pos=0; short firstv=viewlist.pos-dirwinheight/2; if ((firstv+dirwinheight)>viewlist.num) firstv=viewlist.num-dirwinheight; if (firstv<0) firstv=0; short firstp=playlist.pos-dirwinheight/2; if ((firstp+dirwinheight)>playlist.num) firstp=playlist.num-dirwinheight; if (firstp<0) firstp=0; if (!win) viewlist.getcur(m); else playlist.getcur(m); fsShowDir(firstv, win?-1:viewlist.pos, firstp, win?playlist.pos:-1, editmode?editpos:-1, m); if (!ekbhit()&&fsScanNames) { if (curscanned||(m.fileref>=0xFFFC)||mdbInfoRead(m.fileref)) { while (scanpos32)&&(c<=255)&&(c!=0x7f)||(c==8)) { if (c==8) { if (quickfindpos) quickfindpos--; if ((quickfindpos==8)&&(quickfind[8]=='.')) while (quickfindpos&&(quickfind[quickfindpos-1]==' ')) quickfindpos--; } else if (quickfindpos<12) if ((c=='.')&&(quickfindpos&&(*quickfind!='.'))) { while (quickfindpos<9) quickfind[quickfindpos++]=' '; quickfind[8]='.'; } else if (quickfindpos!=8) quickfind[quickfindpos++]=toupper(c); memcpy(quickfind+quickfindpos, " . "+quickfindpos, 12-quickfindpos); if (!quickfindpos) continue; if (!win) viewlist.pos=viewlist.fuzzyfind(quickfind); else playlist.pos=playlist.fuzzyfind(quickfind); continue; } quickfindpos=0; modlist &curlist=(win?playlist:viewlist); curlist.getcur(m); switch (c) { case 27: return 0; case 0x7f: /*c-bs*/ case 0x1f00: /* alt-s */ scanpos=0xFFFFFFFF; break; case 9: win=!win; break; case 0xF00: case 0x1200: editmode=!editmode; break; case 0x1700: case 0xa500: fsInfoMode=(fsInfoMode+1)&3; break; case 0x2E00: fsSetup(); plSetTextMode(fsScrType); break; case 0x3b00: if (!fsHelp2()) return -1; plSetTextMode(fsScrType); break; case 0x2C00: fsScrType=(fsScrType==0)?7:0; plSetTextMode(fsScrType); break; case 10: if (!fsEditViewPath()) return -1; break; case 13: if (editmode) if (m.fileref<0xFFFC) { if (!fsEditFileInfo(m.fileref)) return -1; break; } if (win) { nextplay=m; isnextplay=1; return 1; } else { if (m.fileref<0xFFFC) { nextplay=m; isnextplay=1; return 1; } else { unsigned short parentdir=0xFFFF; if (!memcmp(m.name, "..", 2)) parentdir=dmGetCurDir(); if (dmChangeDir(m.dirref)==0xFFFF) return -1; if (!fsScanDir(0)) return -1; if (parentdir!=0xFFFF) { for (i=viewlist.num-1; i>=0; i--) { viewlist.get(&m, i, 1); if ((m.fileref<0xFFFC)||(m.dirref!=parentdir)) continue; if (memcmp(m.name, "..", 2)&&(m.name[1]!=':')) { viewlist.pos=i; break; } } } } } break; case 0x4800: /* up */ if (editmode) if (plScrWidth==132) editpos="\x00\x01\x02\x03\x00\x01\x04\x05"[editpos]; else editpos="\x00\x01\x06\x06\x00\x04\x00\x05"[editpos]; else curlist.pos--; break; case 0x5000: /* down */ if (editmode) if (plScrWidth==132) editpos="\x04\x05\x05\x05\x06\x07\x06\x07"[editpos]; else editpos="\x04\x06\x07\x07\x05\x07\x03\x07"[editpos]; else curlist.pos++; break; case 0x4900: /* pgup */ curlist.pos-=editmode?1:dirwinheight; break; case 0x5100: /* pgdn */ curlist.pos+=editmode?1:dirwinheight; break; case 0x4700: /* home */ if (editmode) break; curlist.pos=0; break; case 0x4F00: /* end */ if (editmode) break; curlist.pos=curlist.num-1; break; case 0x4D00: /* right */ if (editmode) { if (plScrWidth==132) editpos="\x01\x02\x03\x03\x05\x05\x07\x07"[editpos]; else editpos="\x01\x01\x02\x02\x06\x03\x06\x07"[editpos]; } case 0x5200: /* add */ if (editmode) break; if (win) { if (!playlist.append(m)) return -1; /* playlist.pos=playlist.num-1; */ } else { if (m.fileref==0xFFFC) { if (!fsReadDir(playlist, m.dirref, curmask, 0)) return -1; } else if (m.fileref<0xFFFC) if (!playlist.append(m)) return -1; } break; case 0x4B00: /* left */ if (editmode) { if (plScrWidth==132) editpos="\x00\x00\x01\x02\x04\x04\x06\x06"[editpos]; else editpos="\x00\x00\x03\x05\x04\x05\x04\x07"[editpos]; } case 0x5300: /* del */ if (editmode) break; if (win) playlist.remove(playlist.pos, 1); else { long f; if (m.fileref<0xFFFC) { f=playlist.find(m); if (f!=-1) playlist.remove(f, 1); } else if (m.fileref==0xFFFC) { modlist tl; if (!fsReadDir(tl, m.dirref, curmask, 0)) return -1; for (i=0; i=playlist.num) break; playlist.remove(playlist.pos, 1); playlist.insert(playlist.pos+1, &m, 1); playlist.pos++; break; case 0x8400: /* ctrl-pgup */ if (editmode||!win) break; i=(playlist.pos>dirwinheight)?dirwinheight:playlist.pos; playlist.remove(playlist.pos, 1); playlist.insert(playlist.pos-i, &m, 1); playlist.pos-=i+1; break; case 0x7600: /* ctrl-pgdown */ if (editmode||!win) break; i=((playlist.num-1-playlist.pos)>dirwinheight)?dirwinheight:(playlist.num-1-playlist.pos); playlist.remove(playlist.pos, 1); playlist.insert(playlist.pos+i, &m, 1); playlist.pos+=i; break; case 0x7700: /* ctrl-home */ if (editmode||!win) break; playlist.remove(playlist.pos, 1); playlist.insert(0, &m, 1); playlist.pos=0; break; case 0x7500: /* ctrl-end */ if (editmode||!win) break; playlist.remove(playlist.pos, 1); playlist.insert(playlist.num, &m, 1); playlist.pos=playlist.num-1; break; } } /*return 0; the above while loop doesn't go to this point */ } /* use the god damn playlist instead char fsAddFiles(const char *p) { while (*p) { while (isspace(*p)) p++; int i; char path[_MAX_PATH]; for (i=0; (i<(_MAX_PATH-1))&&!isspace(*p)&&*p; i++) path[i]=*p++; path[i]=0; if ((*path=='-')||(*path=='/')||!*path) continue; if (*path=='@') { unsigned short olddir=dmGetCurDir(); char nam[_MAX_FNAME]; char ext[_MAX_EXT]; char dir[_MAX_DIR]; char drv[_MAX_DRIVE]; _splitpath(path+1, drv, dir, nam, ext); _makepath(path, drv, dir, 0, 0); unsigned short dref=dmGetPathReference(path); if (dref==0xFFFF) return 0; dmGetPath(path, dref); dmChangeDir(dref); if (!*ext) strcpy(ext, ".M3U"); _makepath(path+strlen(path), 0, 0, nam, ext); sbinfile lf; if (!lf.open(path, sbinfile::openro)) { int len=lf.length(); char *fbuf=new char [len+1]; if (!fbuf) return 0; lf.read(fbuf, len); fbuf[len]=0; lf.close(); len=fsAddFiles(fbuf); if (!len) return 0; delete fbuf; } dmChangeDir(olddir); } else { char path2[_MAX_PATH]; unsigned short dref; char nmask[12]; if (!fsExpandPath(path2, nmask, (*path=='@')?(path+1):path)) return 0; dref=dmGetPathReference(path2); if (dref==0xFFFF) return 0; if (!fsReadDir(playlist, dref, nmask, (fsScanArcs?RD_ARCSCAN:0))) return 0; } } return 1; } */ #endif struct mdbreaddirregstruct fsReadDirReg = {stdReadDir MDBREADDIRREGSTRUCT_TAIL}; struct mdbreaddirregstruct dosReadDirReg = {dosReadDir MDBREADDIRREGSTRUCT_TAIL}; void fsConvFileName12(char *c, const char *f, const char *e) /* f=up to 8 chars, might end premature with a null * e=up to 4 chars, starting with a ., migh premature with a null * char c[12], will not be null terminated premature, but not after the 12, and no \0 exists then * f="hei" e=".gz" -> {HEI .GZ\0} * f="hello" e=".txt" -> {HELLO .TXT} */ { int i; for (i=0; i<8; i++) *c++=*f?*f++:' '; for (i=0; i<4; i++) *c++=*e?*e++:' '; for (i=0; i<12; i++) c[i-12]=toupper(c[i-12]); } void convfilename12wc(char *c, const char *f, const char *e) /* same as above, but * is expanded to ? * f="hei" e=".*" -> {HEI .???} * f="*" e=".*" -> {????????.???} */ { int i; for (i=0; i<8; i++) *c++=(*f=='*')?'?':*f?*f++:' '; for (i=0; i<4; i++) *c++=(*e=='*')?'?':*e?*e++:' '; for (i=0; i<12; i++) c[i-12]=toupper(c[i-12]); } /* broken due to the fact that we allow space void fsConv12FileName(char *f, const char *c) { int i; for (i=0; i<8; i++) if (c[i]==' ') break; else *f++=c[i]; for (i=8; i<12; i++) if (c[i]==' ') break; else *f++=c[i]; *f=0; } */ /* broken due to the fact that we allow space, question-mask etc static void conv12filenamewc(char *f, const char *c) { char *f0=f; short i; for (i=0; i<8; i++) if (c[i]==' ') break; else *f++=c[i]; if (i==8) { for (i=7; i>=0; i--) if (c[i]!='?') break; if (++i<7) { f-=8-i; *f++='*'; } } for (i=8; i<12; i++) if (c[i]==' ') break; else *f++=c[i]; if (i==12) { for (i=11; i>=9; i--) if (c[i]!='?') break; if (++i<10) { f-=12-i; *f++='*'; } } *f=0; }*/ int fsMatchFileName12(const char *a, const char *b) { int i; for (i=0; i<12; i++, a++, b++) if ((i!=8)&&(*b!='?')&&(*a!=*b)) break; return i==12; } static struct interfacestruct *plInterfaces = 0; void plRegisterInterface(struct interfacestruct *interface) { interface->next = plInterfaces; plInterfaces = interface; } void plUnregisterInterface(struct interfacestruct *interface) { struct interfacestruct *curr = plInterfaces; if (curr == interface) { plInterfaces = interface->next; return; } while (curr) { if (curr->next == interface) { curr->next = curr->next->next; return; } curr = curr->next; } fprintf(stderr, __FILE__ ": Failed to unregister interface %s\n", interface->name); } struct interfacestruct *plFindInterface(const char *name) { struct interfacestruct *curr = plInterfaces; while (curr) { if (!strcmp(curr->name, name)) return curr; curr = curr->next; } fprintf(stderr, __FILE__ ": Unable to find interface: %s\n", name); return NULL; } void plRegisterPreprocess(struct preprocregstruct *r) { r->next=plPreprocess; plPreprocess=r; } void plUnregisterPreprocess(struct preprocregstruct *r) { struct preprocregstruct *curr = plPreprocess; if (curr == r) { plPreprocess = r->next; return; } while (curr) { if (curr->next == r) { curr->next = curr->next->next; return; } curr = curr->next; } fprintf(stderr, __FILE__ ": Failed to unregister a preprocregstruct %p\n", r); } ocp-0.1.21/filesel/fsptype.c0000644000175000001440000000635711655541726014721 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Fileselector file type detection routines (covers play lists and internal * cache files) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -kb980717 Tammo Hinrichs * -first release */ #include "config.h" #include #include #include #include "types.h" #include "dirdb.h" #include "mdb.h" static int fsReadMemInfo(struct moduleinfostruct *m, const char *buf, size_t len) { /* check for PLS play list */ char *b=(char *)buf; unsigned int pos=10; int num=0; if (!memcmp(buf,"[playlist]", 10)) { while (pos18 && !memcmp(b+pos,"NumberOfEntries=",16)) { pos+=16; num=strtol(b+pos,0,10); pos=len; } } } if (num) { sprintf(m->modname, "PLS style playlist (%d entries)", num); m->modtype=mtPLS; m->flags1|=MDB_PLAYLIST; return 1; } else { strcpy(m->modname,"PLS style playlist ?"); m->modtype=mtPLS; m->flags1|=MDB_PLAYLIST; return 1; } } /* check for M3U-style play list */ if (!memcmp(buf,"#EXTM3U", 7)) { strcpy(m->modname,"M3U playlist"); m->modtype=mtM3U; m->flags1|=MDB_PLAYLIST; return 1; } if (!strncasecmp(m->name+8, ".M3U", 4)) { strcpy(m->modname, "Non-standard M3U playlist"); m->modtype=mtM3U; m->flags1|=MDB_PLAYLIST; return 1; } if (!strncasecmp(m->name+8, ".PLS", 4)) { strcpy(m->modname, "Non-standard PLS playlist"); m->modtype=mtPLS; m->flags1|=MDB_PLAYLIST; return 1; } if (!memcmp(buf, "CPArchiveCache\x1B\x00", 16)) strcpy(m->modname,"openCP archive data base (old)"); if (!memcmp(buf, "CPArchiveCache\x1B\x01", 16)) strcpy(m->modname,"openCP archive data base"); if (!memcmp(buf, "Cubic Player Module Information Data Base\x1B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 60)) strcpy(m->modname,"openCP module info data base"); if (!memcmp(buf, dirdbsigv1, sizeof(dirdbsigv1))) strcpy(m->modname,"openCP dirdb/medialib: db v1"); if (!memcmp(buf, dirdbsigv2, sizeof(dirdbsigv2))) strcpy(m->modname,"openCP dirdb/medialib: db v2"); if (!memcmp(buf, "MDZTagList\x1A\x00", 12)) strcpy(m->modname,"openCP MDZ file cache"); return 0; } static int fsReadInfo(struct moduleinfostruct *m, FILE *fp, const char *buf, size_t len) { return 0; } struct mdbreadinforegstruct fsReadInfoReg = {fsReadMemInfo, fsReadInfo, 0 MDBREADINFOREGSTRUCT_TAIL}; ocp-0.1.21/filesel/cphlpfs.c0000644000175000001440000000403011655541726014650 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * CP hypertext help viewer (Fileselector wrapper) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -fg980924 Fabian Giesen * -first release */ #include "config.h" #include "types.h" #include "stuff/poutput.h" #include "help/cphelper.h" #include "stuff/framelock.h" #include "cphlpfs.h" #include int fsmode; /* ripped from fileselector */ /* the wrapper */ static int plHelpKey(unsigned short key) { switch(key) { case 'h': case 'H': case '?': case '!': case KEY_F(1): case KEY_ESC: fsmode=0; break; default: return brHelpKey(key); } return 1; } unsigned char fsHelp2(void) { unsigned short sbuf[CONSOLE_MAX_X]; helppage *cont; plSetTextMode(0); fillstr(sbuf, 0, 0x30, 0, CONSOLE_MAX_X); writestring(sbuf, 2, 0x30, "opencp help", 11); writestring(sbuf, plScrWidth-29, 0x30, "(c) 1994-2011 Stian Skjelstad", 27); displaystrattr(0, 0, sbuf, plScrWidth); cont=brDecodeRef("Contents"); if (!cont) displaystr(1, 0, 0x04, "shit!", 5); brSetPage(cont); brSetWinStart(2); brSetWinHeight(plScrHeight-2); fsmode=1; while (fsmode) { unsigned short key; brDisplayHelp(); while (!ekbhit()) framelock(); key=egetch(); plHelpKey(key); framelock(); }; return 1; } ocp-0.1.21/filesel/gendir.c0000644000175000001440000001543511655541726014474 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Parsing a directory, and a patch.. aka /root/Desktop + ../.xmms => /root/.xmms * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss051231 Stian Skjelstad * -first release */ #include "config.h" #include "gendir.h" #include "types.h" #include #include #include static void trim_off_leading_slashes(char *src) { char *trim; while (1) { if (strlen(src)) { trim=src+strlen(src)-1; if (*trim=='/') *trim=0; else break; } else { strcpy(src, "/"); break; } } } static void trim_off_a_directory(char *src) { char *last_slash=src, *next; while ((next=strchr(last_slash+1, '/'))) { if (!next[1]) /* but we accept the string to end with a / */ break; last_slash=next; } if (last_slash!=src) *last_slash=0; else src[1]=0; /* let the / be alone */ } void gendir(const char *orgdir, const char *fixdir, char *_retval) { char fixdir_clone[PATH_MAX+1]; char *next_token; char retval[PATH_MAX+1]; if (strlen(orgdir)>(PATH_MAX)) { fprintf(stderr, "gendir.c: strlen(orgdir)>PATH_MAX\n"); exit(1); /*strcpy(_retval, "/"); return;*/ } if (strlen(fixdir)>(PATH_MAX)) { fprintf(stderr, "gendir.c: strlen(fixdir)>PATH_MAX\n"); exit(1); /*strcpy(_retval, "/"); return;*/ } /* we are safe.. buffers should never overflow now! */ strcpy(retval, orgdir); strcpy(fixdir_clone, fixdir); trim_off_leading_slashes(retval); trim_off_leading_slashes(fixdir_clone); next_token=fixdir_clone; while (*fixdir_clone) { if ((*fixdir_clone=='/')) { strcpy(retval, "/"); memmove(fixdir_clone, fixdir_clone+1, strlen(fixdir_clone)/*+0*/); continue; } if ((next_token=strchr(fixdir_clone+1, '/'))) { *next_token=0; next_token++; } else { next_token=fixdir_clone+strlen(fixdir_clone); } if (!strcmp(fixdir_clone, ".")) { /* Do nothing */ } else if (!strcmp(fixdir_clone, "..")) { /* Bump up a level if possible */ trim_off_a_directory(retval); } else { /* append the shit.. prepend it with a / if needed */ if (retval[1]) { if (strlen(retval)<=(PATH_MAX)) strcat(retval, "/"); } if ((strlen(retval)+strlen(fixdir_clone))<=PATH_MAX) strcat(retval, fixdir_clone); } memmove(fixdir_clone, next_token, strlen(next_token)+1); } trim_off_leading_slashes(retval); strcpy(_retval, retval); return; } void genreldir(const char *orgdir, const char *fixdir, char *targetdir) { char orgdirclone[PATH_MAX+1]; char fixdirclone[PATH_MAX+1]; char *nextorgdir, *curorgdir; char *nextfixdir, *curfixdir; int firsttoken=1; if ((orgdir[0]!='/')||(fixdir[0]!='/')) { strcpy(targetdir, fixdir); return; } targetdir[0]=0; strcpy(orgdirclone, orgdir); strcpy(fixdirclone, fixdir); nextorgdir=orgdirclone+1; nextfixdir=fixdirclone+1; while (1) { curorgdir=nextorgdir; curfixdir=nextfixdir; if (curorgdir) if (!*curorgdir) curorgdir=NULL; if (curfixdir) if (!*curfixdir) curfixdir=NULL; if (!curorgdir) /* we append after old, no back-patch */ { if (curfixdir) { strcpy(targetdir, curfixdir); return; } strcpy(targetdir, "."); trim_off_leading_slashes(targetdir); return; } if (!curfixdir) /* we back-patch all tokens after here */ { while (curorgdir) { if (*targetdir) if (strlen(targetdir) int main(int argc, char *argv[]) { char temp[PATH_MAX+1]; gendir("/", "/", temp); printf("/ / -> %s\n", temp); gendir("/home/stian", "/", temp); printf("/home/stian / -> %s\n", temp); gendir("/home/stian", "../", temp); printf("/home/stian/ ../ -> %s\n", temp); gendir("/home/stian", "../.", temp); printf("/home/stian/ ../. -> %s\n", temp); gendir("/home/stian", "./", temp); printf("/home/stian/ ./ -> %s\n", temp); gendir("/home/stian", "..//", temp); printf("/home/stian/ ..// -> %s\n", temp); gendir("/home/stian", "../../tmp/test/./", temp); printf("/home/stian/ ../../tmp/test/./ -> %s\n", temp); printf("\n"); genreldir("/home/stian", "/home/stian/disk/load.mp3", temp); printf("/home/stian /home/stian/disk/load.mp3 -> %s\n", temp); genreldir("/home/stian/", "/home/stian/disk/load.mp3", temp); printf("/home/stian/ /home/stian/disk/load.mp3 -> %s\n", temp); genreldir("/home/stian", "/home/stian/disk/load.mp3/", temp); printf("/home/stian /home/stian/disk/load.mp3/ -> %s\n", temp); genreldir("/home/stian/", "/home/stian/disk/load.mp3/", temp); printf("/home/stian/ /home/stian/disk/load.mp3/ -> %s\n", temp); genreldir("/home/stian", "/home/alfa/disk99/song.s3m", temp); printf("/home/stian /home/alfa/disk99/song.s3m -> %s\n", temp); genreldir("/home/stian", "/root/diska/test.ogg", temp); printf("/home/stian /root/diska/test.ogg -> %s\n", temp); return 0; }*/ ocp-0.1.21/filesel/modlist.h0000644000175000001440000000444411655541726014702 0ustar stianusers#ifndef _DIRLIST_H #define _DIRLIST_H #include "config.h" #if 0 #include #include #endif #include /* size_t */ struct dmDrive; struct modlistentry { char shortname[12]; /* the name that we present in the filelists.. 8:3 format looks so nice... yuck... but i works*/ const struct dmDrive *drive; // char fullname[PATH_MAX+1]; /* the very full path to this object */ uint32_t dirdbfullpath; /* full path */ char name[NAME_MAX+1]; /* the very lonely filename */ #define MODLIST_FLAG_DIR 1 #define MODLIST_FLAG_ARC 2 /* mutual exlusive flags, but we still let them have bit values.. looks nice */ #define MODLIST_FLAG_FILE 4 #define MODLIST_FLAG_VIRTUAL 8 #define MODLIST_FLAG_DRV 16 int flags; uint32_t fileref; /* uint32_t dirref; */ uint32_t adb_ref; /* new, until dirref is re-created later perhaps */ int (*Read)(struct modlistentry *entry, char **mem, size_t *size); int (*ReadHeader)(struct modlistentry *entry, char *mem, size_t *size); /* size is prefilled with max data, and mem is preset*/ FILE *(*ReadHandle)(struct modlistentry *entry); }; struct modlist { struct modlistentry **files; struct modlistentry **realfiles; /* these are used by external */ unsigned int pos; /* position */ unsigned int max; /* current array size */ unsigned int num; /* entries used */ }; extern struct modlist *modlist_create(void); extern void modlist_free(struct modlist *modlist); extern void modlist_sort(struct modlist *modlist); extern void modlist_append(struct modlist *modlist, struct modlistentry *entry); extern void modlist_swap(struct modlist *modlist, unsigned int index1, unsigned int index2); extern void modlist_remove(struct modlist *modlist, unsigned int index, unsigned int count); extern void modlist_remove_all_by_path(struct modlist *modlist, uint32_t ref); extern int modlist_find(struct modlist *modlist, const uint32_t path); extern int modlist_fuzzyfind(struct modlist *modlist, const char *filename); extern struct modlistentry *modlist_get(const struct modlist *modlist, unsigned int index); extern struct modlistentry *modlist_getcur(const struct modlist *modlist); /* does not Ref() */ extern void modlist_append_modlist(struct modlist *target, struct modlist *source); extern void fs12name(char *dst13bytes, const char *source); #endif ocp-0.1.21/filesel/modlist.c0000644000175000001440000001634211655541726014675 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * the file-object code used by the File selector ][ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040613 Stian Skjelstad * -first release * -ss040831 Stian Skjelstad * -updated fs12name to not crash anymore * -removed modlist->pathtothis */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "dirdb.h" #include "modlist.h" #include "stuff/compat.h" void modlist_free(struct modlist *modlist) { unsigned int i; for (i=0;inum;i++) { dirdbUnref(modlist->files[i]->dirdbfullpath); free(modlist->files[i]); } if (modlist->max) free(modlist->files); free(modlist); } struct modlistentry *modlist_getcur(const struct modlist *modlist) /* does not Ref() */ { return modlist_get(modlist, modlist->pos); } struct modlistentry *modlist_get(const struct modlist *modlist, unsigned int index) /* does not Ref() */ { if (!(modlist->num)) return NULL; /* should never happen */ /* if (index<0) return modlist->files[0]; */ if (index>=modlist->num) return modlist->files[modlist->num-1]; return modlist->files[index]; } void modlist_append(struct modlist *modlist, struct modlistentry *entry) { if (!entry) return; if (!modlist->max) /* Keeps Electric Fence happy */ { modlist->max=50; modlist->files=malloc(modlist->max*sizeof(modlist->files[0])); } else if (modlist->num==modlist->max) { modlist->max+=50; modlist->files=realloc(modlist->files, modlist->max*sizeof(modlist->files[0])); } dirdbRef(entry->dirdbfullpath); modlist->files[modlist->num]=malloc(sizeof(struct modlistentry)); /* TODO... make a cache pool of these */ memcpy(modlist->files[modlist->num], entry, sizeof(struct modlistentry)); modlist->num++; } void modlist_remove_all_by_path(struct modlist *modlist, uint32_t ref) { unsigned int i; for (i=0;inum;) { if (modlist->files[i]->dirdbfullpath == ref) modlist_remove(modlist, i, 1); else i++; } } void modlist_remove(struct modlist *modlist, unsigned int index, unsigned int count) { unsigned int i; if (index>=modlist->num) return; if (index+count>modlist->num) count=modlist->num-index; for (i=index;i<(index+count);i++) { dirdbUnref(modlist->files[i]->dirdbfullpath); free(modlist->files[i]); } memmove(&modlist->files[index], &modlist->files[index+count], (modlist->num-index-count)*sizeof(modlist->files[0])); modlist->num-=count; if ((modlist->max-modlist->num>75)) { modlist->max-=50; modlist->files=realloc(modlist->files, modlist->max*sizeof(modlist->files[0])); } if (!modlist->num) modlist->pos = 0; else if (modlist->pos >= modlist->num) modlist->pos = modlist->num-1; } int modlist_find(struct modlist *modlist, const uint32_t path) { unsigned int retval; for (retval=0;retvalnum;retval++) if (path==modlist->files[retval]->dirdbfullpath) return retval; return -1; } void modlist_swap(struct modlist *modlist, unsigned int index1, unsigned int index2) { struct modlistentry *entry; if (index1>=modlist->num) return; if (index2>=modlist->num) return; entry = modlist->files[index1]; modlist->files[index1] = modlist->files[index2]; modlist->files[index2] = entry; } static const char *fuzzycmp12(const char *dst, const char *src) { char DST, SRC; int len=12; while ((*dst)&&len) { len--; DST=toupper(*dst); SRC=toupper(*src); if (DST==SRC) { dst++; src++; } else break; } return dst; } int modlist_fuzzyfind(struct modlist *modlist, const char *filename) { unsigned int retval=0; int hitscore=0; unsigned int i; unsigned int len=strlen(filename); if (!len) return 0; for (i=0;inum;i++) { const char *temp=modlist->files[i]->shortname; const char *diff=fuzzycmp12(temp, filename); int score=diff-temp; if ((unsigned)score==len) return i; else if (score>hitscore) { retval=i; hitscore=score; } } return retval; } static int mlecmp(const void *a, const void *b) { const struct modlistentry *e1=*(struct modlistentry **)a, *e2=*(struct modlistentry **)b; if ((e1->flags&(MODLIST_FLAG_DIR|MODLIST_FLAG_ARC|MODLIST_FLAG_FILE|MODLIST_FLAG_DRV))!=(e2->flags&(MODLIST_FLAG_DIR|MODLIST_FLAG_ARC|MODLIST_FLAG_FILE|MODLIST_FLAG_DRV))) { if ((e1->flags&(MODLIST_FLAG_DIR|MODLIST_FLAG_ARC|MODLIST_FLAG_FILE|MODLIST_FLAG_DRV))>(e2->flags&(MODLIST_FLAG_DIR|MODLIST_FLAG_ARC|MODLIST_FLAG_FILE|MODLIST_FLAG_DRV))) return 1; else return -1; } return memicmp(e1->shortname, e2->shortname, 12); return 0; } void modlist_sort(struct modlist *modlist) { qsort(modlist->files, modlist->num, sizeof(*modlist->files), mlecmp); } struct modlist *modlist_create(void) { /* TODO ARCS */ /* DIR *dir; */ struct modlist *retval=calloc(sizeof(struct modlist), 1); return retval; } void modlist_append_modlist(struct modlist *target, struct modlist *source) { unsigned int i; for (i=0;inum;i++) modlist_append(target, modlist_get(source, i)); } void fs12name(char *shortname, const char *source) { char temppath[NAME_MAX+1]; char *lastdot; int length=strlen(source); strcpy(temppath, source); /* if (length) if (temppath[length-1]=='/') { temppath[length-1]=0; length--; }*/ #if 0 if (entry->flags&MODLIST_FLAG_FILE) /* this makes life more easy */ { #endif if (length>=8) if (!strcasecmp(temppath+length-8, ".tar.bz2")) { strcpy(temppath+length-8, ".tbz"); length-=4; /* entry->flags=MODLIST_FLAG_ARC; */ } if (length>=7) if (!strcasecmp(temppath+length-7, ".tar.gz")) { strcpy(temppath+length-7, ".tgz"); length-=3; /* entry->flags=MODLIST_FLAG_ARC; */ } if (length>=6) if (!strcasecmp(temppath+length-6, ".tar.Z")) { strcpy(temppath+length-6, ".tgz"); length-=2; /* entry->flags=MODLIST_FLAG_ARC; */ } #if 0 } #endif if ((lastdot=rindex(temppath+1, '.'))) /* we allow files to start with . */ { int delta=lastdot-temppath; if (strlen(lastdot)>4) lastdot[4]=0; if ((delta)<=8) { strncpy(shortname, temppath, delta); strncpy(shortname+delta, " ", 8-delta); } else strncpy(shortname, temppath, 8); strncpy(shortname+8, lastdot, 4); if ((length=strlen(lastdot))<4) strncpy(shortname+8+length, " ", 4-length); } else { strncpy(shortname, temppath, 12); if ((length=strlen(temppath))<12) strncpy(shortname+length, " ", 12-length); } } ocp-0.1.21/filesel/dirdb.c0000644000175000001440000004233711655541726014311 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * database for storing a tree of filenames * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include #include #include #include #include #include #include #include "types.h" #include "dirdb.h" #include "boot/psetting.h" struct dirdbEntry { uint32_t parent; uint32_t mdbref; uint32_t adbref; char *name; /* we pollute malloc a lot with this */ int refcount; uint32_t newadbref; uint32_t newmdbref; /* used during scan to find new nodes */ }; static uint32_t tagparentnode = DIRDB_NOPARENT; struct __attribute__((packed)) dirdbheader { char sig[60]; uint32_t entries; }; const char dirdbsigv1[60] = "Cubic Player Directory Data Base\x1B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const char dirdbsigv2[60] = "Cubic Player Directory Data Base\x1B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"; static struct dirdbEntry *dirdbData=0; static uint32_t dirdbNum=0; static int dirdbDirty=0; #ifdef DIRDB_DEBUG static void dumpdb_parent(uint32_t parent, int ident) { uint32_t i; for (i=0;iPATH_MAX) { fprintf(stderr, "dirdb: CPDIRDB.DAT path is too long\n"); return 1; } strcpy(path, cfConfigDir); strcat(path, "CPDIRDB.DAT"); if ((f=open(path, O_RDONLY))<0) { perror("open(cfConfigDir/CPDIRDB.DAT)"); return 1; } fprintf(stderr, "Loading %s .. ", path); if (read(f, &header, sizeof(header))!=sizeof(header)) { fprintf(stderr, "No header\n"); close(f); return 1; } if (memcmp(header.sig, dirdbsigv1, 60)) { if (memcmp(header.sig, dirdbsigv2, 60)) { fprintf(stderr, "Invalid header\n"); close(f); return 1; } else version = 2; } else version = 1; dirdbNum=uint32_little(header.entries); if (!dirdbNum) goto endoffile; dirdbData = calloc (dirdbNum, sizeof(struct dirdbEntry)); if (!dirdbData) { dirdbNum=0; goto outofmemory; } for (i=0; i=dirdbNum) { fprintf(stderr, "Invalid parent in a node .."); dirdbData[i].parent=0; } else dirdbData[dirdbData[i].parent].refcount++; } } fprintf(stderr, "Done\n"); return 1; endoffile: fprintf(stderr, "EOF\n"); close(f); retval=1; goto unload; outofmemory: fprintf(stderr, "out of memory\n"); close(f); retval=0; unload: for (i=0; iNAME_MAX) { fprintf(stderr, "dirdbFindAndRef: name too long\n"); return DIRDB_NOPARENT; } if ((parent!=DIRDB_NOPARENT)&&(parent>=dirdbNum)) { fprintf(stderr, "dirdbFindAndRef: invalid parent\n"); return DIRDB_NOPARENT; } for (i=0;i=dirdbNum) { fprintf(stderr, "dirdbFindAndRef: invalid node\n"); return; } /*fprintf(stderr, "+++ %s (%d p=%d)\n", dirdbData[node].name, node, dirdbData[node].parent);*/ dirdbData[node].refcount++; } uint32_t dirdbResolvePathWithBaseAndRef(uint32_t base, const char *name /* PATH_MAX + 1 */) { char segment[PATH_MAX+1]; const char *next; char *split; uint32_t retval=base, newretval; #ifdef DIRDB_DEBUG fprintf(stderr, "dirdbResolvePathWithBaseAndRef(0x%08x, \"%s\")\n", base, name); #endif if (strlen(name)>PATH_MAX) { fprintf(stderr, "dirdbResolvPathWithBase: name too long\n"); return DIRDB_NOPARENT; } next=name; if (retval!=DIRDB_NOPARENT) dirdbRef(retval); while (next) { if (*next=='/') next++; if ((split=strchr(next, '/'))) { strncpy(segment, next, split-next); segment[split-next]=0; next=split+1; if (!next) next=0; } else { strcpy(segment, next); next=0; } if (!strlen(segment)) continue; newretval=dirdbFindAndRef(retval, segment); dirdbUnref(retval); retval=newretval; } #ifdef DIRDB_DEBUG dumpdirdb(); #endif return retval; } extern uint32_t dirdbResolvePathAndRef(const char *name /*PATH_MAX + 1 */) { char segment[PATH_MAX+1]; const char *next; char *split; uint32_t retval=DIRDB_NOPARENT, newretval; #ifdef DIRDB_DEBUG fprintf(stderr, "dirdbResolvePathAndRef(\"%s\")\n", name); #endif if (strlen(name)>PATH_MAX) { fprintf(stderr, "dirdbResolvPathWithBase: name too long\n"); return DIRDB_NOPARENT; } next=name; while (next) { if (*next=='/') next++; if ((split=strchr(next, '/'))) { strncpy(segment, next, split-next); segment[split-next]=0; next=split+1; if (!next) next=0; } else { strcpy(segment, next); next=0; } if (!strlen(segment)) continue; newretval=dirdbFindAndRef(retval, segment); if (retval!=DIRDB_NOPARENT) dirdbUnref(retval); retval=newretval; } #ifdef DIRDB_DEBUG dumpdirdb(); #endif return retval; } void dirdbUnref(uint32_t node) { uint32_t parent; #ifdef DIRDB_DEBUG fprintf(stderr, "dirdbUnref(0x%08x)\n", node); #endif if (node>=dirdbNum) { err: fprintf(stderr, "dirdbUnref: invalid node\n"); abort(); return; } if (!dirdbData[node].refcount) goto err; /* fprintf(stderr, "--- %s (%d p=%d)\n", dirdbData[node].name, node, dirdbData[node].parent);*/ dirdbData[node].refcount--; if (dirdbData[node].refcount) return; /* fprintf(stderr, "DELETE\n");*/ dirdbDirty=1; parent = dirdbData[node].parent; dirdbData[node].parent=0; free(dirdbData[node].name); dirdbData[node].name=0; dirdbData[node].mdbref=DIRDB_NO_MDBREF; /* this should not be needed */ dirdbData[node].newmdbref=DIRDB_NO_MDBREF; /* this should not be needed */ dirdbData[node].adbref=DIRDB_NO_ADBREF; /* this should not be needed */ dirdbData[node].newadbref=DIRDB_NO_ADBREF; /* this should not be needed */ #ifdef DIRDB_DEBUG dumpdirdb(); #endif if (parent!=DIRDB_NOPARENT) dirdbUnref(parent); } void dirdbGetname(uint32_t node, char *name /*NAME_MAX+1*/) { name[0]=0; if (node>=dirdbNum) { fprintf(stderr, "dirdbGetname: invalid node #1\n"); return; } if (!dirdbData[node].name) { fprintf(stderr, "dirdbGetname: invalid node #2\n"); return; } strcpy(name, dirdbData[node].name); } static void dirdbGetFullnameR(uint32_t node, char *name, unsigned int *left, int nobase) { if (dirdbData[node].parent!=DIRDB_NOPARENT) { dirdbGetFullnameR(dirdbData[node].parent, name, left, nobase); if (!*left) goto errorout; strcat(name, "/"); (*left)--; } else if (nobase) return; if ((*left)<=strlen(dirdbData[node].name)) goto errorout; strcat(name, dirdbData[node].name); (*left)-=strlen(dirdbData[node].name); return; errorout: fprintf(stderr, "dirdbGetFullname: string grows to long\n"); return; } void dirdbGetFullName(uint32_t node, char *name /* PATH_MAX+1, ends not with a / */, int flags) { unsigned int i = PATH_MAX; *name=0; if (node>=dirdbNum) { fprintf(stderr, "dirdbGetFullname: invalid node\n"); return; } dirdbGetFullnameR(node, name, &i, flags&DIRDB_FULLNAME_NOBASE); if (flags&DIRDB_FULLNAME_ENDSLASH) if (strlen(name)+1PATH_MAX) { fprintf(stderr, "dirdb: CPDIRDB.DAT path is too long\n"); return; } strcpy(path, cfConfigDir); strcat(path, "CPDIRDB.DAT"); if ((f=open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE))<0) { perror("open(cfConfigDir/CPDIRDB.DAT)"); return; } max=0; for (i=0;i=dirdbNum) return DIRDB_NOPARENT; if ((retval=dirdbData[node].parent)!=DIRDB_NOPARENT) dirdbData[dirdbData[node].parent].refcount++; return retval; } #if 0 void dirdbMakeMdbRef(uint32_t node, uint32_t mdbref) { #ifdef DIRDB_DEBUG fprintf(stderr, "dirdbMakeMdbRef(node 0x%08x, mdbref 0x%08x)\n", node, mdbref); #endif if (node>=dirdbNum) { fprintf(stderr, "dirdbMakeMdbRef: invalid node\n"); return; } if (mdbref==DIRDB_NO_MDBREF) { if (dirdbData[node].mdbref!=DIRDB_NO_MDBREF) { dirdbData[node].mdbref=DIRDB_NO_MDBREF; dirdbDirty=1; dirdbUnref(node); } } else { int doref = (dirdbData[node].mdbref==DIRDB_NO_MDBREF); dirdbData[node].mdbref=mdbref; dirdbDirty=1; if (doref) dirdbRef(node); } #ifdef DIRDB_DEBUG dumpdirdb(); #endif } #endif void dirdbTagSetParent(uint32_t node) { uint32_t i; if (tagparentnode!=DIRDB_NOPARENT) { fprintf(stderr, "dirdbTagSetParent: warning, a node was already set as parent\n"); dirdbUnref(tagparentnode); tagparentnode=DIRDB_NOPARENT; } for (i=0;i=dirdbNum) { fprintf(stderr, "dirdbTagSetParent: invalid node\n"); return; } tagparentnode = node; dirdbRef(node); } void dirdbMakeMdbAdbRef(uint32_t node, uint32_t mdbref, uint32_t adbref) { if (node>=dirdbNum) { fprintf(stderr, "dirdbMakeMdbRef: invalid node\n"); return; } /* the madness below is in order to keep track of references the correct way */ if (mdbref==DIRDB_NO_MDBREF) { if (dirdbData[node].newmdbref!=DIRDB_NO_MDBREF) { dirdbData[node].newmdbref=DIRDB_NO_MDBREF; dirdbUnref(node); } /* else, no change */ } else { if (dirdbData[node].mdbref==DIRDB_NO_MDBREF) { dirdbData[node].newmdbref=mdbref; dirdbRef(node); } else { /*dirdbUnref(node);*/ dirdbData[node].newmdbref=mdbref; /*dirdbRef(node); overkill to unref and re-ref just for the name's sake*/ } } dirdbData[node].newadbref = adbref; } void dirdbTagCancel(void) { uint32_t i; for (i=0;i * * CP hypertext help viewer fileselector wrapper * * revision history: (please note changes here) * -fg980924 Fabian Giesen * -first version (mainly for wrappers) */ #ifndef _cphlpfs_h #define _cphlpfs_h extern unsigned char fsHelp2(void); #endif ocp-0.1.21/filesel/pfspls.c0000644000175000001440000000702411655541726014526 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * *.PLS file-reader/parser * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss051231 Stian Skjelstad * -first release */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "dirdb.h" #include "gendir.h" #include "mdb.h" #include "modlist.h" #include "playlist.h" #include "pfilesel.h" #include "stuff/compat.h" static int plsReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { char *s1, *s2; #if 0 char *s3; #endif char newpath[PATH_MAX+1]; char *readbuffer; char *buftail; int buftail_n; int fd; struct stat st; #ifndef FNM_CASEFOLD char *mask_upper; char *iterate; #endif if (drive!=dmFILE) /* we, only support file:// transport for now... TODO */ return 1; dirdbGetFullName(path, newpath, DIRDB_FULLNAME_NOBASE); /* no file: */ /* Does the file end in .PLS ? */ s1=newpath+strlen(newpath)-4; if (s1(1024*1024)) { fprintf(stderr, "[PLS] File too big\n"); close(fd); return 1; } readbuffer=malloc(st.st_size); if (read(fd, readbuffer, st.st_size)!=st.st_size) { close(fd); return 1; } close(fd); buftail=readbuffer; buftail_n=st.st_size; #ifndef FNM_CASEFOLD if ((mask_upper = strdup(mask))) { for (iterate = mask_upper; *iterate; iterate++) *iterate = toupper(*iterate); } else { perror("pfspls.c: strdup() failed"); return 1; } #endif while (buftail_n>0) { /* find new-line */ s1=memchr(buftail, '\n', buftail_n); s2=memchr(buftail, '\r', buftail_n); if (!s1) { if (!s2) break; s1=s2; } else if (s2) if (s2 * * playlist related functions (used by .pls and .m3u parsers) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "dirdb.h" #include "gendir.h" #include "mdb.h" #include "modlist.h" #include "pfilesel.h" #include "playlist.h" #include "stuff/compat.h" void fsAddPlaylist(struct modlist *ml, const char *path, const char *mask, unsigned long opt, const char *source) { const struct dmDrive *dmDrive=0; char fullpath[PATH_MAX+1]; struct stat st; struct modlistentry retval; char *s3; if (source[0]!='/') { if ((s3=index(source, '/'))) if (s3[-1]==':') { if (!(dmDrive=dmFindDrive(source))) { *s3=0; fprintf(stderr, "[playlist] Drive/Protocol not supported (%s)\n", source); /* Drive/Protocol not supported */ return; } source+=strlen(dmDrive->drivename); if ((source[0]!='/')||strstr(source, "/../")) { /* doesnt catch /.. suffix, but shouldn' be a issue */ fprintf(stderr, "[playlist] Relative paths in fullpath not possible\n"); return; } } } if (!dmDrive) dmDrive=dmFindDrive("file:"); if (strcmp(dmDrive->drivename, "file:")) { fprintf(stderr, "[playlist], API for getting handlers via dmDrive needed. TODO\n"); return; } gendir(path, source, fullpath); /* path's doesn't need to reflect dmDrive, if drive is given, path must be full */ if ((s3=rindex(fullpath, '/'))) s3++; else s3=fullpath; memset(&st, 0, sizeof(st)); memset(&retval, 0, sizeof(retval)); if (stat(fullpath, &st)<0) { fprintf(stderr, "[playlist] stat() failed for %s\n", fullpath); return; } retval.drive=dmDrive; strncpy(retval.name, s3, NAME_MAX); retval.name[NAME_MAX]=0; retval.dirdbfullpath = dirdbResolvePathWithBaseAndRef(dmDrive->basepath, fullpath); fs12name(retval.shortname, s3); if (S_ISREG(st.st_mode)) { /* if (isarchivepath(fullpath)) { retval.flags=MODLIST_FLAG_ARC; strncat(retval.fullname, "/", PATH_MAX-strlen(retval.fullname)-1); } else */{ char curext[NAME_MAX+1]; _splitpath(fullpath, 0, 0, 0, curext); #ifndef FNM_CASEFOLD { char *name_upper; char *iterate; if ((name_upper = strdup(retval.name))) { for (iterate = name_upper; *iterate; iterate++) *iterate = toupper(*iterate); } else { perror("pfsm3u.c: strdup() failed"); dirdbUnref(retval.dirdbfullpath); return; } if (fnmatch(mask, name_upper, 0)||(!fsIsModule(curext))) { free(name_upper); dirdbUnref(retval.dirdbfullpath); return; } free(name_upper); } #else if ((fnmatch(mask, retval.name, FNM_CASEFOLD))||(!fsIsModule(curext))) { dirdbUnref(retval.dirdbfullpath); return; } #endif retval.fileref=mdbGetModuleReference(retval.shortname, st.st_size); retval.adb_ref=0xffffffff; retval.flags=MODLIST_FLAG_FILE; } } else if (S_ISDIR(st.st_mode)) { /* if ((opt&RD_PUTSUBS)) { retval.flags=MODLIST_FLAG_DIR; strncat(retval.fullname, "/", PATH_MAX-strlen(retval.fullname)-1); } else if ((opt&RD_PUTRSUBS)) { strncat(retval.fullname, "/", PATH_MAX-strlen(retval.fullname)-1); fsReadDir(ml,drive, retval.fullname, mask, opt); return; } else*/ { dirdbUnref(retval.dirdbfullpath); return; } } else { dirdbUnref(retval.dirdbfullpath); return; } retval.Read=dosfile_Read; retval.ReadHeader=dosfile_ReadHeader; retval.ReadHandle=dosfile_ReadHandle; modlist_append(ml, &retval); dirdbUnref(retval.dirdbfullpath); } ocp-0.1.21/filesel/mdb.c0000644000175000001440000003174511655541726013770 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Module information DataBase (and some other related stuff= * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss04?????? Stian Skjelstad #include #include #include #include #include #include #include #include "types.h" #include "boot/plinkman.h" #include "boot/psetting.h" #include "stuff/imsrtns.h" #include "mdb.h" #include "modlist.h" #include "pfilesel.h" struct mdbreaddirregstruct *mdbReadDirs = 0; struct __attribute__((packed)) modinfoentry { uint8_t flags; union { struct __attribute__((packed)) { uint8_t modtype; /* 1 */ uint32_t comref; /* 5 */ uint32_t compref; /* 9 */ uint32_t futref; /* 13 */ char name[12]; /* 25 */ uint32_t size; /* 29 */ char modname[32]; /* 61 */ uint32_t date; /* 65 */ uint16_t playtime; /* 67 */ uint8_t channels; /* 68 */ uint8_t moduleflags;/* 69 */ /* last uint8_t flags2 is up-padding for the top uint8_t and so on.. */ } gen; char comment[63]; struct __attribute__((packed)) { char composer[32]; char style[31]; } comp; } mie; }; #define gen mie.gen #define comp mie.comp struct __attribute__((packed)) mdbheader { char sig[60]; uint32_t entries; }; const char mdbsigv1[60] = "Cubic Player Module Information Data Base\x1B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; static struct modinfoentry *mdbData; static uint32_t mdbNum; static int mdbDirty; static uint32_t *mdbReloc; static uint32_t mdbGenNum; static uint32_t mdbGenMax; int fsReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { struct mdbreaddirregstruct *readdirs; for (readdirs=mdbReadDirs; readdirs; readdirs=readdirs->next) if (!readdirs->ReadDir(ml, drive, path, mask, opt)) return 0; return 1; } const char *mdbGetModTypeString(unsigned char type) { return fsTypeNames[type&0xFF]; } int mdbGetModuleType(uint32_t fileref) { if (fileref>=mdbNum) return -1; if ((mdbData[fileref].flags&(MDB_USED|MDB_BLOCKTYPE))!=(MDB_USED|MDB_GENERAL)) return -1; return mdbData[fileref].gen.modtype; } uint8_t mdbReadModType(const char *str) { int v=255; int i; for (i=0; i<256; i++) if (!strcasecmp(str, fsTypeNames[i])) v=i; return v; } int mdbInfoRead(uint32_t fileref) { if (fileref>=mdbNum) return -1; if ((mdbData[fileref].flags&(MDB_USED|MDB_BLOCKTYPE))!=(MDB_USED|MDB_GENERAL)) return -1; return mdbData[fileref].gen.modtype!=mtUnRead; } /* This thing will end up with a register of all valid pre-interprators for modules and friends */ static struct mdbreadinforegstruct *mdbReadInfos=NULL; void mdbRegisterReadInfo(struct mdbreadinforegstruct *r) { r->next=mdbReadInfos; mdbReadInfos=r; if (r->Event) r->Event(mdbEvInit); } void mdbUnregisterReadInfo(struct mdbreadinforegstruct *r) { struct mdbreadinforegstruct *root=mdbReadInfos; if (root==r) { mdbReadInfos=r->next; return; } while (root) { if (root->next==r) { root->next=root->next->next; return; } if (!root->next) return; root=root->next; } } int mdbReadMemInfo(struct moduleinfostruct *m, const char *buf, int len) { struct mdbreadinforegstruct *rinfos; for (rinfos=mdbReadInfos; rinfos; rinfos=rinfos->next) if (rinfos->ReadMemInfo) if (rinfos->ReadMemInfo(m, buf, len)) return 1; return 0; } int mdbReadInfo(struct moduleinfostruct *m, FILE *f) { char mdbScanBuf[1084]; struct mdbreadinforegstruct *rinfos; int maxl; memset(mdbScanBuf, 0, 1084); maxl=1084; maxl=fread(mdbScanBuf, 1, maxl, f); if (mdbReadMemInfo(m, mdbScanBuf, maxl)) return 1; for (rinfos=mdbReadInfos; rinfos; rinfos=rinfos->next) if (rinfos->ReadInfo) if (rinfos->ReadInfo(m, f, mdbScanBuf, maxl)) return 1; return m->modtype==mtUnRead;; } static uint32_t mdbGetNew(void) { uint32_t i; for (i=0; i=mdbNum) { fprintf(stderr, "mdbWriteModuleInfo, fileref(%d)flags1=MDB_USED|MDB_DIRTY|MDB_GENERAL|(m->flags1&(MDB_VIRTUAL|MDB_BIGMODULE|MDB_PLAYLIST)); m->flags2=MDB_DIRTY|MDB_COMPOSER; m->flags3=MDB_DIRTY|MDB_COMMENT; m->flags4=MDB_DIRTY|MDB_FUTURE; if (*m->composer||*m->style) m->flags2|=MDB_USED; if (*m->comment) m->flags3|=MDB_USED; if (m->compref!=0xFFFFFFFF) mdbData[m->compref].flags=MDB_DIRTY; if (m->comref!=0xFFFFFFFF) mdbData[m->comref].flags=MDB_DIRTY; if (m->futref!=0xFFFFFFFF) mdbData[m->futref].flags=MDB_DIRTY; m->compref=0xFFFFFFFF; m->comref=0xFFFFFFFF; m->futref=0xFFFFFFFF; if (m->flags2&MDB_USED) { m->compref=mdbGetNew(); if (m->compref!=0xFFFFFFFF) memcpy(mdbData+m->compref, &m->flags2, 70); } if (m->flags3&MDB_USED) { m->comref=mdbGetNew(); if (m->comref!=0xFFFFFFFF) memcpy(mdbData+m->comref, &m->flags3, 70); } if (m->flags4&MDB_USED) { m->futref=mdbGetNew(); if (m->futref!=0xFFFFFFFF) memcpy(mdbData+m->futref, &m->flags4, 70); } memcpy(mdbData+fileref, m, 70); mdbDirty=1; return 1; } void mdbScan(struct modlistentry *m) { if (!(m->flags&MODLIST_FLAG_FILE)) return; if (!mdbInfoRead(m->fileref)) /* use mdbReadInfo again here ? */ { struct moduleinfostruct mdbEditBuf; FILE *f; if (m->flags&MODLIST_FLAG_VIRTUAL) /* don't scan virtual files */ return; if (!(f=m->ReadHandle(m))) return; mdbGetModuleInfo(&mdbEditBuf, m->fileref); mdbReadInfo(&mdbEditBuf, f); fclose(f); mdbWriteModuleInfo(m->fileref, &mdbEditBuf); } } void mdbRegisterReadDir(struct mdbreaddirregstruct *r) { r->next=mdbReadDirs; mdbReadDirs=r; } void mdbUnregisterReadDir(struct mdbreaddirregstruct *r) { struct mdbreaddirregstruct *root=mdbReadDirs; if (root==r) { mdbReadDirs=r->next; return; } while (root) { if (root->next==r) { root->next=root->next->next; return; } if (!root->next) return; root=root->next; } } static int miecmp(const void *a, const void *b) { struct modinfoentry *c=&mdbData[*(uint32_t *)a]; struct modinfoentry *d=&mdbData[*(uint32_t *)b]; if (c->gen.size==d->gen.size) return memcmp(c->gen.name, d->gen.name, 12); if (c->gen.sizegen.size) return -1; else return 1; } int mdbInit(void) { char path[PATH_MAX+1]; int f; struct mdbheader header; uint32_t i; mdbDirty=0; mdbData=0; mdbNum=0; mdbReloc=0; mdbGenNum=0; mdbGenMax=0; if ((strlen(cfConfigDir)+12)>PATH_MAX) { fprintf(stderr, "mdb: CPMODNDO.DAT path is too long\n"); return 1; } strcpy(path, cfConfigDir); strcat(path, "CPMODNFO.DAT"); if ((f=open(path, O_RDONLY))<0) { perror("open(cfConfigDir/CPMODNDO.DAT)"); return 1; } fprintf(stderr, "Loading %s .. ", path); if (read(f, &header, sizeof(header))!=sizeof(header)) { fprintf(stderr, "No header\n"); close(f); return 1; } if (memcmp(header.sig, mdbsigv1, sizeof(mdbsigv1))) { fprintf(stderr, "Invalid header\n"); close(f); return 1; } mdbNum=uint32_little(header.entries); if (!mdbNum) { close(f); fprintf(stderr, "EOF\n"); return 1; } mdbData=malloc(sizeof(struct modinfoentry)*mdbNum); if (!mdbData) return 0; if (read(f, mdbData, mdbNum*sizeof(*mdbData))!=(signed)(mdbNum*sizeof(*mdbData))) { mdbNum=0; free(mdbData); mdbData=0; close(f); return 1; } close(f); for (i=0; iPATH_MAX) { fprintf(stderr, "mdb: CPMODNDO.DAT path is too long\n"); return; } strcpy(path, cfConfigDir); strcat(path, "CPMODNFO.DAT"); if ((f=open(path, O_WRONLY|O_CREAT, S_IREAD|S_IWRITE))<0) { perror("open(CPMODNFO.DAT)"); return; } lseek(f, 0, SEEK_SET); memcpy(header.sig, mdbsigv1, sizeof(mdbsigv1)); header.entries = uint32_little(mdbNum); while (1) { ssize_t res; res = write(f, &header, sizeof(header)); if (res < 0) { if (errno==EAGAIN) continue; if (errno==EINTR) continue; fprintf(stderr, __FILE__ " write() to %s failed: %s\n", path, strerror(errno)); exit(1); } else if (res != sizeof(header)) { fprintf(stderr, __FILE__ " write() to %s returned only partial data\n", path); exit(1); } else break; } i=0; while (i>1]]; int ret; if (size==m->gen.size) ret=memcmp(name, m->gen.name, 12); else if (sizegen.size) ret=-1; else ret=1; if (!ret) return min[num>>1]; if (ret<0) num>>=1; else { min+=(num>>1)+1; num=(num-1)>>1; } } mn=min-mdbReloc; i=mdbGetNew(); if (i==0xFFFFFFFF) return 0xFFFFFFFF; if (mdbGenNum==mdbGenMax) { void *n; mdbGenMax+=512; if (!(n=realloc(mdbReloc, sizeof (*mdbReloc)*mdbGenMax))) return 0xFFFFFFFF; mdbReloc=(uint32_t *)n; } memmovel(mdbReloc+mn+1, mdbReloc+mn, mdbGenNum-mn); mdbReloc[mn]=(uint32_t)i; mdbGenNum++; m=&mdbData[i]; m->flags=MDB_DIRTY|MDB_USED|MDB_GENERAL; memcpy(m->gen.name, name, 12); m->gen.size=size; m->gen.modtype=0xFF; m->gen.comref=0xFFFFFFFF; m->gen.compref=0xFFFFFFFF; m->gen.futref=0xFFFFFFFF; memset(m->gen.modname, 0, 32); m->gen.date=0; m->gen.playtime=0; m->gen.channels=0; m->gen.moduleflags=0; mdbDirty=1; return (uint32_t)i; } int mdbGetModuleInfo(struct moduleinfostruct *m, uint32_t fileref) { memset(m, 0, sizeof(struct moduleinfostruct)); if (fileref>=mdbNum) /* needed, since we else might index mdbData wrong */ goto invalid; if ((mdbData[fileref].flags&(MDB_USED|MDB_BLOCKTYPE))!=(MDB_USED|MDB_GENERAL)) { invalid: m->modtype=0xFF; m->comref=0xFFFFFFFF; m->compref=0xFFFFFFFF; m->futref=0xFFFFFFFF; return 0; } memcpy(m, mdbData+fileref, 70); if (m->compref!=0xFFFFFFFF) memcpy(&m->flags2, mdbData+m->compref, 70); if (m->comref!=0xFFFFFFFF) memcpy(&m->flags3, mdbData+m->comref, 70); if (m->futref!=0xFFFFFFFF) memcpy(&m->flags4, mdbData+m->futref, 70); return 1; } ocp-0.1.21/filesel/Makefile0000644000175000001440000001022511655541726014510 0ustar stianusersTOPDIR=../ include $(TOPDIR)Rules.make ifeq ($(CDROM_SUPPORT),1) CDROM_SO=cdrom$(LIB_SUFFIX) endif arctar_so=arctar.o arczip_so=arczip.o cdrom_so=cdrom.o pfilesel_so=adb.o cphlpfs.o dirdb.o pfilesel.o pfsmain.o modlist.o fsptype.o mdb.o pfspls.o pfsm3u.o gendir.o playlist.o ifeq ($(STATIC_BUILD),1) all: $(arctar_so) $(arczip_so) $(cdrom_so) $(pfilesel_so) fstypes.o else all: arctar$(LIB_SUFFIX) arczip$(LIB_SUFFIX) $(CDROM_SO) fstypes.o pfilesel$(LIB_SUFFIX) endif arctar$(LIB_SUFFIX): $(arctar_so) $(CC) $(SHARED_FLAGS) -o $@ $^ arczip$(LIB_SUFFIX): $(arczip_so) $(CC) $(SHARED_FLAGS) -o $@ $^ -lz cdrom$(LIB_SUFFIX): $(cdrom_so) $(CC) $(SHARED_FLAGS) -o $@ $^ pfilesel$(LIB_SUFFIX): $(pfilesel_so) $(CC) $(SHARED_FLAGS) $(MATH_LIBS) -o $@ $^ clean: rm -f *.o *$(LIB_SUFFIX) modlist_test ifeq ($(STATIC_BUILD),1) install: uninstall: else install: $(CP) arctar$(LIB_SUFFIX) "$(DESTDIR)$(LIBDIR)/autoload/30-arctar$(LIB_SUFFIX)" $(CP) arczip$(LIB_SUFFIX) "$(DESTDIR)$(LIBDIR)/autoload/30-arczip$(LIB_SUFFIX)" $(CP) pfilesel$(LIB_SUFFIX) "$(DESTDIR)$(LIBDIR)/autoload/25-pfilesel$(LIB_SUFFIX)" ifeq ($(CDROM_SUPPORT),1) $(CP) $(CDROM_SO) "$(DESTDIR)$(LIBDIR)/autoload/30-cdrom$(LIB_SUFFIX)" endif uninstall: rm -f "$(DESTDIR)$(LIBDIR)/autoload/30-arctar$(LIB_SUFFIX)" rm -f "$(DESTDIR)$(LIBDIR)/autoload/30-arczip$(LIB_SUFFIX)" rm -f "$(DESTDIR)$(LIBDIR)/autoload/25-pfilesel$(LIB_SUFFIX)" ifeq ($(CDROM_SUPPORT),1) rm -f "$(DESTDIR)$(LIBDIR)/autoload/30-cdrom$(LIB_SUFFIX)" endif endif adb.o: adb.c adb.h \ ../config.h \ ../types.h \ dirdb.h \ ../boot/plinkman.h \ ../boot/psetting.h \ ../stuff/poutput.h \ modlist.h \ mdb.h \ pfilesel.h \ ../stuff/compat.h $(CC) adb.c -o $@ -c dirdb.o: dirdb.c dirdb.h \ ../config.h \ ../types.h \ ../boot/psetting.h $(CC) dirdb.c -o $@ -c cdrom.o: cdrom.c \ ../config.h \ ../types.h \ dirdb.h \ ../boot/plinkman.h \ modlist.h \ pfilesel.h \ ../stuff/err.h \ mdb.h $(CC) cdrom.c -o $@ -c mdb.o: mdb.c mdb.h \ ../config.h \ ../types.h \ ../boot/plinkman.h \ ../boot/psetting.h \ modlist.h \ pfilesel.h \ ../stuff/imsrtns.h $(CC) mdb.c -o $@ -c cphlpfs.o: cphlpfs.c cphlpfs.h \ ../config.h \ ../types.h \ ../stuff/framelock.h \ ../stuff/poutput.h \ ../help/cphelper.h $(CC) cphlpfs.c -o $@ -c fsptype.o: fsptype.c \ ../config.h \ ../types.h \ dirdb.h \ mdb.h $(CC) fsptype.c -o $@ -c modlist.o: modlist.c modlist.h \ ../config.h \ ../types.h \ ../stuff/compat.h \ dirdb.h $(CC) modlist.c -o $@ -c modlist_test.o: modlist_test.c \ ../config.h modlist.h $(CC) modlist_test.c -o $@ -c modlist_test: modlist.o modlist_test.o $(CC) -o $@ $^ -lefence pfilesel.o: pfilesel.c pfilesel.h \ ../config.h \ ../types.h \ adb.h \ ../boot/psetting.h \ ../cpiface/cpiface.h \ cphlpfs.h \ dirdb.h \ gendir.h \ mdb.h \ ../stuff/compat.h \ ../stuff/framelock.h \ ../stuff/poutput.h \ modlist.h $(CC) pfilesel.c -o $@ -c fstypes.o: fstypes.c \ ../config.h \ ../boot/plinkman.h \ mdb.h $(CC) fstypes.c -o $@ -c pfsmain.o: pfsmain.c \ ../config.h \ ../types.h \ mdb.h \ pfilesel.h \ ../boot/plinkman.h \ ../boot/pmain.h \ ../stuff/poutput.h \ ../stuff/err.h \ ../boot/psetting.h $(CC) pfsmain.c -o $@ -c arctar.o: arctar.c \ ../config.h \ ../types.h \ adb.h \ mdb.h \ mif.h \ modlist.h \ ../boot/plinkman.h \ ../stuff/compat.h \ pfilesel.h $(CC) arctar.c -o $@ -c arczip.o: arczip.c \ ../config.h \ ../types.h \ adb.h \ mdb.h \ mif.h \ modlist.h \ ../boot/plinkman.h \ ../boot/psetting.h \ ../stuff/compat.h \ ../stuff/pagesize.inc.c \ pfilesel.h $(CC) arczip.c -o $@ -c pfspls.o: pfspls.c \ ../config.h \ ../types.h \ adb.h \ dirdb.h \ gendir.h \ mdb.h \ modlist.h \ playlist.h \ pfilesel.h \ ../stuff/compat.h $(CC) pfspls.c -o $@ -c pfsm3u.o: pfsm3u.c \ ../config.h \ ../types.h \ adb.h \ dirdb.h \ gendir.h \ mdb.h \ modlist.h \ playlist.h \ pfilesel.h \ ../stuff/compat.h $(CC) pfsm3u.c -o $@ -c gendir.o: gendir.c \ ../config.h \ ../types.h \ gendir.h $(CC) gendir.c -o $@ -c playlist.o: playlist.c \ ../config.h \ ../types.h \ adb.h \ dirdb.h \ gendir.h \ mdb.h \ modlist.h \ pfilesel.h \ playlist.h \ ../stuff/compat.h $(CC) playlist.c -o $@ -c ocp-0.1.21/filesel/cdrom.c0000644000175000001440000002735511655541726014334 0ustar stianusers/* * copyright (c) '94-'10 Niklas Beisert * * UNIX cdrom filebrowser * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040907 Stian Skjelstad * -first release * -ss040920 Stian Skjelstad * -Duplicate filedescriptor, so we can try to avoid the kernel re-reading * the toc when we access the cdrom from the fileselector while in use */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "types.h" #include "dirdb.h" #include "boot/plinkman.h" #include "modlist.h" #include "mdb.h" #include "pfilesel.h" #include "stuff/err.h" struct cdrom_t; static struct cdrom_t { char dev[32]; char vdev[12]; int caps; int fd; uint32_t dirdbnode; struct cdrom_t *next; } *root; static struct dmDrive *dmCDROM=0; static struct mdbreaddirregstruct cdReadDirReg; static void try(const char *dev, const char *vdev) { struct cdrom_t *temp; int fd; #ifdef CDROM_VERBOSE fprintf(stderr, "Testing %s\n", dev); #endif if ((fd=open(dev, O_RDONLY|O_NONBLOCK))>=0) { int caps; if ((caps=ioctl(fd, CDROM_GET_CAPABILITY, 0))>=0) { temp=malloc(sizeof(struct cdrom_t)); strcpy(temp->dev, dev); strcpy(temp->vdev, vdev); temp->dirdbnode=dirdbFindAndRef(dmCDROM->basepath, vdev); temp->caps=caps; temp->next=root; temp->fd=fd; fcntl(fd, F_SETFD, 1); root=temp; #ifdef CDROM_VERBOSE fprintf(stderr, "%s is a cdrom\n", dev); if (caps&CDC_CLOSE_TRAY) fprintf(stderr, "CDC_CLOSE_TRAY\n"); if (caps&CDC_OPEN_TRAY) fprintf(stderr, "CDC_OPEN_TRAY\n"); if (caps&CDC_LOCK) fprintf(stderr, "CDC_LOCK\n"); if (caps&CDC_SELECT_SPEED) fprintf(stderr, "CDC_SELECT_SPEED\n"); if (caps&CDC_SELECT_DISC) fprintf(stderr, "CDC_SELECT_DISC\n"); if (caps&CDC_MULTI_SESSION) fprintf(stderr, "CDC_MULTI_SESSION\n"); if (caps&CDC_MCN) fprintf(stderr, "CDC_MCN\n"); if (caps&CDC_MEDIA_CHANGED) fprintf(stderr, "CDC_MEDIA_CHANGED\n"); if (caps&CDC_PLAY_AUDIO) fprintf(stderr, "CDC_PLAY_AUDIO\n"); if (caps&CDC_RESET) fprintf(stderr, "CDC_RESET\n"); if (caps&CDC_IOCTLS) fprintf(stderr, "CDC_IOCTLS\n"); if (caps&CDC_DRIVE_STATUS) fprintf(stderr, "CDC_DRIVE_STATUS\n"); if (caps&CDC_GENERIC_PACKET) fprintf(stderr, "CDC_GENERIC_PACKET\n"); if (caps&CDC_CD_R) fprintf(stderr, "CDC_CD_R\n"); if (caps&CDC_CD_RW) fprintf(stderr, "CDC_CD_RW\n"); if (caps&CDC_DVD) fprintf(stderr, "CDC_DVD\n"); if (caps&CDC_DVD_R) fprintf(stderr, "CDC_DVD_R\n"); if (caps&CDC_DVD_RAM) fprintf(stderr, "CDC_DVD_RAM\n"); switch (ioctl(fd, CDROM_DISC_STATUS)) { case CDS_NO_INFO: fprintf(stderr, "CDROM doesn't support CDROM_DISC_STATUS\n"); break; case CDS_NO_DISC: fprintf(stderr, "No disc\n"); break; case CDS_AUDIO: fprintf(stderr, "Audio CD\n"); break; case CDS_DATA_1: fprintf(stderr, "Data CD, mode 1, form 1\n"); break; case CDS_DATA_2: fprintf(stderr, "Data CD, mode 1, form 2\n"); break; case CDS_XA_2_1: fprintf(stderr, "Data CD, mode 2, form 1\n"); break; case CDS_XA_2_2: fprintf(stderr, "Data CD, mode 2, form 2\n"); break; case CDS_MIXED: fprintf(stderr, "Mixed mode CD\n"); break; case -1: perror("ioctl()"); break; default: fprintf(stderr, "Unknown cd type\n"); } { struct cdrom_mcn mcn; if (!ioctl(fd, CDROM_GET_MCN, &mcn)) fprintf(stderr, "MCN: %13s\n", mcn.medium_catalog_number); } { struct cdrom_tochdr tochdr; if (!ioctl(fd, CDROMREADTOCHDR, &tochdr)) { #if 0 int i; struct cdrom_tocentry tocentry; #endif fprintf(stderr, "Start track: %d\nStop track: %d\n", tochdr.cdth_trk0, tochdr.cdth_trk1); #if 0 for (i=tochdr.cdth_trk0;i<=(tochdr.cdth_trk1+1);i++) { if (i>tochdr.cdth_trk1) i=CDROM_LEADOUT; tocentry.cdte_track=i; tocentry.cdte_format=CDROM_MSF; /* CDROM_LBA */ if (!ioctl(fd, CDROMREADTOCENTRY, &tocentry)) { fprintf(stderr, "cdte_track: %d%s\n", tocentry.cdte_track, (i==CDROM_LEADOUT)?" LEADOUT":""); fprintf(stderr, "cdte_adr: %d\n", tocentry.cdte_adr); fprintf(stderr, "cdte_ctrl: %d %s\n", tocentry.cdte_ctrl, (tocentry.cdte_ctrl&CDROM_DATA_TRACK)?"(DATA)":"AUDIO"); fprintf(stderr, "cdte_format: %d\n", tocentry.cdte_format); if (tocentry.cdte_format==CDROM_MSF){ fprintf(stderr, "cdte_addr.msf.minute: %d\n", tocentry.cdte_addr.msf.minute); fprintf(stderr, "cdte_addr.msf.second: %d\n", tocentry.cdte_addr.msf.second); fprintf(stderr, "cdte_addr.msf.frame: %d\n", tocentry.cdte_addr.msf.frame); } else { fprintf(stderr, "cdte_addr.lba: %d\n", tocentry.cdte_addr.lba); } fprintf(stderr, "cdte_datamode: %d\n", tocentry.cdte_datamode); fprintf(stderr, "\n"); } } #endif } } #endif } else close(fd); } } static int cdint(void) { char dev[32], vdev[12]; char a; root=0; mdbRegisterReadDir(&cdReadDirReg); dmCDROM=RegisterDrive("cdrom:"); fprintf(stderr, "Locating cdroms [ ]\010\010\010"); for (a=0;a<=32;a++) { sprintf(dev, "/dev/cdroms/cdrom%d", a); sprintf(vdev, "cdrom%d", a); try(dev, vdev); } fprintf(stderr, "."); for (a=0;a<=32;a++) { sprintf(dev, "/dev/scd%d", a); sprintf(vdev, "scd%d", a); try(dev, vdev); } fprintf(stderr, "."); for (a='a';a<='z';a++) { sprintf(dev, "/dev/hd%c", a); sprintf(vdev, "hd%c", a); try(dev, vdev); } fprintf(stderr, ".]\n"); return errOk; } static void cdclose(void) { struct cdrom_t *current=root; while (current) { struct cdrom_t *temp=current; temp=current->next; dirdbUnref(current->dirdbnode); free(current); current=temp; } mdbUnregisterReadDir(&cdReadDirReg); } static FILE *cdrom_ReadHandle(struct modlistentry *entry) { int fd=dup(((struct cdrom_t *)entry->adb_ref)->fd); if (fd>=0) return fdopen(fd, "r"); return NULL; } static int cdReadDir(struct modlist *ml, const struct dmDrive *drive, const uint32_t path, const char *mask, unsigned long opt) { struct modlistentry entry; if (strcmp(drive->drivename, "cdrom:")) return 1; if (path==drive->basepath) /* / */ { struct cdrom_t *current=root; while (current) { strcpy(entry.shortname, current->vdev); strcpy(entry.name, current->dev); entry.drive=drive; entry.dirdbfullpath=current->dirdbnode; dirdbRef(entry.dirdbfullpath); /* overkill */ entry.flags=MODLIST_FLAG_DIR; entry.fileref=0xffffffff; entry.adb_ref=0xffffffff; entry.Read=0; entry.ReadHeader=0; entry.ReadHandle=0; modlist_append(ml, &entry); dirdbUnref(entry.dirdbfullpath); /* overkill */ current=current->next; } } else { struct cdrom_t *current=root; while (current) { if (current->dirdbnode==path) { struct cdrom_tochdr tochdr; struct cdrom_tocentry tocentry; struct cdrom_tocentry tocentryN; int initlba=-1; int lastlba=lastlba; /* remove a warning */ if (!ioctl(current->fd, CDROMREADTOCHDR, &tochdr)) { int i; for (i=tochdr.cdth_trk0;i<=(tochdr.cdth_trk1);i++) { /* if (i>tochdr.cdth_trk1) i=CDROM_LEADOUT; */ tocentry.cdte_track=i; tocentry.cdte_format=CDROM_LBA; /* CDROM_MSF */ if (!ioctl(current->fd, CDROMREADTOCENTRY, &tocentry)) { tocentryN.cdte_track=(i==tochdr.cdth_trk1)?CDROM_LEADOUT:i+1; tocentryN.cdte_format=CDROM_LBA; ioctl(current->fd, CDROMREADTOCENTRY, &tocentryN); /* fprintf(stderr, "cdte_track: %d%s\n", tocentry.cdte_track, (i==CDROM_LEADOUT)?" LEADOUT":""); fprintf(stderr, "cdte_adr: %d\n", tocentry.cdte_adr); fprintf(stderr, "cdte_ctrl: %d %s\n", tocentry.cdte_ctrl, (tocentry.cdte_ctrl&CDROM_DATA_TRACK)?"(DATA)":"AUDIO"); fprintf(stderr, "cdte_format: %d\n", tocentry.cdte_format); if (tocentry.cdte_format==CDROM_MSF){ fprintf(stderr, "cdte_addr.msf.minute: %d\n", tocentry.cdte_addr.msf.minute); fprintf(stderr, "cdte_addr.msf.second: %d\n", tocentry.cdte_addr.msf.second); fprintf(stderr, "cdte_addr.msf.frame: %d\n", tocentry.cdte_addr.msf.frame); } else { fprintf(stderr, "cdte_addr.lba: %d\n", tocentry.cdte_addr.lba); } fprintf(stderr, "cdte_datamode: %d\n", tocentry.cdte_datamode); */ if (!(tocentry.cdte_ctrl&CDROM_DATA_TRACK)) { char buffer[12]; struct moduleinfostruct mi; snprintf(buffer, 12, "TRACK%02d.CDA", i); if (initlba<0) initlba=tocentry.cdte_addr.lba; lastlba=tocentryN.cdte_addr.lba; fs12name(entry.shortname,buffer); strcpy(entry.name, buffer); entry.drive=drive; entry.dirdbfullpath=dirdbFindAndRef(path, buffer); entry.flags=MODLIST_FLAG_FILE|MODLIST_FLAG_VIRTUAL; if ((entry.fileref=mdbGetModuleReference(entry.shortname, 0))==0xffffffff) { dirdbUnref(entry.dirdbfullpath); return 0; } if (mdbGetModuleInfo(&mi, entry.fileref)) { mi.modtype=mtCDA; mi.channels=2; mi.playtime=(tocentryN.cdte_addr.lba - tocentry.cdte_addr.lba)/CD_FRAMES; strcpy(mi.comment, current->vdev); strcpy(mi.modname, "CDROM audio track"); mdbWriteModuleInfo(entry.fileref, &mi); } entry.adb_ref=(int)current; /* nasty hack, but hey.. it is free of use */ #warning ADB_REF hack used here entry.Read=0; entry.ReadHeader=0; entry.ReadHandle=cdrom_ReadHandle; modlist_append(ml, &entry); dirdbUnref(entry.dirdbfullpath); } } } if (initlba>=0) { const char *buffer="DISK.CDA"; struct moduleinfostruct mi; fs12name(entry.shortname,buffer); strcpy(entry.name, buffer); entry.drive=drive; entry.dirdbfullpath=dirdbFindAndRef(path, buffer); entry.flags=MODLIST_FLAG_FILE|MODLIST_FLAG_VIRTUAL; if ((entry.fileref=mdbGetModuleReference(entry.shortname, 0))==0xffffffff) { dirdbUnref(entry.dirdbfullpath); return 0; } if (mdbGetModuleInfo(&mi, entry.fileref)) { mi.modtype=mtCDA; mi.channels=2; mi.playtime=(lastlba - initlba)/CD_FRAMES; strcpy(mi.comment, current->vdev); strcpy(mi.modname, "CDROM audio disc"); mdbWriteModuleInfo(entry.fileref, &mi); } entry.adb_ref=(int)current; /* nasty hack, but hey.. it is free of use */ #warning ADB_REF hack used here entry.Read=0; entry.ReadHeader=0; entry.ReadHandle=cdrom_ReadHandle; modlist_append(ml, &entry); dirdbUnref(entry.dirdbfullpath); } } break; } current=current->next; } } return 1; } static struct mdbreaddirregstruct cdReadDirReg = {cdReadDir MDBREADDIRREGSTRUCT_TAIL}; #ifndef SUPPORT_STATIC_PLUGINS char *dllinfo = ""; #endif DLLEXTINFO_PREFIX struct linkinfostruct dllextinfo = {"cdrom", "OpenCP UNIX audio-cdrom filebrowser (c) 2004-09 Stian Skjelstad", DLLVERSION, 0, Init: cdint, Close: cdclose, PreInit:0, LateInit:0, PreClose:0, LateClose:0}; ocp-0.1.21/filesel/arctar.c0000644000175000001440000002504111655541726014472 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Archive handler for TAR-balls archives * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040816 Stian Skjelstad #include #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "mdb.h" #include "mif.h" #include "modlist.h" #include "pfilesel.h" #include "boot/plinkman.h" #include "stuff/compat.h" struct __attribute__((packed)) posix_header { /* byte offset */ char name[100]; /* 0 */ char mode[8]; /* 100 */ char uid[8]; /* 108 */ char gid[8]; /* 116 */ char size[12]; /* 124 */ char mtime[12]; /* 136 */ char chksum[8]; /* 148 */ char typeflag; /* 156 */ char linkname[100]; /* 157 */ char magic[6]; /* 257 */ char version[2]; /* 263 */ char uname[32]; /* 265 */ char gname[32]; /* 297 */ char devmajor[8]; /* 329 */ char devminor[8]; /* 337 */ char prefix[155]; /* 345 */ /* 500 */ char padding[12]; }; #define TMAGIC "ustar" /* ustar and a null */ #define REGTYPE '0' /* regular file */ #define AREGTYPE '\0' /* regular file */ #define DIRTYPE '5' /* directory */ #define BLOCKSIZE 512 static int format=0; static char ext[NAME_MAX+1]; static char name[NAME_MAX+1]; static char arcname[ARC_PATH_MAX+1]; static int setupformat(const char *path) { _splitpath(path, 0, 0, name, ext); if ((strlen(name)+strlen(ext)+1)>ARC_PATH_MAX) return 0; strcpy(arcname, name); strcat(arcname, ext); if (!strcasecmp(ext, ".tgz")) format=1; else if (!strcasecmp(ext, ".tar.gz")) format=1; else if (!strcasecmp(ext, ".tar.Z")) format=3; else if (!strcasecmp(ext, ".tZ")) format=3; else if (!strcasecmp(ext, ".tar.bz2")) format=2; else if (!strcasecmp(ext, ".tbz")) format=2; else format=0; return 1; } size_t char12tosize_t(char src[12]) { size_t retval; char tmp[13]; strncpy(tmp, src, 12); tmp[12]=0; retval=strtol(tmp, 0, 8); return retval; } static int pipe_pid; static int pipe_fd; static int pipe_done(void) { int result=0; if (pipe_fd>0) { close(pipe_fd); pipe_fd=-1; } if (pipe_pid>0) { kill(SIGKILL, pipe_pid); /* make sure it is dead */ if (waitpid(pipe_pid, &result, WUNTRACED)) result=-1; } pipe_pid=-1; return result; } static int pipe_uncompress(const char *program, char *const argv[], const char *source) { int fds[2]; int fd; pipe_fd=-1; if ((fd=open(source, O_RDONLY))<0) { perror("arctar: open(source, O_RDONLY)"); return -1; } if (pipe(fds)) { perror("arctar: pipe()"); return -1; } if ((pipe_pid=fork())) { if (pipe_pid<0) { perror("arctar: fork()"); close(fds[1]); close(fds[0]); close(fd); return -1; } close(fds[1]); close(fd); return pipe_fd=fds[0]; } close(fds[0]); close(1); if (dup(fds[1])!=1) { perror(__FILE__ ": dup() failed #1"); exit(1); } close(fds[1]); close(0); if (dup(fd)!=0) { perror(__FILE__ ": dup() failed #2"); exit(1); } close(fd); execvp(program, argv); perror("arctar: execlp(program, argv, NULL)"); exit(-1); } #define BUFFER_SIZE 128*1024 static int adbTARScan(const char *path) { uint32_t arcref; struct arcentry a; int extfd; char buffer[BUFFER_SIZE]; size_t bufferfill=0; int retval; size_t skip=0; size_t requiredata=0; /* fprintf(stderr, "adbTARScan, %s\n", path);*/ if (!setupformat(path)) return 0; switch (format) { /* case 0: */ default: /* avoids warning -ss040902 */ extfd=open(path, O_RDONLY); break; case 1: { char *argv[5]; argv[0]="gunzip"; argv[1]="-c"; argv[2]="-d"; argv[3]="-f"; argv[4]=NULL; extfd=pipe_uncompress("gunzip", argv, path); break; } case 2: { char *argv[4]; argv[0]="bzcat"; argv[1]="-d"; argv[2]="-c"; argv[3]=NULL; extfd=pipe_uncompress("bzcat", argv, path); break; } case 3: { char *argv[2]; argv[0]="zcat"; argv[1]=NULL; extfd=pipe_uncompress("zcat", argv, path); break; } } if (extfd<0) return 0; if ((retval=read(extfd, buffer, BUFFER_SIZE))<=0) { pipe_done(); return 0; } bufferfill=retval; memset(a.name, 0, sizeof(a.name)); strncpy(a.name, arcname, sizeof(a.name)-1); a.size=_filelength(path); a.flags=ADB_ARC; if (!adbAdd(&a)) { pipe_done(); return 0; } arcref=adbFind(arcname); while (1) { while ((bufferfill>(sizeof(struct posix_header)+requiredata))&&(!skip)) { struct posix_header *entry=(struct posix_header *)buffer; /* do we need this entry? */ size_t size; if (strncmp(entry->magic, "ustar", 5)) { if (memcmp(entry->magic, "\0\0\0\0\0\0", 6)) { fprintf(stderr, "arctar: Error in TAR-stream: %s\n", path); pipe_done(); return 0; } } if (!*entry->name) { pipe_done(); return 1; } /* fprintf(stderr, "arctar: Entry: %s\n", entry->name); */ size=char12tosize_t(entry->size); _splitpath(entry->name, 0, 0, name, ext); if(fsIsModule(ext)) { if ( ((strlen(entry->name)+1)typeflag==REGTYPE) || (entry->typeflag==AREGTYPE) ) ) { /* TODO if ((!strcasecmp(ext, MIF_EXT))&&size<65536) requiredata=size; else*/ { requiredata=1084; if (sizename); a.size=size; a.flags=0; a.parent=arcref; if(!adbAdd(&a)) { pipe_done(); return 0; } strcpy(a.name, name); strcat(a.name, ext); if (fsScanInArc) { char shortname[12]; uint32_t fileref; struct moduleinfostruct mi; fs12name(shortname, a.name); fileref=mdbGetModuleReference(shortname, a.size); if (fileref==0xffffffff) { pipe_done(); return 0; } if (!mdbInfoRead(fileref)) { if (mdbGetModuleInfo(&mi, fileref)) { mdbReadMemInfo(&mi, buffer+sizeof(struct posix_header), 1084); mdbWriteModuleInfo(fileref, &mi); } } /* TODO MIF_EXT a.name.... if ((!stricmp(ext, MIF_EXT)) && (size<65536)) mifMemRead(a.name, size, buffer+sizeof(struct posix_header)); */ } requiredata=0; } } skip=(sizeof(struct posix_header)+size+BLOCKSIZE-1)&~(BLOCKSIZE-1); } if (skip) { if (skip>bufferfill) { skip-=bufferfill; bufferfill=0; } else { memmove(buffer, buffer+skip, bufferfill-skip); bufferfill-=skip; skip=0; } } retval=read(extfd, buffer+bufferfill, BUFFER_SIZE-bufferfill); if (retval<=0) break; bufferfill+=retval; } pipe_done(); return 1; } static int adbTARCall(const int act, const char *apath, const char *fullname, const int fd) { /* fprintf(stderr, "adbTARCall, %d %s %s %s\n", act, apath, file, dpath); */ if (!setupformat(apath)) return 0; switch (act) { case adbCallGet: { char *argv[6]; pid_t child; int status; argv[0]="tar"; switch(format) { case 0: argv[1]="xf"; break; case 1: argv[1]="xfz"; break; case 2: argv[1]="xfj"; break; case 3: argv[1]="xfZ"; break; } argv[2]=(char *)apath; /* dirty, but should be safe */ argv[3]="-O"; argv[4]=(char *)fullname; /* dirty, but should be safe */ argv[5]=NULL; if (!(child=fork())) { close(1); if (dup(fd)!=1) { perror(__FILE__ ": dup() failed #3: "); exit(1); } execvp("tar", argv); perror(__FILE__": execvp(tar, argv): "); exit(1); } if (child<0) { perror(__FILE__ ": fork(): "); return 0; } if (waitpid(child, &status, WUNTRACED)<0) { perror(__FILE__ ": waitpid(): "); return 0; } if (status) { fprintf(stderr, __FILE__ ": Child exited with error on archive %s\n", apath); return 0; } return 1; } case adbCallPut: return 0; case adbCallDelete: return 0; case adbCallMoveTo: return 0; case adbCallMoveFrom: return 0; } return 0; } static struct adbregstruct adbTARReg1 = {".TGZ", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static struct adbregstruct adbTARReg2 = {".TBZ", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static struct adbregstruct adbTARReg3 = {".TAR", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static struct adbregstruct adbTARReg4 = {".TZ", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static struct adbregstruct adbTARReg5 = {".TAR.GZ", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static struct adbregstruct adbTARReg6 = {".TAR.BZ2", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static struct adbregstruct adbTARReg7 = {".TAR.Z", adbTARScan, adbTARCall ADBREGSTRUCT_TAIL}; static void __attribute__((constructor))init(void) { adbRegister(&adbTARReg1); adbRegister(&adbTARReg2); adbRegister(&adbTARReg3); adbRegister(&adbTARReg4); adbRegister(&adbTARReg5); adbRegister(&adbTARReg6); adbRegister(&adbTARReg7); } static void __attribute__((destructor))done(void) { adbUnregister(&adbTARReg1); adbUnregister(&adbTARReg2); adbUnregister(&adbTARReg3); adbUnregister(&adbTARReg4); adbUnregister(&adbTARReg5); adbUnregister(&adbTARReg6); adbUnregister(&adbTARReg7); } #ifndef SUPPORT_STATIC_PLUGINS char *dllinfo = ""; #endif DLLEXTINFO_PREFIX struct linkinfostruct dllextinfo = {"arctar", "OpenCP Archive Reader: .TAR (c) 2004-09 Stian Skjelstad", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/filesel/arczip.c0000644000175000001440000003056711655541726014517 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Archive handler for ZIP archives * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb980510 Niklas Beisert * -first release * -kb980717 Tammo Hinrichs * -added _dllinfo record * -fd981206 Felix Domke * -edited for new binfile */ #include "config.h" #include #include #include #include #include #include #include #include #include "types.h" #include "adb.h" #include "mdb.h" #include "mif.h" #include "modlist.h" #include "pfilesel.h" #include "boot/plinkman.h" #include "boot/psetting.h" #include "stuff/compat.h" #include "stuff/pagesize.inc.c" static char mdbScanBuf[1084]; static uint8_t adbScanBuf[2048]; struct __attribute__((packed)) local_file_header { uint32_t sig; uint16_t ver; uint16_t opt; uint16_t method; uint32_t d1; uint32_t d2; uint32_t csize; uint32_t osize; uint16_t flen; uint16_t xlen; }; static int method_supported(int method) { return (method==0)||(method==8)||(method==9); } static int decode_partial(char *dest, size_t destlen, uint8_t *src, size_t srclen, int method) { switch (method) { case 0: { if (destlen > srclen ) destlen = srclen; memcpy(dest, src, destlen); break; } case 8: case 9: { z_stream strm; int res; memset(&strm, 0, sizeof(strm)); strm.next_in=src; strm.avail_in=(uLong)srclen; strm.next_out=(Bytef *)dest; strm.avail_out=(uLongf)destlen; if ((res=inflateInit2(&strm, -15))) { fprintf(stderr, "arcZIP: InflateInit2 failed (%d)\n", res); destlen=0; } else { res=inflate(&strm, 1); destlen=strm.total_out; inflateEnd(&strm); } break; } } return destlen; } static int decode_to_fd(char *src, ssize_t srclen, int dest, int method) { switch (method) { case 0: { return (write(dest, src, srclen)==srclen); break; } case 8: case 9: { Bytef buffer[65536]; z_stream strm; int res; memset(&strm, 0, sizeof(strm)); strm.next_in=(Bytef *)src; strm.avail_in=srclen; strm.next_out=buffer; strm.avail_out=sizeof(buffer); #ifdef ZIP_DEBUG fprintf(stderr, "pre\n"); fprintf(stderr, "strm.next_in=%p\n", strm.next_in); fprintf(stderr, "strm.avail_in=%d\n", strm.avail_in); #endif if ((res=inflateInit2(&strm, -15))) { fprintf(stderr, "arcZIP: InflateInit2 failed (%d)\n", res); return 0; } #ifdef ZIP_DEBUG fprintf(stderr, "after init\n"); fprintf(stderr, "strm.next_in=%p\n", strm.next_in); fprintf(stderr, "strm.avail_in=%d\n", strm.avail_in); #endif while (1) { int len; #ifdef ZIP_DEBUG fprintf(stderr, "before inflate\n"); fprintf(stderr, "strm.next_in=%p\n", strm.next_in); fprintf(stderr, "strm.avail_in=%d\n", strm.avail_in); #endif switch (inflate(&strm, 1)) { case Z_OK: len=sizeof(buffer)-strm.avail_out; #ifdef ZIP_DEBUG fprintf(stderr, "Z_OK, len=%d\n", len); #endif if (write(dest, buffer, len)!=len) { perror("arcZIP: write()"); return 0; } strm.next_out=buffer; strm.avail_out=sizeof(buffer); break; case Z_STREAM_END: len=sizeof(buffer)-strm.avail_out; #ifdef ZIP_DEBUG fprintf(stderr, "Z_STREAM_END: len=%d\n", len); #endif if (write(dest, buffer, len)!=len) { perror("arcZIP: write()"); return 0; } strm.next_out=buffer; strm.avail_out=sizeof(buffer); inflateEnd(&strm); return 1; break; default: if (strm.msg) fprintf(stderr, "arcZIP: inflate(): %s\n", strm.msg); else fprintf(stderr, "arcZIP: inflate(): unknown error\n"); inflateEnd(&strm); return 0; } } } break; default: fprintf(stderr, "arcZIP: Invalid method (%d)\n", method); } return 0; } static int openZIP(const char *path) { struct stat st; int extfd=-1; if ((extfd=open(path, O_RDONLY))<0) { perror("arcZIP: open(path, O_RDONLY)"); return -1; } if ((fstat(extfd, &st))<0) { perror("arcZIP: fstat(extfd, &st)"); close(extfd); return -1; } if (!(S_ISREG(st.st_mode))) { fprintf(stderr, "arcZIP: Not a regular file\n"); close(extfd); return -1; } return extfd; } static int adbZIPScan(const char *path) { char ext[NAME_MAX+1]; char name[NAME_MAX+1]; char arcname[ARC_PATH_MAX+1]; int extfd=-1; uint32_t arcref; struct arcentry a; _splitpath(path, 0, 0, name, ext); if ((strlen(name)+strlen(ext)+1)>ARC_PATH_MAX) return 0; strcpy(arcname, name); strcat(arcname, ext); if ((extfd=openZIP(path))<0) return 0; memset(a.name, 0, sizeof(a.name)); strncpy(a.name, arcname, sizeof(a.name)-1); lseek(extfd, 0, SEEK_END); a.size=lseek(extfd, 0, SEEK_CUR); lseek(extfd, 0, SEEK_SET); a.flags=ADB_ARC; if (!adbAdd(&a)) { close(extfd); return 0; } arcref=adbFind(arcname); while (1) { off_t nextpos; struct local_file_header hdr; if (read(extfd, &hdr, sizeof(hdr))!=sizeof(hdr)) break; hdr.sig = uint32_little (hdr.sig); hdr.ver = uint16_little (hdr.ver); hdr.opt = uint16_little (hdr.opt); hdr.method = uint16_little (hdr.method); hdr.d1 = uint32_little (hdr.d1); hdr.d2 = uint32_little (hdr.d2); hdr.csize = uint32_little (hdr.csize); hdr.osize = uint32_little (hdr.osize); hdr.flen = uint16_little (hdr.flen); hdr.xlen = uint16_little (hdr.xlen); if (hdr.sig!=0x04034B50) break; nextpos=lseek(extfd, 0, SEEK_CUR)+hdr.flen+hdr.xlen+hdr.csize; if (((hdr.flen+1)sizeof(adbScanBuf))?sizeof(adbScanBuf):hdr.csize; if (read(extfd, adbScanBuf, srclen)!=srclen) { close(extfd); return 0; } if ((destlen = decode_partial(mdbScanBuf, destlen, adbScanBuf, srclen, hdr.method))) if (mdbGetModuleInfo(&mi, fileref)) { int res; res=mdbReadMemInfo(&mi, mdbScanBuf, destlen); mdbWriteModuleInfo(fileref, &mi); } } } } /* if ((!stricmp(ext, MIF_EXT)) && (hdr.osize<65536)) { char *obuffer=new char[hdr.osize], *cbuffer=new char[hdr.csize]; file.read(cbuffer, hdr.csize); if (hdr.method==8) inflatemax(obuffer, cbuffer, hdr.osize); else memcpy(obuffer, cbuffer, hdr.osize); mifMemRead(a.name, hdr.osize, obuffer); delete[] obuffer; delete[] cbuffer; }*/ } lseek(extfd, nextpos, SEEK_SET); } close(extfd); return 1; } static int adbZIPCall(const int act, const char *apath, const char *fullname, const int fd) { switch (act) { case adbCallGet: { int extfd; #ifdef ZIP_DEBUG fprintf(stderr, "STIAN act=adbCallGet, apath=%s, fullname=%s, fd=%d\n", apath, fullname, fd); #endif if ((extfd=openZIP(apath))<0) return 0; /* TODO, read EOC */ while (1) { struct local_file_header hdr; char name[ARC_PATH_MAX+1]; if (read(extfd, &hdr, sizeof(hdr))!=sizeof(hdr)) break; hdr.sig = uint32_little (hdr.sig); hdr.ver = uint16_little (hdr.ver); hdr.opt = uint16_little (hdr.opt); hdr.method = uint16_little (hdr.method); hdr.d1 = uint32_little (hdr.d1); hdr.d2 = uint32_little (hdr.d2); hdr.csize = uint32_little (hdr.csize); hdr.osize = uint32_little (hdr.osize); hdr.flen = uint16_little (hdr.flen); hdr.xlen = uint16_little (hdr.xlen); if (hdr.sig!=0x04034B50) break; if (method_supported(hdr.method)) { if ((hdr.flen<=ARC_PATH_MAX)&&!(hdr.opt&0x1)) { memset(name, 0, sizeof(name)); if (read(extfd, name, hdr.flen)!=hdr.flen) { fprintf(stderr, "arcZIP: Premature EOF\n"); close(extfd); return 0; } name[hdr.flen]=0; lseek(extfd, hdr.xlen, SEEK_CUR); if (!strcmp(fullname, name)) { char *data; off_t start = lseek(extfd, 0, SEEK_CUR); off_t length = hdr.csize; off_t mmap_start=start&~((off_t)(pagesize()-1)); off_t mmap_start_pad=start-mmap_start; off_t mmap_length=(mmap_start_pad+length+pagesize()-1)&~((off_t)(pagesize()-1)); if ((data=mmap(0, mmap_length, PROT_READ, MAP_SHARED, extfd, mmap_start))==MAP_FAILED) { perror("arcZIP mmap()"); close(extfd); return 0; } close(extfd); if (!decode_to_fd(data+mmap_start_pad, length, fd, hdr.method)) { munmap(data, mmap_length); fprintf(stderr, "arcZIP: Failed to decompress\n"); return 0; } munmap(data, mmap_length); return 1; /* all OK */ } else lseek(extfd, hdr.csize, SEEK_CUR); } else lseek(extfd, hdr.csize+hdr.flen+hdr.xlen, SEEK_CUR); } else lseek(extfd, hdr.csize+hdr.flen+hdr.xlen, SEEK_CUR); } fprintf(stderr, "arcZIP: File not found in arc\n"); break; /* const char *temp; fprintf(stderr, "adbZIPCall::adbCallGet(apath=%s, fullname=%s file=%s dpath=%s\n", apath, fullname, file, dpath); temp = cfGetProfileString("arcZIP", "get", "pkunzip %a %d %n"); return !adbCallArc(temp, apath, file, dpath);*/ } #if 0 case adbCallPut: return !adbCallArc(cfGetProfileString("arcZIP", "moveto", "pkzip %a %n"), apath, file, dpath); case adbCallDelete: if (adbCallArc(cfGetProfileString("arcZIP", "delete", "pkzip -d %a %n"), apath, file, dpath)) return 0; if (cfGetProfileBool("arcZIP", "deleteempty", 0, 0)) { struct stat st; if (stat(apath, &st)) return 1; if (st.st_size==22) unlink(apath); } return 1; case adbCallMoveFrom: if (cfGetProfileString("arcZIP", "movefrom", 0)) return !adbCallArc(cfGetProfileString("arcZIP", "movefrom", ""), apath, file, dpath); if (!adbZIPCall(adbCallGet, apath, fullname, file, dpath)) return 0; return adbZIPCall(adbCallDelete, apath, fullname, file, dpath); case adbCallMoveTo: if (cfGetProfileString("arcZIP", "moveto", 0)) return !adbCallArc(cfGetProfileString("arcZIP", "moveto", "pkzip -m %a %n"), apath, file, dpath); if (!adbZIPCall(adbCallPut, apath, fullname, file, dpath)) return 0; unlink(file); return 1; #endif } return 0; } static struct adbregstruct adbZIPReg = {".ZIP", adbZIPScan, adbZIPCall ADBREGSTRUCT_TAIL}; static void __attribute__((constructor))init(void) { adbRegister(&adbZIPReg); } static void __attribute__((destructor))done(void) { adbUnregister(&adbZIPReg); } #ifndef SUPPORT_STATIC_PLUGINS char *dllinfo = ""; #endif DLLEXTINFO_PREFIX struct linkinfostruct dllextinfo = {"arczip", "OpenCP Archive Reader: .ZIP (c) 1994-09 Niklas Beisert", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/filesel/gendir.h0000644000175000001440000000043611655541726014474 0ustar stianusers#ifndef _GENDIR_HELPERS_H #define _GENDIR_HELPERS_H extern void gendir(const char *orgdir, const char *fixdir, char *targetdir); /* ALL dirs must be PATH_MAX+1 */ extern void genreldir(const char *orgdir, const char *fixdir, char *targetdir); /* ALL dirs must be PATH_MAX+1 */ #endif ocp-0.1.21/filesel/fstypes.c0000644000175000001440000000420611655541726014713 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Export _dllinfo for FSTYPES.DLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -kb980717 Tammo Hinrichs * -first release */ #include "config.h" #include "types.h" #include "boot/plinkman.h" #include "mdb.h" extern struct mdbreadinforegstruct #ifdef HAVE_MAD ampegpReadInfoReg, #endif itpReadInfoReg, oggReadInfoReg, gmdReadInfoReg, xmpReadInfoReg, gmiReadInfoReg, wavReadInfoReg; static void __attribute__((constructor))init(void) { #ifdef HAVE_MAD mdbRegisterReadInfo(&egpReadInfoReg); #endif mdbRegisterReadInfo(&itpReadInfoReg); mdbRegisterReadInfo(&oggReadInfoReg); mdbRegisterReadInfo(&gmdReadInfoReg); mdbRegisterReadInfo(&xmpReadInfoReg); mdbRegisterReadInfo(&gmiReadInfoReg); mdbRegisterReadInfo(&wavReadInfoReg); } static void __attribute__((destructor))done(void) { #ifdef HAVE_MAD mdbUnregisterReadInfo(&egpReadInfoReg); #endif mdbUnregisterReadInfo(&itpReadInfoReg); mdbUnregisterReadInfo(&oggReadInfoReg); mdbUnregisterReadInfo(&gmdReadInfoReg); mdbUnregisterReadInfo(&xmpReadInfoReg); mdbUnregisterReadInfo(&gmiReadInfoReg); mdbUnregisterReadInfo(&wavReadInfoReg); } #ifndef SUPPORT_STATIC_PLUGINS char *dllinfo = ""; #endif DLLEXTINFO_PREFIX struct linkinfostruct dllextinfo = {"fstypes", "OpenCP Module Detection (c) 1994-09 Niklas Beisert, Tammo Hinrichs", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/filesel/pfsmain.c0000644000175000001440000003271011655541726014654 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Main routine, calls fileselector and interface code * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb980510 Niklas Beisert * -first release * -kb980717 Tammo Hinrichs * -complete restructuring of fsMain_ etc. to enable non-playable * file types which are handled differently * -therefore, added "handler" line in CP.INI filetype entries * -added routines to read out PLS and M3U play lists * -as always, added dllinfo record ;) * -fd981014 Felix Domke * -small bugfix (tf was closed, even if it was NULL) * -ss040918 Stian Skjelstad * -minor tweak.. Do not touch any screen functions after conRestore and * before conSave */ #define NO_PFILESEL_IMPORT #include "config.h" #include #include #include #include "types.h" #include "stuff/err.h" #include "mdb.h" #include "pfilesel.h" #include "boot/plinkman.h" #include "boot/pmain.h" #include "stuff/poutput.h" #include "boot/psetting.h" extern struct mdbreaddirregstruct adbReadDirReg, dosReadDirReg, fsReadDirReg, plsReadDirReg, m3uReadDirReg; extern struct mdbreadinforegstruct fsReadInfoReg; static struct interfacestruct *plintr = 0; static struct interfacestruct *nextintr = 0; static FILE *thisf=NULL; static FILE *nextf=NULL; static struct moduleinfostruct nextinfo; static struct moduleinfostruct plModuleInfo; static char thispath[PATH_MAX+1]; static char nextpath[PATH_MAX+1]; typedef enum { DoNotForceCallFS = 0, DoForceCallFS = 1 } enumForceCallFS; typedef enum { DoNotAutoCallFS = 0, DoAutoCallFS = 1 } enumAutoCallFS; typedef enum { DoNotForceNext=0, DoForceNext=1, DoForcePrev=2 } enumForceNext; static enumAutoCallFS callfs; static char firstfile; static interfaceReturnEnum stop; /* stop: 0 cont * 1 next song * 6 prev song * 2 quit * 3 iface : next song or fs * 4 iface : call fs * 5 iface : dosshell */ /* return values: * 0 - no files available (and user hit esc) * 1 - we have a new song availble * -1 - error occured */ int callselector (char *path, struct moduleinfostruct *info, FILE **fi, enumAutoCallFS callfs, enumForceCallFS forcecall, enumForceNext forcenext, struct interfacestruct **iface) { int ret; int result; char tpath[PATH_MAX+1]; struct interfacestruct *intr; struct filehandlerstruct *hdlr; struct moduleinfostruct tmodinfo; char secname[20]; FILE *tf=NULL; *iface=0; *fi=0; do { ret=result=0; if ((callfs && !fsFilesLeft())||forcecall) ret=result=fsFileSelect(); if (!fsFilesLeft()) return 0; while (ret || forcenext) { conRestore(); if (!fsFilesLeft()) { conSave(); break; } if (forcenext==2) { if (!fsGetPrevFile(tpath, &tmodinfo, &tf)) { if (tf) { fclose(tf); tf=NULL; } conSave(); continue; } } else { if (!fsGetNextFile(tpath, &tmodinfo, &tf)) { if (tf) { fclose(tf); tf=NULL; } conSave(); continue; } } sprintf(secname, "filetype %d", tmodinfo.modtype&0xFF); intr=plFindInterface(cfGetProfileString(secname, "interface", "")); hdlr=(struct filehandlerstruct *)_lnkGetSymbol(cfGetProfileString(secname, "handler", "")); if (hdlr) { hdlr->Process(tpath, &tmodinfo, &tf); } conSave(); { unsigned int i; for (i=0;iClose(); plintr=0; /* _heapshrink(); */ } if (thisf) { fclose(thisf); thisf=NULL; } strcpy(thispath,nextpath); thisf=nextf; nextf=NULL; plModuleInfo=nextinfo; plintr=nextintr; nextintr=0; stop=interfaceReturnContinue; for (prep=plPreprocess; prep; prep=prep->next) prep->Preprocess(thispath, &plModuleInfo, &thisf); if (!plintr->Init(thispath, &plModuleInfo, &thisf)) { stop = interfaceReturnCallFs; /* file failed, exit to filebrowser, if we don't do this, we can end up with a freeze if we only have this invalid file in the playlist, optional we could remove the file... */ plintr=0; } else { /* char wt[256]; char realname[13]; memset(wt,0,256); fsConv12FileName(realname,plModuleInfo.name); strncpy(wt,realname,12); strcat(wt," - "); strncat(wt,plModuleInfo.modname,32); #ifdef DOS32 setwintitle(wt); #endif */ } conSave(); } if (plintr) { /* while (ekbhit()) egetch();*/ while (!stop) /* != interfaceReturnContinue */ { stop=plintr->Run(); switch (stop) { case interfaceReturnContinue: /* 0 */ case interfaceReturnQuit: break; case interfaceReturnNextAuto: /* next playlist file (auto) */ if (callselector(nextpath,&nextinfo,&nextf, DoAutoCallFS, DoNotForceCallFS, DoNotForceNext, &nextintr)==0) { if (fsFilesLeft()) { callselector(nextpath, &nextinfo,&nextf, DoNotAutoCallFS, DoNotForceCallFS, DoForceNext, &nextintr); stop = interfaceReturnNextAuto; } else stop = interfaceReturnQuit; } else stop = interfaceReturnNextAuto; break; case interfaceReturnPrevManuel: /* prev playlist file (man) */ if (fsFilesLeft()) stop=callselector(nextpath,&nextinfo,&nextf, DoNotAutoCallFS, DoNotForceCallFS, DoForcePrev, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue; else stop=callselector(nextpath,&nextinfo,&nextf, DoAutoCallFS, DoNotForceCallFS, DoNotForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue; break; case interfaceReturnNextManuel: /* next playlist file (man) */ if (fsFilesLeft()) stop=callselector(nextpath,&nextinfo,&nextf, DoNotAutoCallFS, DoNotForceCallFS, DoForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue; else stop=callselector(nextpath,&nextinfo,&nextf, DoAutoCallFS, DoNotForceCallFS, DoNotForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue; break; case interfaceReturnCallFs: /* call fs */ stop=callselector(nextpath,&nextinfo,&nextf, DoAutoCallFS, DoForceCallFS, DoNotForceNext, &nextintr)?interfaceReturnNextAuto:interfaceReturnContinue; break; case interfaceReturnDosShell: /* dos shell */ plSetTextMode(fsScrType); if (conRestore()) break; stop=interfaceReturnContinue; plDosShell(); conSave(); /* while (ekbhit()) egetch();*/ break; } } firstfile=0; } } plSetTextMode(fsScrType); conRestore(); if (plintr) plintr->Close(); if (thisf) { fclose(thisf); thisf=NULL; } return errOk; } static int fspreint(void) { mdbRegisterReadDir(&adbReadDirReg); mdbRegisterReadDir(&dosReadDirReg); mdbRegisterReadDir(&fsReadDirReg); mdbRegisterReadDir(&plsReadDirReg); mdbRegisterReadDir(&m3uReadDirReg); mdbRegisterReadInfo(&fsReadInfoReg); fprintf(stderr, "initializing fileselector...\n"); if (!fsPreInit()) { fprintf(stderr, "fileselector pre-init failed!\n"); return errGen; } return errOk; } static int fsint(void) { if (!fsInit()) { fprintf(stderr, "fileselector init failed!\n"); return errGen; } return errOk; } static void fsclose() { mdbUnregisterReadDir(&adbReadDirReg); mdbUnregisterReadDir(&dosReadDirReg); mdbUnregisterReadDir(&fsReadDirReg); mdbUnregisterReadDir(&plsReadDirReg); mdbUnregisterReadDir(&m3uReadDirReg); mdbUnregisterReadInfo(&fsReadInfoReg); fsClose(); } #if 0 void addtoplaylist(const char *source,const char *homepath, char *dest) { char finalpath[_MAX_PATH]; char longpath[_MAX_PATH]; if (strchr(source,'\\')) strcpy(longpath,source); else { strcpy(longpath,homepath); strcat(longpath,source); } strcpy(finalpath,longpath); #ifdef DOS32 callrmstruct r; char *mem; void __far16 *rmptr; __segment pmsel; mem=(char*)dosmalloc(1024, rmptr, pmsel); if (!mem) return; strcpy(mem, longpath); strcpy(mem+512, longpath); clearcallrm(r); r.w.ax=0x7160; r.b.cl=1; r.b.ch=0x80; r.w.si=(unsigned short)rmptr; r.w.di=((unsigned short)rmptr)+512; r.s.ds=((unsigned long)rmptr)>>16; r.s.es=((unsigned long)rmptr)>>16; r.s.flags|=1; intrrm(0x21,r); if (!(r.s.flags&1)) strcpy(finalpath, mem+512); else if (strchr(finalpath,' ')) *finalpath=0; dosfree(pmsel); #endif if (!memcmp(finalpath,"\\\\",2)) *finalpath=0; if (*finalpath) { strcat(dest,finalpath); strcat(dest," "); } } static char bdest[32768]; int addpls(const char *path, moduleinfostruct &info, binfile *&fil) { printf("adding %s to playlist ...\n", path); char dir[_MAX_DIR]; char pspec[_MAX_PATH]; _splitpath(path, pspec, dir, 0, 0); strcat(pspec,dir); *bdest=0; char *buffer = new char[fil->length()+128]; char *bufend = buffer+fil->length(); *bufend=0; fil->seek(0); fil->read(buffer,fil->length()); char *bufptr=buffer; char *lineptr[1000]; int linenum=0; while (bufptr=32) bufptr++; if (bufptr==bufend) break; *bufptr++=0; linenum++; } int snum=1, fnd; char lbuf[10]; strcpy(lbuf,"File"); if (linenum && !strcmp(lineptr[0],"[playlist]")) { do { ltoa(snum,lbuf+4,10); for (fnd=1; fndlength()+128]; char *bufend = buffer+fil->length(); *bufend=0; fil->seek(0); fil->read(buffer,fil->length()); char *bufptr=buffer; char *lineptr[1000]; int linenum=0; while (bufptr=32) bufptr++; if (bufptr==bufend) break; *bufptr++=0; if (strchr(lineptr[linenum],';')) *strchr(lineptr[linenum],';')=0; if (lineptr[linenum][0]) linenum++; } int fnd; for (fnd=0; fnd * * NoSound sampler device (samples perfect noise-free 16bit silence) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb980510 Niklas Beisert * -first release * -kb980717 Tammo Hinrichs * -added _dllinfo record */ #include "config.h" #include #include "types.h" #include "boot/plinkman.h" #include "dev/imsdev.h" #include "dev/sampler.h" #include "stuff/imsrtns.h" extern struct sounddevice smpNone; unsigned char *sampbuf; static void ndSetOptions(int rate, int opt) { if (rate<5000) rate=5000; if (rate>48000) rate=48000; smpRate=rate; smpOpt=opt; } static void ndSetSource(int src) { } static int getbufpos(void) { return 0; } static int ndStart(unsigned char **buf, int *len) { uint32_t initval; uint32_t dmalen; initval=(smpOpt&SMP_SIGNEDOUT)?0:0x80808080; if (smpOpt&SMP_16BIT) initval&=0xFF00FF00; dmalen=(*len)>>((!!(smpOpt&SMP_STEREO))+(!!(smpOpt&SMP_16BIT))); memsetd(*buf, initval, dmalen); smpGetBufPos=getbufpos; sampbuf=*buf=calloc(*len, 1); return 1; } static void ndStop(void) { free(sampbuf); } static int ndInit(const struct deviceinfo *c) { smpSetOptions=ndSetOptions; smpSample=ndStart; smpStop=ndStop; smpSetSource=ndSetSource; smpSetOptions(65535, SMP_STEREO|SMP_16BIT); smpSetSource(SMP_LINEIN); return 1; } static void ndClose(void) { smpSample=0; } static int ndDetect(struct deviceinfo *c) { c->devtype=&smpNone; c->port=-1; c->port2=-1; /* c->irq=-1; c->irq2=-1; c->dma=-1; c->dma2=-1; */ c->subtype=-1; c->mem=0; c->chan=2; return 1; } struct sounddevice smpNone={SS_SAMPLER, 0, "Eternal Silence Recorder", ndDetect, ndInit, ndClose, 0}; char *dllinfo="driver smpNone"; struct linkinfostruct dllextinfo = {"devsnone", "OpenCP Sampler Device: None (c) 1994-09 Niklas Beisert", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/devs/devsoss.c0000644000175000001440000002037111655541726014223 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Samples device for OSS input * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -ss040906 Stian Skjelstad * -first release */ #include "config.h" #include #include #ifdef HAVE_SYS_SOUNDCARD_H #include #endif #include #include #include #include #include #include #include #include "types.h" #include "boot/plinkman.h" #include "boot/psetting.h" #include "dev/devigen.h" #include "dev/imsdev.h" #include "dev/sampler.h" #include "stuff/imsrtns.h" #ifdef SMP_DEBUG #include "stuff/poutput.h" #endif #define REVSTEREO 1 extern struct sounddevice smpOSS; static struct deviceinfo currentcard; static int fd_dsp=-1, fd_mixer=-1; static unsigned char *sampbuf; static int buflen, bufpos; static int stereo; static int bit16; static int igain; static int getbufpos(void) { while (1) { int target, result; if (bufpos==buflen) bufpos=0; target=buflen-bufpos; result=read(fd_dsp, sampbuf+bufpos, target); if (result>0) bufpos+=result; if (result!=target) /* We don't care if we overrun buffer */ break; } return bufpos; } static void SetOptions(int rate, int opt) { int tmp; int newopt; int fd; if (fd_dsp<0) { if ((fd=open(currentcard.path, O_RDONLY|O_NONBLOCK))<0) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: open(%s, O_RDONLY|O_NONBLOCK): %s\n", currentcard.path, strerror(errno)); #endif smpRate=rate; /* damn it... device currently busy */ smpOpt=opt; return; } } else fd=fd_dsp; if (opt&SMP_16BIT) tmp=16; else tmp=8; if (ioctl(fd, SOUND_PCM_WRITE_BITS, &tmp)<0) { #ifdef OSS_DEBUG perror("devsoss: ioctl(fd_dsp, SOUND_PCM_WRITE_BITS, &tmp)"); #endif } if ((bit16=(tmp==16))) newopt = SMP_16BIT | SMP_SIGNEDOUT; else newopt = 0; if (opt&SMP_STEREO) tmp=2; else tmp=1; if (ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &tmp)<0) { #ifdef OSS_DEBUG perror("devsoss: ioctl(fd_dsp, SOUND_PCM_WRITE_CHANNELS, tmp)"); #endif } if ((stereo=(tmp==2))) newopt |= SMP_STEREO; if (ioctl(fd, SOUND_PCM_WRITE_RATE, &rate)<0) { #ifdef OSS_DEBUG perror("devposs: ioctl(fd_dsp, SOUND_PCM_WRITE_RATE, rate)"); #endif } if (currentcard.opt&REVSTEREO) newopt|=SMP_REVERSESTEREO; smpRate=rate; smpOpt=newopt; if (fd_dsp<0) /* nasty hack */ close(fd); } static void ossSetSource(int src) { int oss_src; if (fd_mixer<0) return; switch (src) { case SMP_MIC: oss_src=1<65536) *len=65536; if (*len<4096) *len=4096; *buf=sampbuf=malloc(*len); memsetd(*buf, (smpOpt&SMP_SIGNEDOUT)?0:(smpOpt&SMP_16BIT)?0x80008000:0x80808080, (*len)>>2); buflen=*len; bufpos=0; smpGetBufPos=getbufpos; if ((fd_dsp=open(currentcard.path, O_RDONLY|O_NONBLOCK))<0) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: open(%s, O_RDONLY|O_NONBLOCK): %s\n", currentcard.path, strerror(errno)); sleep(3); #endif return 0; } if (fcntl(fd_dsp, F_SETFD, FD_CLOEXEC)<0) perror("devsoss: fcntl(fd_dsp, F_SETFD, FD_CLOEXEC)"); #ifdef OSS_DEBUG #if defined(OSS_GETVERSION) if (ioctl(fd_dsp, OSS_GETVERSION, &tmp)<0) tmp=0; if (tmp<361) tmp= ((tmp&0xf00)<<8) | ((tmp&0xf0)<<4) | (tmp&0xf); fprintf(stderr, "devsoss: compiled agains OSS version %d.%d.%d, version %d.%d.%d detected\n", (SOUND_VERSION&0xff0000)>>16, (SOUND_VERSION&0xff00)>>8, SOUND_VERSION&0xff, (tmp&0xff0000)>>16, (tmp&0xff00)>>8, tmp&0xff); #elif defined(SOUND_VERSION) fprintf(stderr, "devsoss: compiled agains OSS version %d.%d.%d\n", (SOUND_VERSION&0xff0000)>>16, (SOUND_VERSION&0xff00)>>8, SOUND_VERSION&0xff); #endif #endif #ifdef SMP_DEBUG smpDebug=ossDebug; #endif smpSetOptions(smpRate, smpOpt); /* nasty hack */ if ((fd_mixer>=0)&&igain>=0) { int tmp; if (igain>100) igain=100; tmp=((uint8_t)igain)|(((uint8_t)igain)<<8); if (ioctl(fd_mixer, SOUND_MIXER_WRITE_IGAIN, &tmp)) { #ifdef OSS_DEBUG perror("devsoss: ioctl(fd_mixer, SOUND_MIXER_WRITE_IGAIN, &tmp)"); #endif } } return 1; } static void ossStop(void) { free(sampbuf); #ifdef SMP_DEBUG smpDebug=0; #endif if (fd_dsp) { close(fd_dsp); fd_dsp=-1; } } static int ossInit(const struct deviceinfo *card) { memcpy(¤tcard, card, sizeof(struct deviceinfo)); igain=(int8_t)(card->opt>>8); smpSetOptions=SetOptions; smpSample=ossSample; smpStop=ossStop; smpSetSource=ossSetSource; if (!card->mixer[0]) fd_mixer=-1; else if ((fd_mixer=open(card->mixer, O_RDWR|O_NONBLOCK))<0) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: open(%s, O_RDWR|O_NONBLOCK): %s\n", card->mixer, strerror(errno)); sleep(3); #endif } else { if (fcntl(fd_mixer, F_SETFD, FD_CLOEXEC)) perror("fcntl(fd_mixer, F_SETFD, FD_CLOEXEC)"); } smpSetOptions(44100, SMP_STEREO|SMP_16BIT); smpSetSource(SMP_LINEIN); return 1; } static void ossClose(void) { smpSample=0; smpStop=0; smpSetOptions=0; smpSetSource=0; if (fd_dsp>=0) close(fd_dsp); fd_dsp=-1; if (fd_mixer>=0) close(fd_mixer); fd_mixer=-1; } static int ossDetect(struct deviceinfo *card) { struct stat st; #if defined(OSS_GETVERSION) int tmp; #endif char *temp; card->devtype=&smpOSS; card->port=-1; card->port2=-1; card->subtype=-1; card->mem=0; if ((card->chan<=0)||(card->chan>2)) card->chan=2; if ((temp=getenv("DSP"))) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: $DSP found\n"); #endif strncpy(card->path, temp, DEVICE_NAME_MAX); card->path[DEVICE_NAME_MAX-1]=0; } else if (!card->path[0]) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: path not set, using /dev/dsp\n"); #endif strcpy(card->path, "/dev/dsp"); } if ((temp=getenv("MIXER"))) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: $MIXER found\n"); #endif strncpy(card->mixer, temp, DEVICE_NAME_MAX); card->mixer[DEVICE_NAME_MAX-1]=0; } if (stat(card->path, &st)) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: stat(%s, &st): %s\n", card->path, strerror(errno)); #endif return 0; } /* test if basic OSS functions exists */ if ((fd_dsp=open(card->path, O_RDONLY|O_NONBLOCK))<0) { if (errno==EAGAIN) { #ifdef OSS_DEBUG fprintf(stderr, "devsoss: OSS detected (EGAIN)\n"); #endif return 1; } #ifdef OSS_DEBUG fprintf(stderr, "devsoss: open(%s, O_RDONLY|O_NONBLOCK): %s\n", card->path, strerror(errno)); #endif return 0; } #if defined(OSS_GETVERSION) if (ioctl(fd_dsp, OSS_GETVERSION, &tmp)<0) { #ifdef OSS_DEBUG perror("devposs: (warning) ioctl(fd_dsp, OSS_GETVERSION, &tmp)"); #endif } #endif #ifdef OSS_DEBUG fprintf(stderr, "devposs: OSS detected\n"); #endif close(fd_dsp); fd_dsp=-1; return 1; /* device exists, so we are happy.. can do better tests later */ } static uint32_t ossGetOpt(const char *sec) { uint32_t opt=0; int8_t igain; if (cfGetProfileBool(sec, "revstereo", 0, 0)) opt|=REVSTEREO; igain=cfGetProfileInt(sec, "igain", -1, 10); opt|=(((uint16_t)igain)<<8); return opt; } struct devaddstruct smpOSSAdd = {ossGetOpt, 0, 0, 0}; struct sounddevice smpOSS={SS_SAMPLER, 0, "OSS Recorder", ossDetect, ossInit, ossClose, &smpOSSAdd}; char *dllinfo="driver smpOSS"; struct linkinfostruct dllextinfo = {"devsoss", "OpenCP Sampler Device: OSS (c) 2004-09 Stian Skjelstad", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/devs/Makefile0000644000175000001440000000177511655541726014040 0ustar stianusersTOPDIR=../ include $(TOPDIR)Rules.make ifeq ($(HAVE_OSS),1) OSS_SO=devsoss$(LIB_SUFFIX) endif all: devsnone$(LIB_SUFFIX) $(OSS_SO) devsnone_so=devsnone.o devsnone$(LIB_SUFFIX): $(devsnone_so) $(CC) $(SHARED_FLAGS) -o $@ $^ devsoss_so=devsoss.o devsoss$(LIB_SUFFIX): $(devsoss_so) $(CC) $(SHARED_FLAGS) $(OSS_LIBS) -o $@ $^ clean: rm -f *.o *$(LIB_SUFFIX) install: $(CP) devsnone$(LIB_SUFFIX) "$(DESTDIR)$(LIBDIR)" ifeq ($(HAVE_OSS),1) $(CP) $(OSS_SO) "$(DESTDIR)$(LIBDIR)" endif uninstall: rm -f "$(DESTDIR)$(LIBDIR)/devsnone$(LIB_SUFFIX)" ifeq ($(HAVE_OSS),1) rm -f "$(DESTDIR)$(LIBDIR)/$(OSS_SO)" endif devsnone.o: devsnone.c \ ../config.h \ ../types.h \ ../boot/plinkman.h \ ../dev/imsdev.h \ ../dev/sampler.h \ ../stuff/imsrtns.h $(CC) devsnone.c -o $@ -c devsoss.o: devsoss.c \ ../config.h \ ../types.h \ ../boot/plinkman.h \ ../boot/psetting.h \ ../dev/devigen.h \ ../dev/imsdev.h \ ../dev/sampler.h \ ../stuff/imsrtns.h \ ../stuff/poutput.h $(CC) $(OSS_CFLAGS) devsoss.c -o $@ -c ocp-0.1.21/README.Darwin0000644000175000001440000000120111655541726013522 0ustar stianusersIf you use liboss, you might need to edit /opt/local/lib/pkgconfig/liboss.pc and remove -Wno-precomp (liboss 0.0.1 is known to be broken and crashes, so I discourage the use of liboss) To configure Darwin, my experience is that you need to run configure like this: PATH=$PATH:/opt/local/bin LDFLAGS=-L/opt/local/lib CFLAGS=-I/opt/local/include CXXFLAGS=-I/opt/local/include CPPFLAGS=-I/opt/local/include CPPCXXFLAGS=-I/opt/local/include ./configure and optionally add things like --prefix etc. To get curses up and running with colors, you need to run ocp like this TERM=xterm-color ocp or export TERM=xterm-color before you run ocp ocp-0.1.21/config.sub0000755000175000001440000010242511655541726013414 0ustar stianusers#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 # Free Software Foundation, Inc. timestamp='2009-06-11' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tile*) basic_machine=tile-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: ocp-0.1.21/Changelog0000644000175000001440000010266711655541726013253 0ustar stianusers* Changelog was created 31. Aug 2004. About time perhaps 2004-08-31: filesel/modlist.c: updated fs12name to use rindex, and removed bug using strncpy instead of strcat 2004-08-31: boot/plinkman.c: updated lnkDoLoad do work if LD_DEBUG is not defined (STUPID BUG), and made dll-load only available via cfProgramDir. Needed if ran as setuid. 2004-08-31: boot/kickload.c: on crash, loose setuid permissions before we kick off gdb and other cool stuff 2004-08-31: filesel/*: removed all modlist->pathtothis stuff, and renamed dmPath to curdirpath since original ocp used that 2004-08-31: filesel/pfilesel.c: updated bugs in fsEditPath, when doing strlen() on uinitilized data, path-buffer-overrun and that enter is named _KEY_ENTER. Still behaves a bit not userfriendly until we make the filemask stuff 2004-08-31: config.h: removed FNAME_MAX and EXT_MAX, since they should be local to each plugin. 2004-09-01: Makefile: added DESTDIR 2004-09-01: ocp.spec: Created a redhat build spec file 2004-09-02: poutput-cursor (and some other): added support for setcur* and plDosShell 2004-09-06: boot/kickload.c Renamed ".ocp" to ".ocp-" VERSION 2004-09-06: Makefile: Remove backup files 2004-09-06: boot/plinkman,c: better error message if no dllextinfo is found and LD_DEBUG is on 2004-09-06: *: fix non-local characters in sources. 2004-09-06: dev/Makefile: don't run the tests 2004-09-06: devp/devposs.c: release /dev/dsp when it is not in use 2004-09-06: devs/devsoss.c: First release.. Welcome buddy 2004-09-06: dev/sampler.c dev/player.c devs/devsnone.c: Drivers allocate their own memory, since they might do funny things like mmap() 2004-09-06: dev/devisamp.c dev/deviplay.c dev/deviwave.c: Forgot to flag to modlist that we are a file, so no device info was shown in filelist 2004-09-07: stuff/timer.c: use gettimeofday() to calculate cpu-usage. 2004-09-07: VERSION 0.0.9 2004-09-08: __asm__ : updated all statemens to correctly identify registers, and dirty registers. But still miss to tag incomming registers as dirty. 2004-09-08: playit/itplay.c: copy 5 bytes instead of sizeof(c->delayed) in playtick(). We don't want to touch unmapped memory 2004-09-10: playmp2:* initial version.. based on playwav and playmp and links against libmad 2004-09-11: playogg: initial version.. based on playwav and playmp and links agains ogg vorbis 2004-09-11: configure configure.ac config.h.in Rules.make.in: autoconf has been introduced 2004-09-11: Makefile */Makefile */*/Makefile: autoconf 2004-09-11: help/cphelper.c: Stupid misstake prevented cp.hlp to be loaded from cp.pak 2004-09-13: binfile/binfpak.c: added a missing fseek 2004-09-13: goodies/pack/pack.c: Removed a bogus fwrite 2004-09-11: VERSION 0.1.0 2004-09-13: configure.ac: Check that gcc is version 3 or higher 2004-09-14: boot/kickload.c: use execvp on "gdb" aswell and honor $PATH 2004-09-14: filesel/pfilesel.c filesel/adb.c: Make sure the *ReadHandle() does not survive a fork 2004-09-14: play*/*pplay.c*: Make sure 128 is the big-screen value, and not 132 in *GDrawStrings() 2004-09-16: playogg/oggplay.c: fixed problem regarding random-sound in the first buffer-run and a signess problem around the PANPROC function 2004-09-16: rules.make Makefile configure.ac */Makefile: Don't use ld, but gcc/g++ instead, else the shared libraries wont be linked to libc, stdlibc+ etc when compiler without optimization. Wierd that it worked with optimization though. 2004-09-16: cpiface/cpiphase.c: gcc 3.3.3 has an optimizebug when using -O2 or higher. NASTY 2004-09-17: VERSION 0.1.1 2004-09-17: playogg/oggplay.c: Fixed the problem in bitrate reporting 2004-09-17: filesel/fsmain.c: Fixed problem with dos-shell not setting the screen-mode 2004-09-18: filesel/fsmain.c filesel/pfilesel.c stuff/poutput-curses.c: tweakings and fixing regarding outputting and restoring of the screen 2004-09-18: cpiface/cpitrack.c: Fixed a bug when scrolling channels, when they are zoomed wider than the screen 2004-09-18: play*/*pplay.c*: GStrings(): clear the part of the buffer we want to be blank at the right 2004-09-18: filesel/pfilesel.c filesel/adb.c: dump out "Scanning archive" message to the console 2004-09-18: stuff/poutput-vcsa.c: Implemented conSave/conRestore 2004-09-18: stuff/poutput-fb.c: devfs/linux kernel 2.6 support in device filename 2004-09-20: stuff/poutput-dga.c: DGA in XFree86 atleast leaves a descriptor open to /dev/mem across exec-calls, so we manually flag it to be closed 2004-09-20: filesel/cdrom.c: Duplicate filedescriptor, so we can try to avoid the kernel re-reading the toc when we access the cdrom from the fileselector while in use 2004-09-20: config.h autoconfig.ac */*.c*: DLLVERSION tagging 2004-09-20: VERSION 0.1.2 2004-09-26: boot/kickload.c: Get out of graphicmode on signals. 2004-10-04: playmp2/mpplay.c: Close file on exec 2005-01-18: configure.ac */Makefile.in and some few other c files: merged in some BSD related defines 2005-01-18: boot/kickload.c: jump out of graphical-mode on crashes 2005-01-18: playmp2/mpplay.c: close file on exec 2005-01-18: stuff/framelock.*: first implementation 2005-01-18: VERSION 0.1.3 2005-02-08: cpiface/mcpedit.c Added \ as key to split speed/pitch (ctrl-f12 in dos/win32 version) 2005-01-24: filesel/cphlpfs.c framelock the right way 2005-01-24: filesel/* make filemask work 2005-02-07: * */*.c: -fPIC support 2005-04-09: filesel/pfilesel.c: dynamic width in fileinfobox 2005-04-09: VERSION 0.1.4 2005-04-23: renamed ocplinux.ini(.in) to ocp.ini(.in) to reflect we now support BSD 2005-04-23: changed all comments/messages from linux to unix. 2005-04-23: keyboard updates 2005-04-23: detect gcc-versions better in ./configure 2005-04-23: make cdrom-support optional since current cdrom driver is linux-only. 2005-04-23: Removed support for config having other names like cp.ini etc in the kickloader 2005-04-23: Removed lots of out-commented code and watcom-assembler inlines. 2005-04-23: Moved some duplicated mixer-code from play*/ to a common dev/mixclip.c file. 2005-04-23: devw/dwnone_asminc.c no longer requires assembler inlines. 2005-04-23: Made filesel/modlist.c a little more intelligent in cpu-usage. 2005-04-23: Updated all copyrights to 2005 2005-04-23: Made support for various PAT config layouts for playgmi/* and cleaned up the code, so midi works for unix users 2005-04-23: Fixed keyboard handling in stuff/poutput-dga.c to support ALT keys. 2005-04-23: Added more escape-codes into stuff/poutput-keyboard.c 2005-04-23: VERSION 0.1.5 2005-05-01: Cleaned up Makefile.in install routines to consider --prefix from configure 2005-05-01: medialib/* implemented 2005-05-01: --with-dir-suffix added to ./configure to make BSD users happy (drop version from path-names) 2005-05-01: Made X11 fullscreen driver, and implemented wurfel-mode again 2005-05-01: Let kickload close X11 on crash 2005-05-01: keyboard updates 2005-05-01: detect if ncurses can resize (old versions of ncurses can't) in configure 2005-05-01: detect if libc has memmem in configure 2005-05-01: ALT-C from player added 2005-05-01: background support (needed palette flushing) 2005-05-01: Crash-bug in devw/dwmixfa.c fixed 2005-05-01: Remove debuging in filesel/mdb.c that was VERY slow 2005-05-01: Make some graphic-routines in stuff/poutput*.c 2005-05-01: VERSION 0.1.6 2005-05-04: freedesk.org icon/menu-entry 2005-05-04: don't crash in kickload if player fails to init. 2005-05-04: Let .ocp in $HOME not use version. Tag ocp.ini instead with a variable 2005-05-04: Redid loading-order of modules in ocp.ini 2005-05-04: Keyboard updates 2005-05-04: --with-debug in configure makes ocp drop optimizations, drop usage of SIGALRM, and enables kickloading of gdb 2005-05-04: Fix wurfel and picture loading (make it more userfriendly) 2005-05-04: Update freedesktop.org files. 2005-05-04: Documentation converted into texinfo 2005-05-04: Let fileselector and player use same screen-resolution 2005-05-04: Make private variables static in help/cphelper.c medialib/medialib.c 2005-05-04: playgmi/*: freepats and timidity should somewhat work (note= and other parameters aren't interprated yet) 2005-05-04: VERSION 0.1.7 2005-05-09: Make cpi-anal sample enough data for it's output to avoid random-noise 2005-05-10: Makefile.in update to respect ./configure paths 2005-05-10: Removed lrmi 2005-05-10: Removed not-used code-paths in console-driver 2005-05-10: Updated freedesktop.org files 2005-05-10: Compile-issue with dev/mixasm.c and -fPIC solved 2005-05-10: Let console-drivers take-over keyboard interface completley when they are used 2005-05-10: X11 and DGA tries to respect rootwindow changes more. 2005-05-10: Handle curses/vcsa key-throttles better 2005-05-13: configure.ac set LIBDIR very wrong when using --libdir= or --with-dir-suffix= 2005-05-13: filesel/pfilesel.c parse ocp.ini before adding drives, init rootfs etc 2005-05-18: filesel/adb.c filesel/mdb.c medialib/medialib.c: More verbose init to tell user what ocp does 2005-05-28: filesel/pfilsel.c: RD_PUTDSUBS, recursive directory adding 2005-05-31: filesel/*: bufferchecks in arctar, and made adb take 127 chars names instead of 63 2005-05-31: filesel/pfilesel.c: Changing directory, places to marker at the directory you came from 2005-06-01: playmp2/*: Scan file-length, since VBR files are ... vbr in time 2005-06-01: playopl/* adplug support (beta) 2005-06-01: VERSION 0.1.8 2005-05-05: Don't crash loading modules after playopl has been used 2005-06-07: Don't crash when using curses and x11 is present 2005-06-08: Some gcc 4.x fixes and a adplug get-extention buffer-overflow 2005-06-08: filesel/cdrom.c: strncpy instead strncmp doesn't really work as expected 2005-06-09: VERSION 0.1.9 2005-07-11: Make sure all x11_init() are inside HAVE_X11 defines 2005-12-02: Aylet support 2005-12-02: Don't crash after ALT-C if in graphical mode 2005-12-02: X11 crash-fix 2005-12-02: Various crash-fixes 2005-12-02: Putting myself as author (of this fork) 2005-12-02: VERSION 0.1.10-rc1 2005-12-06: -ldl must be checked without altered CFLAGS, since some libs might link -ldl 2005-12-06: VERSION 0.1.10-rc2 2005-12-06: configure.ac: -ldl fix 2005-12-18: alsa initial support 2005-12-18: VERSION 0.1.10-rc3 2005-12-18: Make it possible to browse files by long filenames 2005-12-18: ALSA Buffer underruns are now handled 2005-12-18: VERSION 0.1.10-rc4 2005-12-29: cdrom updates 2005-12-31: Read .m3u and .pls files 2005-12-31: Write .pls files 2005-12-18: VERSION 0.1.10-rc5 2006-01-01: Better handling of paths in kickload 2006-04-28: Improve the ocp.ini parser, and some minor updates from cp.ini=>ocp.ini 2006-04-28: cfStoreConfig, can be called from ALT_C dialog 2006-04-28: dev/devi*.c: Handle failure of the first init call (check if *curdev is valid) 2006-04-28: devp/devpalsa.c: Don't crash if alsa is not available 2006-05-18: filesel/pfilesel.c: Add a filetype editor and color-editor 2006-05-20: playgmd/gmdptype.c: Send adlib s3mfiles to adplug, and length check all buffers 2006-06-20: filesel/fstypes.c: Handle headerless pls and m3u files 2006-07-23: *: Changed some paths in the configure/build system, so some files might have moved around 2006-08-02: Thanks to Luigi Auriemma for reporting some overflow issues. Fixed a bunch of overflows like this. 2006-08-02: Some trackers sets unused samples to strange values, and OCP sent them to adlib, when they shouldn't have been 2006-08-02: VERSION 0.1.10-rc6 2006-08-08: filesel/pfilesel.c: Removed a memory-leak 2006-08-08: playmp2/mpptype.c: Removed a buffer overrun (buffer was from heap) 2006-08-08: filesel/gendir.c: Use a tempbuffer, to avoid strcpy with same source and dest. Valgrind complained on those 2006-08-25: */type*: make opltype work in detection 2006-08-25: filesel/arczip.c zip file support (read-only and deflate only) 2006-08-25: cpiface/cpitrack: Remove some small bugs/graphical issues 2006-10-29: *: Detect broken adplug installations (it doesn't have correct path for libbinio) 2006-10-30: *: Try to use pkg-config for adplug (version 2.x and above has this) 2006-10-30: *: Try to use pkg-config for id3tag and mad 2006-10-30: *: Try to use pkg-config for ogg, vorbis and vorbisfile 2006-11-01: devw/devwmixf.c: -fstrict-aliasing fix for gcc 4.x 2006-11-01: VERSION 0.1.10-rc7 2006-11-04: devw/devwmix.c: compiler barrier for the "thread" lock a sign error in volume, causing ticking sounds 2006-11-07: configure.ac: Detect broken signed char to signed int conversions (gcc 4.1.1. with -O or higher bug) 2006-11-08: VERSION 0.1.10-rc8 2006-11-14: boot/kickload.c: fix stderr for reset 2006-11-14: Various assembler->C updates 2006-11-16: devwmix and devwmixq without assembler now works 2006-11.18: Renamed cp.pak to ocp.pak Renamed cp.hlp to ocp.hlp 2006-11-25: Lots up endian updates (and some other minor updates along the same run) 2006-11-26: New logic in playlist: If scramble/random, you see no difference. If non-scramle, the the cursor tells the next song to play If non-scramle and no-remove, the cursor in playlist will step down as you play the list 2006-11-28: Always display filter to off on streams 2006-11-28: Fix noise when starting to play streams 2006-11-28: Allow to use modes that aren't supported in fullscreen when we are in a window. 2006-11-28: Fix recursive add files 2006-11-28: VERSION 0.1.10_rc9 2006-11-29: Fixed a crash in .xm loader that was introduced in 0.1.10_rc9 2006-11-29: Fixed a buffer-error in boot/psetting.c when saving settings 2006-11-30: It compiles on darwin. Don't know if it works as excepted though 2006-12-01: boot/psetting.c: Storing ocp.ini didn't flush/close itself, corrupting the ini file for next time you ran ocp 2006-12-01: filesel/pfilesel.c: Small memoryleak when exiting ocp fixed 2006-12-01: playmp2/mpplay.c: Memory leak fixed 2006-12-01: Added -p flag, that causes ocp to quit when playlist reaches empty (or when hitting f for filebrowser). 2006-12-01: devp/devwmixf.c: Don't implement minimum buffersize. Fixes the problem with devpdisk.dev hanging 2006-12-01: stuff/poutput.c: Endian introduced a signed error, causing character >=0x80 causing white cells 2006-12-03: stuff/poutput-curses.c stuff/poutput-x11.c config.h.in: Fixed ALT_S and disabled keys that are not used/defined 2006-12-03: filesel/pfilesel.c: Fixed file: to use RegisterDrive, and not to manipulate dmDrives. It messed up when cleaning up 2006-12-03: stuff/poutput-x11.c: Added some caching in the text routines 2006-12-08: devp/devpalsa.c: Try to set the bufferspace to 0.5 secs 2006-12-08: Add big_endian fixes (don't use htons/htonl) 2006-12-12: VERSION 0.1.10 2006-12-12: boot/kickload.c: Don't try to dump regs on non-x86 arcs running linux 2006-12-13: cpiface/cpiface.c: Display height above 99 with 3 digits 2006-12-13: filesel/*: Started to implement the new directory database scheme 2006-12-14: filesel/*: Made the databases more endian aware, and alignment friendly 2006-12-14: playmp2/mpptype: fix dectection for systems that needs proper alignment 2006-12-14: We just confirmed that OCP runs on sparc (32bit) 2006-12-14: VERSION 0.1.11 2006-12-14: Updates for dirdb 2006-12-14: remove endian-mess in devposs 2006-12-14: Fix endian in x11 output 2006-12-14: Fixed xmlmod.c to handle endians better 2006-12-14: goodies/helpc/ocphhc.c: Make it endian-aware 2006-12-14: */*: Make volumebars endian aware 2006-12-14: help/*: endian updates 2006-12-14: VERSION 0.1.12 2006-12-18: playmp2/mpptype.c: detection of mp3files where broken 2006-12-18: */*: dirdb implementation and update, part 1 2006-12-18: configure.ac goodies/helpc/*: Make the help compiler work with efence/duma, and clean up memory when done 2006-12-18: playsid/sidplay.c: Use the proper delete[] statement 2006-12-18: poutput/x11-common.c: Close down xlib properly 2006-12-19: */*: dirdb implementation and update, part 2 2006-12-22: */*: Coreaudio initial code 2006-12-24: */*: Endian updates and CoreAudio update 2007-01-01: playay/ayplay.c: don't import libmad header files 2007-01-17: boot/kickload.c: just look for sigcontext on linux (should fix building for solaris) 2007-01-18: config.h playogg/*: Endian needs to be checked correctly 2007-01-18: Don't fetch functionpointers directory from libs, use structs instead (removes warnings from gcc / makes compiling for embedded systems more possible) 2007-01-21: dev/mixer.c: gcc/binutils optimizes away $0 offset in data-addreses. It caused mp3 and wav files to crash on some hosts 2007-01-27: dev/dwmixfa.c: handle extreem loops better (and make some more code PIC) 2007-02-04: cpiface/cpitrack.c: Increase intelligens of the renderer (to avoid crashes when viewing files with long patterns, and black lines on small ones) 2007-02-05: VERSION 0.1.13 2007-02-10: Removed outdated DGA support 2007-02-10: Removed the old plSetGraphPage code. Since it sometimes where used wrong, and that all the current graphic drivers are linear, and not paged. 2007-02-19: Updated the build system regarding "make install" and "make uninstall", and prepared the support for autoload a directory of plugins (so that we can start to strip down ocp.ini) 2007-03-02: Internal changes: Remove a lot of symbol lookups for init/close stuff 2007-05-27: Add support for .flac files 2007-06-20: Fix the support for compressed archieves again 2007-07-09: medialib: now somewhat works again 2007-07-13: cpiface: alt+k now displays some help about keys 2007-07-22: devw/*: Some crash-fixes regarding 64bit archs (uint32_t/int32_t index behaves differently on 32bit and 64bit systems) 2007-09-17: playmp2/mpptype.c playmp2/charset.*: id3 v2.x support (and some lame charset handling) 2007-09-18: ALT-K updates (support for graphical modes) 2007-09-18: make FLAC support optional, and add some stuff to ocp.ini.in that was lost regarding FLAC support 2007-10-13: Support FLAC the "new" 1.1.3 API 2007-10-15: Edit FPS from ALT-C setup window 2007-10-18: filesel/pfilesel.c: minor buffer-overflow by a byte in fsEditModType() 2007-10-19: playmp2/mpptype.c: id3 v2.3/v.2.4 parser updates 2007-10-19: */*: ALT+R in the fileselector for rescanning the selected file. 2007-10-21: VERSION 0.1.14 2007-10-27: cpiface/cpiscope.c: Draw the entire background picture if present 2007-10-27: playgmi/gmitimidity.c: Now it should work with configs that has several search-dirs 2007-11-11: playcda/*.c: Disk size is now correct (displayed on track to little), and removed a crash when you were done playing cd 2007-11-16: cpiface/cpigraph.c: palette updates for "palette2", replaceable with shift-tab (works in X11 atleast) 2007-11-16: cpiface/volctrl.c: Don't swallow key we didn't use it 2007-11-16: cpiface/cpitext.c: Don't send "focused" keyboard events to interfaces that no more is active 2007-11-16: playmp2/mpptype.c: Mac OS X needs sys/types.h 2007-11-16: configure.ac: detect libiconv if needed 2007-11-17: playxm/xmload.c: check if fread/fseek calls failes, and free memory properly when we abort to load 2007-11-17: filesel/arczip.c: removed an invalid unlink() that tried to remove a tempfile no longer used in the code 2007-11-17: filesel/arczip.c: Taking padding into account when calculating mmap length (crash bug) 2007-11-18: playxm/xmload.c: more sanity-checks and an error in the endian-fixups 2007-11-18: playxm/xmload.c: support .xm files with truncated headers (and files with maleformed headers) 2007-12-13: medialib/medialib.c: buffer overflow when reading string from user 2007-12-13: devp/devpalsa.c (and some others): support for "default" and custom device strings 2007-12-14: dev/smpman.c: boundarycheck loops properly 2007-12-15: playxm/xmplay.c: Playing a note without a valid instrument/sample could cause a null-pointer dereference/segfault 2007-12-15: stuff/console.c and others: -dx11 -dcurses -dvcsa flag, to force display driver to use 2008-01-04: stuff/poutput-x11.c cpiface/cpikeykelp.c: don't crash on wurfel-mode + ALT-K 2008-01-14: VERSION 0.1.15 2008-01-20: */*: Removed some overhead in `struct modlist` and fixed sorting logic when adding a directory to the playlist, and added recursivity to the logic when deleting a directory from the playlist aswell. 2008-01-29: */*: Removed the dependency on libid3tag (we only used one simple function from it) 2008-02-01: boot/plinkman.c: missing closedir() fixed 2008-02-02: playxm/xmlmxm.c: Added a length-check constraint, fixes crash when loading broken MXM files (however, they are played wrong then) 2008-02-20: */*: Added KEY_CTRL_PGUP, KEY_CTRL_PGDN, KEY_CTRL_UP and KEY_CTRL_DOWN (not reachable from curses driver) and relevant code 2008-03-20: filesel/pfilesel.c boot/psetting.c: Add support for @some.m3u support as stated on the help text. 2008-03-30: ctrl+j and alt+enter was mapped to the same key id. Also added two missing key names in the keyhelp (alt+k window) 2008-04-24: boot/* cpiface/cpikeyhelp.c stuff/*: Grey-out keys in the keyhelp that aren't available in the currently used consoledriver. 2008-06-24: desktop/opencubicplayer.desktop.in: Changed encoding to UTF-8, thanks to Adam Sampson 2008-06-24: devp/devpalsa: Various updates: "default" mixer device, bugfix for the ALSA PulseAudio plugin, thanks to Chuck Anderson 2008-06-24: *: Make MAD (mpeg) support optional, thanks to Chuck Anderson 2008-06-24: configure.ac: exec_prefix should now expand to prefix unless specicied with --exec-prefix= 2008-06-26: devw/dwmixa.c: Minor updates in the low-quality-mixer (both assembler and C versions) 2008-06-29: Makefile.in ocp.spec: move documentation stuff into prefix/doc/ocp-version instead of prefix/share/ocp-version, Chuck Anderson 2008-06-29: Makefile.in: relative symlink on ocp-suffix instead of absolute, thanks to Chuck Anderson 2008-06-29: doc/texi/Makefile doc/texi/ocp.texi.in: Add ocp to the global info directory, thanks to Chuck Anderson 2008-08-03: playxm/xmplay: Fixed a crash bug when playing certain files. 2008-11-06: */*: Various small array underflow/overflow warnings were fixed (non-fatal all of them) 2008-11-06: ocp.ini.in: renamed [x11]:framebuffer to [x11]:autodetect and added [x11]:font 2008-11-16: stuff/poutput-x11.c Redid resolution and fullscreen handling 2008-11-16: configure.ac install-sh config.sub config.guess: Enabled cross-compiling (and added needed files from automake 1.10) 2008-11-16: help/cphelper.c: KEY_UP was broken, and rendering errors on big-screens 2008-11-16: cpiface/cpimvol.c: One of the volumebars were insymetrical. 2008-11-17: *: use autoload feature in boot/plinkman.c; This makes it possible to have filesupport in different packages without regenerating ocp.ini 2008-11-21: config.h.in playmp2/mpptype.c: Added debug-info and fixed a minor parsing bug (could cause random data at end of strings) 2008-11-21: filesel/pfilsel.c: KEY_PPAGE/KEY_UP would cause wrap-around, now all UP/DOWN movements are boundary checked 2008-11-21: pfilesel/modlist.c: playing the last song on a playlist would cause strange behaviour and random crashes 2008-11-22: *: Add support for "previous" in playlist (see ALT-K for keys CTRL-J and CTRL-K). Keys make even more sense if you disable "remove from playlist" on ALT-C setup screen 2008-11-25: Added fnmatch from gnulib, so that OS-X can compile without patches, and behave the same (other issues remain on OS-X however). 2008-12-05: filesel/fsmain.c: increased the intelligence of esc-handling, fileselector interaction and broken files handling (several freeze conditions) 2008-12-30: stuff/poutput-x11.c configure.ac: Add icons on x11 window (Adds libXpm dependency) 2008-12-30: playxm/xmload.c: try to load even more module files correct 2008-12-30: playit/itload.c: don't fail to load .it files without instruments 2008-12-30: updated gnulib 2008-12-31: cpiface/cpikube.c: Fixed some segfaults 2008-12-31: VERSION 0.1.16 2009-01-02: playgmd/gmdlokt.c: endian-issue made the file fail to load on little-endian (x86) hosts. 2009-02-01: devp/devpcoreaudio.c: Re-arranged code a bit, made x11 support work-aswell (no idea why that bOrked before) 2009-02-08: remove autoload away from ocp.ini (no need to have it there, since it will change for each version of OCP. OCP should know this statically, based on where it found libocp.so 2009-02-08: boot/pmain.c: auto-update ocp.ini from earlier versions of ocp 2009-02-09: filesel/pfilesel.c: playlist now cover entire screen when selected. Pressing INSERT while in playlist now also works as expected 2009-02-11: binfile/*: removed support for ocp.pak. We only had one file left in it, and we don't bother if ocp spans of multiple files either any more (dlopen() is more easy to use when you don't use an archieve aswell) 2009-02-13: design change: remove interface= and preprocess= away from dllinfo, and let plugins call apropriate register/unregister instead. 2009-03-28: playopl/oplplay.cpp: big-endian hosts didn't play right. 2009-04-24: boot/plinkman* cpiface/cpilink.c: Added backend support for static plugins, however it is not used yet 2009-05-12: playgmi/gmiload.c: Fixed a small possible buffer overflow (readonly while parsing) that could lead to SEGFAULT on broken midi files. Also removed a optimization that were broken (only some gcc setups hit it in a wrong maner) 2009-06-04: doc/texi/Makefile: Don't fail if install-info isn't available 2009-06-04: dev/mix.c: typecast pointers via long int, and not just uint32_t when you want to do shifting on them (even though other arcs not using x86 assembler inlines doesn't use the variables, but we still want it beeing sane) 2009-06-04: dev/player.*: Fixed issues regarding x86_64 (segfaulting). Mixing 64bit unsigned and 32bit signed variables doing simple + math can lead to undefined behaviour. 2009-06-04: playflac/flacplay.c: wrong footprint on a callback (visible on 64bit hosts) 2009-06-04: playit/itload.c playxm/xmload.c: (debug) printf format string warnings on 64 hosts fixed 2009-06-15: boot/kickload.c playmp2/charset.c: getenv() pointers are safe to keep for long. Also added some more constraints (const, etc). 2009-06-27: VERSION 0.1.17 2009-06-29: devpcoreaudio didn't compile on darwin 2009-07-19: dev/smpman.c: x86_64 crashed when expanding loops 2009-07-20: configure.ac: missing AC_DEFINE, made compiling on ubuntu flash a lot of warnings due to we not knowing about some header files 2009-07-20: platit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Out-of-range_note_delays 2009-07-20: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Pattern_loop 2009-07-20: playit/itptrack.c: track-visualizer didn't show SBx commands (now appears like plx - pattern loop) 2009-07-20: *: use sysconf(_SC_PAGESIZE) if available, before trying to use PAGESIZE, and defaulting to 4096 2009-07-21: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Tremor_effect 2009-07-21: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Ping-pong_loop_and_sample_number 2009-07-22: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Retrigger 2009-07-22: stuff/*x11*: Borrowed some code from mplayer (don't attemt to use SHM on network connected X11 servers) 2009-07-23: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Pattern_row_delay 2009-07-23: stuff/poutput-x11.c: Added XSync() after resize-windows, else XGetImage sometimes fails, since local structure isn't ajour with server fast enough (window resize on remote X11 would sometime exit ocp with X11 error) 2009-07-23: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Random_waveform 2009-07-25: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Pan_swing_and_set_panning_effect 2009-07-26: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Zero_value_for_note_cut_and_note_delay 2009-07-26: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Portamento_with_no_note 2009-07-28: playit/itplay.c: http://eval.sovietrussia.org/wiki/Player_abuse_tests#Portamento_and_pitch_slide 2009-07-29: playgmi/*: Added buffer overrun protection to the MIDI file parser 2009-07-30: playit/itload.c: use Impulse Tracker 2.15 sample decompression, only when needed 2009-08-07: *: Remove the need for keep=1 on certain drivers. The drivers can tell themselfs if they need it. 2009-08-07: devp/devpcoreaudio.c: Major updates 2009-09-24: stuff/*: Added support for SDL video 2009-09-24: dev*/dev*oss.c: Only warn if GET_VERSION fails (some BSDs fails on this) 2009-09-24: ocp-*: Make even faster method for forcing SDL, etc video drivers 2009-09-25: Compiling SDL support without X11 gave a missing symbol 2009-11-18: configure.ac: AC_MSG_ERROR was used wrong some places 2009-12-25: *: medialib didn't handle archived files very well. This is now fixed, however, a rescan is needed in order to make them work (database didn't store archive data) 2009-12-26: playit/itload.c: Don't fail on loading samples with length set to zero, skip them instead 2009-12-26: VERSION 0.1.18 2010-01-03: devw/dwmixqa.c [DEVWMIXQ.DEV]: Both assembler and non-assembler version updates (crash bug-fixes) 2010-01-10: configure.ac, Makefile.in desktop/*: Use desktop-file-install, and remove the wmconfig stuff 2010-01-10: dev/mixasm.c: Random crash that affects all non-x86 platforms. 2010-01-10: ocp.spec: Major overhaul (partly tested on OpenSUSE only) 2010-01-19: stuff/putput-x11.c: support for 24bit resolution (qemu uses this in virtual machines) 2010-02-12: devw/devwmix.c: Non x86 platforms would randomly crash when using effects like "b" and "o" views 2010-02-12: stuff/poutput-x11.c stuff/poutput-sdl.c: Even better support for 24/32 bit resolutions 2010-02-12: ocp.spec: Relax SELinux on x86 (we use textrels), and give install-info the correct flags 2010-03-29: asm_emu/*: Added a x86-asm-emulator (used for debuging x86-assembler mixers) 2010-03-29: devw/*: Non-x86 now plays long samples correct (thanks to Chuck Anderson for bugreport) 2010-03-31: playgmd/gmdlptm.c: One block of data-load wasn't endian-safe 2010-04-01: playxm/*.c: Accept .XM files with bogus header (no 0x1a mark at offset 37) 2010-04-01: playopl/oplplay.cpp: Disable endian swap for data that comes from adplug 2010-04-15: devp/devpalsa.c: Try to compensate for pulseaudio returning a delay of zero samples 2010-04-16: Removed gnulib (it violated the GPLv2+ license OCP is released under) 2010-04-19: playay/sound.c: Update to aylet 5.0 2010-04-19: *: Specify GPLv2+ on all source files 2010-05-19: playay/ayplay.c: pause made noise 2010-05-11: playopl/oplplay.c: Minor error could cause noise on high cpu-load 2010-05-11: playym/*: First release of YM file support (Based on STYMulator) 2010-05-12: filesel/arczip.c: Compression method 0 didn't work as expected 2010-05-12: filesel/*: Split fileselector init into two separate parts. Starting ocp in a directory with uncached archieves caused a segfault due to usage of uninitalized modules. 2010-05-12: cpiface/cpichan.c: Full-width view with width of 81..127 where drawn in 128 wide mode, causing non-visible-output. 2010-05-14: playmp2/mppplay.c: RIFF contained files were unable to play (usually only used on MP2 files) 2010-05-15: VERSION 0.1.19 2010-05-16: Make it possible to disable 'desktop-file-install' (Fink needs this) 2010-05-17: configure.ac: removed a syntax error 2010-05-18: ocp.ini boot/pmain.c: ocp.ini shipped with version 0.1.19 wasn't correct 2010-05-18: VERSION 0.1.20 2010-05-18: playgmd/gmdldmf.c: Remove a nested function 2011-03-19: compat/stuff.*: strupr is actually implemented on some systems 2011-03-19: configure.ac */*: -lm is not required on all platforms 2011-03-19: * */*: AC_STRUCT_DIRENT_D_TYPE; not all platforms has dirent.d_type 2011-03-19: config.guess, config.sub, install-sh: update to more recent versions (used the ones present in automake-1.11 in ubuntu 10.10) 2011-03-19: configure.ac Makefile.in: Only link to pthread if on OS-X / CoreAudio 2011-03-19: Support getcwd() for retrieving current working directory 2011-03-20: Added support for SDL audio 2011-03-20: cpiface/cpilinks.c: crash-bug when resizing window while link viewer was active 2011-03-20: devpcoreaudio devpsdl: gettimer() didn't work as expected (needed by cpitrack.c) 2011-06-01: play*/*: Some of the players didn't have volatile on the "timer" lock 2011-06-08: playwav/wavplay.c: Race condition that caused some audio artifacts (some parts could be replayed randomly) 2011-06-19: playmp2/charset.c: Detection of glibc bug 4936 alrways returned true (thanks to Jindrich Makovicka) 2011-07-11: devw/dwmixfa*: 8087 fpu version is now able to compile in PIC mode without use of text-rels. 2011-07-13: devw/dwmixfa: Added support for proper C verion of the FPU mixer (Thanks to JindÅ™ich MakoviÄka) 2011-07-13: devw/dwmixfa: 8087_asm_emu code made some annoying clicking sounds 2011-09-05: configure.ac: AC_LINK_IFELSE for ADPLUG could fail if "ld --as-needed" was used 2011-09-18: devp/devpalsa: newer versions of libalsa does not need plughw syntax, and in some cases works better without 2011-09-18: configure.ac: removed a warning visible when using autoconf >= 2.68 2011-09-30: devp/devpcoreaudio.c: Didn't compile 2011-10-21: playgmd/gmdl*.c: Removed a nested function (GCC on OS-X dislikes them) 2011-11-03: playgmi/gmitimitidy.c: Updated against ubuntu 11.10 configfile structure, closing ticket #3 2011-11-03: dev/mixclip.c: wav and sid files would crash on non-x86 platforms (optimization for assembler mixer in lookup-tables were fixed for 32bit pointers) 2011-11-04: playwav/wavpplay.c: pause on wave files caused crash. Also did some minor cleanups in pause-handling in other file-plugins aswell 2011-11-05: boot/psetting.c: ocp.ini upgrade code could crash due memmove moved too much memory 2011-11-06: VERSION 0.1.21 ocp-0.1.21/playcda/0000755000175000001440000000000011655541750013037 5ustar stianusersocp-0.1.21/playcda/cdapplay.c0000644000175000001440000002642511655541726015014 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Interface routines for Audio CD player * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb980510 Niklas Beisert * -first release * -ss040907 Stian Skjelstad * -removed cdReadDir * -Linux related changes */ #include "config.h" #include #include #include #include #include #include "types.h" #include "cdaudio.h" #include "boot/plinkman.h" #include "cpiface/cpiface.h" #include "dev/deviplay.h" #include "dev/devisamp.h" #include "filesel/pfilesel.h" #include "filesel/mdb.h" #include "stuff/compat.h" #include "stuff/poutput.h" #include "stuff/err.h" #include "stuff/sets.h" #include void _splitpath(const char *src, char *drive, char *path, char *file, char *ext); /* defined in stuff/compat.h but this header clashed with linux/cdrom.h */ static unsigned long cdpTrackStarts[CDROM_LEADOUT+1]; static unsigned char cdpFirstTrack; static unsigned char cdpPlayMode; /* 1 = disk, 0 = track */ static unsigned char cdpTrackNum; /* current track, calculated in GStrings */ static int cdpViewSectors; /* ??? view-option */ static FILE *cdpDrive; /* nasty */ static unsigned long basesec; /* current start... usually a cdpTrack[n] value */ static unsigned long length; /* and the length of it */ static signed long newpos; /* skip to */ static unsigned char setnewpos; /* and the fact we should skip */ static char vdev[8]; static int16_t speed; static char finespeed=8; static uint32_t pausefadestart; static uint8_t pausefaderelspeed; static int8_t pausefadedirect; static void startpausefade(void) { if (pausefadedirect) { if (pausefadedirect<0) plPause=1; pausefadestart=2*dos_clock()-DOS_CLK_TCK-pausefadestart; } else pausefadestart=dos_clock(); if (plPause) { plChanChanged=1; plPause=0; cdRestart(fileno(cdpDrive)); pausefadedirect=1; } else pausefadedirect=-1; } static void normalize(void) { mcpNormalize(0); speed=set.speed; cdSetSpeed(speed); } static void dopausefade(void) { int16_t i; if (pausefadedirect>0) { i=((int32_t)dos_clock()-pausefadestart)*64/DOS_CLK_TCK; if (i<0) i=0; if (i>=64) { i=64; pausefadedirect=0; } } else { i=64-((int32_t)dos_clock()-pausefadestart)*64/DOS_CLK_TCK; if (i>=64) i=64; if (i<=0) { i=0; pausefadedirect=0; plPause=1; cdPause(fileno(cdpDrive)); plChanChanged=1; cdSetSpeed(speed); return; } } pausefaderelspeed=i; cdSetSpeed(speed*i/64); } static char *gettimestr(unsigned long s, char *time) { unsigned char csec, sec, min; csec=(s%75)*4/3; time[8]=0; time[7]='0'+csec%10; time[6]='0'+csec/10; sec=(s/75)%60; time[5]=':'; time[4]='0'+sec%10; time[3]='0'+sec/10; min=s/(75*60); time[2]=':'; time[1]='0'+min%10; time[0]='0'+min/10; return time; } static void cdaDrawGStrings(uint16_t (*buf)[CONSOLE_MAX_X]) { int i; char timestr[9]; struct cdStat stat; cdGetStatus(fileno(cdpDrive), &stat); memset(buf[0]+80, 0, (plScrWidth-80)*sizeof(uint16_t)); memset(buf[1]+80, 0, (plScrWidth-80)*sizeof(uint16_t)); memset(buf[2]+80, 0, (plScrWidth-80)*sizeof(uint16_t)); writestring(buf[0], 0, 0x09, " mode: .......... ", 20); writestring(buf[0], 8, 0x0F, "cd-audio", 10); for (i=1; i<=cdpTrackNum; i++) if (stat.position', "Jump track forward"); cpiKeyHelp(KEY_CTRL_LEFT, "Jump track back"); cpiKeyHelp(KEY_CTRL_RIGHT, "Jump track forward"); cpiKeyHelp(KEY_F(9), "Pitch speed down"); cpiKeyHelp(KEY_F(11), "Pitch speed down"); cpiKeyHelp(KEY_F(10), "Pitch speed up"); cpiKeyHelp(KEY_F(12), "Pitch speed up"); if (plrProcessKey) plrProcessKey(key); return 0; case 'p': case 'P': startpausefade(); break; case KEY_CTRL_P: pausefadedirect=0; plPause=!plPause; if (plPause) cdPause(fileno(cdpDrive)); else cdRestart(fileno(cdpDrive)); break; case 't': cdpViewSectors=!cdpViewSectors; break; /* case 0x2000: cdpPlayMode=1; setnewpos=0; basesec=cdpTrackStarts[0]; length=cdpTrackStarts[cdpTrackNum]-basesec; // strcpy(name, "DISK"); break; */ case KEY_DOWN: newpos-=75; setnewpos=1; break; case KEY_UP: newpos+=75; setnewpos=1; break; case KEY_LEFT: newpos-=75*10; setnewpos=1; break; case KEY_RIGHT: newpos+=75*10; setnewpos=1; break; case KEY_HOME: if (!cdpPlayMode) { newpos=0; setnewpos=1; break; } for (i=1; i<=cdpTrackNum; i++) if (newpos<(signed)(cdpTrackStarts[i]-basesec)) break; newpos=cdpTrackStarts[i-1]-basesec; setnewpos=1; break; case KEY_CTRL_UP: /* case 0x8D00: //ctrl-up */ newpos-=60*75; setnewpos=1; break; case KEY_CTRL_DOWN: /*case 0x9100: //ctrl-down */ newpos+=60*75; setnewpos=1; break; case KEY_CTRL_LEFT: case '<': if (!cdpPlayMode) break; for (i=2; i<=cdpTrackNum; i++) if (newpos<(signed)(cdpTrackStarts[i]-basesec)) break; newpos=cdpTrackStarts[i-2]-basesec; setnewpos=1; break; case KEY_CTRL_RIGHT: case '>': if (!cdpPlayMode) break; for (i=1; i<=cdpTrackNum; i++) if (newpos<(signed)(cdpTrackStarts[i]-basesec)) break; newpos=cdpTrackStarts[i]-basesec; setnewpos=1; break; /* TODO-keys case 0x7700: //ctrl-home newpos=0; setnewpos=1; break;*/ case KEY_F(9): case KEY_F(11): if ((speed-=finespeed)<16) speed=16; cdSetSpeed(speed); break; case KEY_F(10): case KEY_F(12): if ((speed+=finespeed)>2048) speed=2048; cdSetSpeed(speed); break; default: if (smpProcessKey) { int ret=smpProcessKey(key); if (ret==2) cpiResetScreen(); if (ret) return 1; } if (plrProcessKey) { int ret=plrProcessKey(key); if (ret==2) cpiResetScreen(); if (ret) return 1; } return 0; } return 1; } static int cdaLooped(void) { struct cdStat stat; if (pausefadedirect) dopausefade(); cdSetLoop(fsLoopMods); cdIdle(); cdGetStatus(fileno(cdpDrive), &stat); /* if (status->error&STATUS_ERROR) return 1; */ if (stat.looped) return 1; if (setnewpos) { if (newpos<0) newpos=0; if (newpos>=(signed)length) { if (fsLoopMods) newpos=0; else return 1; } cdPause(fileno(cdpDrive)); cdRestartAt(fileno(cdpDrive), basesec+newpos /*, length-newpos*/); if (plPause) cdPause(fileno(cdpDrive)); setnewpos=0; } else newpos=stat.position-basesec; return 0; } static void cdaCloseFile(void) { cdStop(fileno(cdpDrive)); } static int cdaOpenFile(const char *path, struct moduleinfostruct *info, FILE *file) { char name[NAME_MAX+1]; char ext[NAME_MAX+1]; unsigned char tnum; cdpDrive=file; _splitpath(path, 0, 0, name, ext); if (!strcmp(name, "DISK")) tnum=0xFF; else if (!memcmp(name, "TRACK", 5)&&isdigit(name[5])&&isdigit(name[6])&&(strlen(name)==7)) tnum=(name[5]-'0')*10+(name[6]-'0'); else return -1; if (!cdIsCDDrive(fileno(cdpDrive))) return -1; cdpTrackNum=cdGetTracks(fileno(cdpDrive), cdpTrackStarts, &cdpFirstTrack, CDROM_LEADOUT); if (tnum!=0xFF) { if ((tnum(cdpFirstTrack+cdpTrackNum))) return -1; cdpPlayMode=0; basesec=cdpTrackStarts[tnum-cdpFirstTrack]; length=cdpTrackStarts[tnum-cdpFirstTrack+1]-basesec; } else { if (!cdpTrackNum) return -1; cdpPlayMode=1; basesec=cdpTrackStarts[0]; length=cdpTrackStarts[cdpTrackNum+1]-basesec; } newpos=0; setnewpos=1; plPause=0; plIsEnd=cdaLooped; plProcessKey=cdaProcessKey; plDrawGStrings=cdaDrawGStrings; /* cdLockTray(cdpDrive, 1); */ strncpy(vdev, info->comment, 8); vdev[7]=0; if (cdPlay(fileno(cdpDrive), basesec, length)) return -1; normalize(); pausefadedirect=0; return errOk; } struct cpifaceplayerstruct cdaPlayer = {cdaOpenFile, cdaCloseFile}; char *dllinfo = ""; struct linkinfostruct dllextinfo = {"playcda", "OpenCP CDA Player (c) 1995-09 Niklas Beisert, Tammo Hinrichs, Stian Skjelstad", DLLVERSION, 0 LINKINFOSTRUCT_NOEVENTS}; ocp-0.1.21/playcda/cdaplay.c0000644000175000001440000004120111655541726014621 0ustar stianusers/* OpenCP Module Player * copyright (c) '94-'10 Niklas Beisert * * Audio CD player * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * revision history: (please note changes here) * -nb980510 Niklas Beisert * -first release * -ss040907 Stian Skjelstad * -complete rewrite for linux */ #include "config.h" #include #include #include #include #include #include "types.h" #include "boot/psetting.h" #include "cpiface/cpiface.h" #include "dev/deviplay.h" #include "dev/devisamp.h" #include "dev/player.h" #include "dev/plrasm.h" #include "dev/sampler.h" #include "stuff/imsrtns.h" #include "stuff/poll.h" #include "cdaudio.h" static int device; /* 0 = sampler (with no avaible device) * 1 = sampler (analog) * 2 = player (digital) */ static int cfCDAtLineIn; static int cfCDAdigital; static int doPause; /* digital playback */ /* devp buffer zone */ static uint32_t bufpos; /* devp write head location */ static uint32_t buflen; /* devp buffer-size in samples */ static void *plrbuf; /* the devp buffer */ static int stereo; /* boolean */ static int bit16; /* boolean */ static int signedout; /* boolean */ static int reversestereo; /* boolean */ /* cdIdler dumping locations */ static uint8_t *cdbuf=NULL; /* the buffer */ static uint32_t cdbuflen; /* total buffer size */ static uint32_t cdbufread; /* actually this is the write head */ static uint32_t cdbufpos; /* read pos */ static uint32_t cdbuffpos; /* read fine-pos.. when cdbufrate has a fraction */ static uint32_t cdbufrate; /* re-sampling rate.. fixed point 0x10000 => 1.0 */ static volatile int clipbusy; static int speed; static int doLoop; static int cdflushed; /* all is sent to devp */ /* cdIdle dumping location */ static uint16_t *buf16=NULL; static int lba_start, lba_stop, lba_next; static int cd_fd; #define BUFFER_SLOTS 4 /* TODO, add circular rip buffer */ static struct cdrom_read_audio rip_ioctl; static unsigned char rip_ioctl_buf[CD_FRAMESIZE_RAW*BUFFER_SLOTS]; static unsigned int rip_pcm_left; static void cdIdler(void) { size_t clean; clean=(cdbufpos+cdbuflen-cdbufread)%cdbuflen; if (clean<8) return; clean-=8; while (clean) { size_t read=clean; if (!rip_pcm_left) { if (lba_next==lba_stop) { if (doLoop) lba_next=lba_start; else return; } rip_ioctl.addr.lba=lba_next; rip_ioctl.addr_format=CDROM_LBA; rip_ioctl.nframes=lba_stop-lba_next; if (rip_ioctl.nframes>BUFFER_SLOTS) rip_ioctl.nframes=BUFFER_SLOTS; rip_ioctl.buf=rip_ioctl_buf; if (ioctl(cd_fd, CDROMREADAUDIO, &rip_ioctl)<0) { perror("ioctl(cd_fd, CDROMREADAUDIO, &rip_ioctl)"); return; } rip_pcm_left=CD_FRAMESIZE_RAW*rip_ioctl.nframes; lba_next+=rip_ioctl.nframes; } if (read>rip_pcm_left) read=rip_pcm_left; if ((cdbufread+read)>cdbuflen) read=cdbuflen-cdbufread; memcpy(cdbuf+cdbufread, rip_ioctl_buf+(CD_FRAMESIZE_RAW*BUFFER_SLOTS)-rip_pcm_left, read); cdbufread=(cdbufread+read)%cdbuflen; clean-=read; rip_pcm_left-=read; } } void __attribute__ ((visibility ("internal"))) cdIdle(void) { uint32_t bufplayed; uint32_t bufdelta; uint32_t pass2; int quietlen; if (clipbusy++) { clipbusy--; return; } quietlen=0; /* Where is our devp reading head? */ bufplayed=plrGetBufPos()>>(stereo+bit16); bufdelta=(buflen+bufplayed-bufpos)%buflen; /* No delta on the devp? */ if (!bufdelta) { clipbusy--; if (plrIdle) plrIdle(); return; } /* fill up our buffers */ cdIdler(); if (doPause) { cdflushed=0; quietlen=bufdelta; } else { uint32_t towrap=imuldiv((((cdbuflen+cdbufread-cdbufpos-4)%cdbuflen)>>(1 /* we are always given stereo */ + 1 /* we are always given 16bit */)), 65536, cdbufrate); cdflushed=!towrap; /* dirty hack to tell if all pcm-data has been sent.. */ if (bufdelta>towrap) { /* will the eof hit inside the delta? */ /*quietlen=bufdelta-towrap;*/ bufdelta=towrap; #if 0 /* TODO */ if (eof) /* make sure we did hit eof, and just not out of data situasion due to streaming latency */ looped=1; #endif } } bufdelta-=quietlen; if (bufdelta) { uint32_t i; if (cdbufrate==0x10000) /* 1.0... just copy into buf16 direct until we run out of target buffer or source buffer */ { uint32_t o=0; while (o>2; cdbufpos+=w; if (cdbufpos>=cdbuflen) cdbufpos-=cdbuflen; } } else { /* re-sample intil we don't have more target-buffer or source-buffer */ int32_t c0, c1, c2, c3, ls, rs, vm1,v1,v2, wpm1; uint32_t wp1, wp2; /* if ((bufdelta-=2)<0) bufdelta=0; by my meening, this should be in place TODO stian */ for (i=0; i=cdbuflen) wp1-=cdbuflen; wp2=cdbufpos+8; if (wp2>=cdbuflen) wp2-=cdbuflen; c0 = *(uint16_t *)(cdbuf+cdbufpos)^0x8000; vm1= *(uint16_t *)(cdbuf+wpm1)^0x8000; v1 = *(uint16_t *)(cdbuf+wp1)^0x8000; v2 = *(uint16_t *)(cdbuf+wp2)^0x8000; c1 = v1-vm1; c2 = 2*vm1-2*c0+v1-v2; c3 = c0-vm1-v1+v2; c3 = imulshr16(c3,cdbuffpos); c3 += c2; c3 = imulshr16(c3,cdbuffpos); c3 += c1; c3 = imulshr16(c3,cdbuffpos); ls = c3+c0; if (ls>65535) ls=65535; else if (ls<0) ls=0; c0 = *(uint16_t *)(cdbuf+cdbufpos+2)^0x8000; vm1= *(uint16_t *)(cdbuf+wpm1+2)^0x8000; v1 = *(uint16_t *)(cdbuf+wp1+2)^0x8000; v2 = *(uint16_t *)(cdbuf+wp2+2)^0x8000; c1 = v1-vm1; c2 = 2*vm1-2*c0+v1-v2; c3 = c0-vm1-v1+v2; c3 = imulshr16(c3,cdbuffpos); c3 += c2; c3 = imulshr16(c3,cdbuffpos); c3 += c1; c3 = imulshr16(c3,cdbuffpos); rs = c3+c0; if (rs>65535) rs=65535; else if(rs<0) rs=0; buf16[2*i]=(uint16_t)ls^0x8000; buf16[2*i+1]=(uint16_t)rs^0x8000; cdbuffpos+=cdbufrate; cdbufpos+=(cdbuffpos>>16)*4; cdbuffpos&=0xFFFF; if (cdbufpos>=cdbuflen) cdbufpos-=cdbuflen; } } /* when we copy out of buf16, pass the buffer-len that wraps around end-of-buffer till pass2 */ if ((bufpos+bufdelta)>buflen) pass2=bufpos+bufdelta-buflen; else pass2=0; bufdelta-=pass2; if (bit16) { if (stereo) { if (reversestereo) { int16_t *p=(int16_t *)plrbuf+2*bufpos; int16_t *b=(int16_t *)buf16; if (signedout) { for (i=0; i=buflen) bufpos-=buflen; } bufdelta=quietlen; if (bufdelta) { if ((bufpos+bufdelta)>buflen) pass2=bufpos+bufdelta-buflen; else pass2=0; if (bit16) { plrClearBuf((uint16_t *)plrbuf+(bufpos<=buflen) bufpos-=buflen; } plrAdvanceTo(bufpos<<(stereo+bit16)); if (plrIdle) plrIdle(); clipbusy--; } void __attribute__ ((visibility ("internal"))) cdSetSpeed(unsigned short sp) { if (!cfCDAdigital) return; if (sp<32) sp=32; speed=sp; cdbufrate=imuldiv(256*sp, 44100, plrRate); } int __attribute__ ((visibility ("internal"))) cdIsCDDrive(int fd) { if (ioctl(fd, CDROM_GET_CAPABILITY, 0)>=0) return 1; return 0; } void __attribute__ ((visibility ("internal"))) cdPause(int fd) { doPause=1; if (!cfCDAdigital) { if (ioctl(fd, CDROMPAUSE)) perror("cdaplay: ioctl(fd, CDROMPAUSE)"); } } void __attribute__ ((visibility ("internal"))) cdStop(int fd) { doPause=1; if (!cfCDAdigital) { if (ioctl(fd, CDROMPAUSE)) perror("cdaplay: ioctl(fd, CDROMPAUSE)"); } if (device==1) smpCloseSampler(); else if (device==2) { pollClose(); plrStop(); if (buf16) { free(buf16); buf16=NULL; } if (cdbuf) { free(cdbuf); cdbuf=NULL; } } } void __attribute__ ((visibility ("internal"))) cdRestart(int fd) { doPause=0; if (!cfCDAdigital) { if (ioctl(fd, CDROMRESUME)) perror("cdaplay: ioctl(fd, CDROMRESUME)"); } } unsigned short __attribute__ ((visibility ("internal"))) cdGetTracks(int fd, unsigned long *starts, unsigned char *first, unsigned short maxtracks) { int min=0, max=0, i; struct cdrom_tochdr tochdr; struct cdrom_tocentry tocentry; *first=0; if (!ioctl(fd, CDROMREADTOCHDR, &tochdr)) { if ((min=tochdr.cdth_trk0)<0) min=0; max=tochdr.cdth_trk1; if (max>maxtracks) max=maxtracks; for (i=min;i<=max;i++) { tocentry.cdte_track=i; tocentry.cdte_format= CDROM_LBA; if (!ioctl(fd, CDROMREADTOCENTRY, &tocentry)) starts[i-min]=tocentry.cdte_addr.lba; else { perror("cdaplay: ioctl(fd, CDROMREADTOCENTRY, &tocentry)"); max=i-1; } } tocentry.cdte_track=CDROM_LEADOUT; tocentry.cdte_format= CDROM_LBA; if (!ioctl(fd, CDROMREADTOCENTRY, &tocentry)) starts[max+1-min]=tocentry.cdte_addr.lba; else { perror("cdaplay: ioctl(fd, CDROMREADTOCENTRY, &tocentry)"); max-=1; } } else perror("cdaplay: ioctl(fd, CDROMREADTOCHDR, &tochdr)"); if (max<0) min=max=0; *first=min; return max-min; } void __attribute__ ((visibility ("internal"))) cdRestartAt(int fd, unsigned long start) { doPause=0; lba_next=start; if (cfCDAdigital) { cd_fd=fd; rip_pcm_left=0; } else { struct cdrom_blk blk; blk.from=lba_next; blk.len=lba_stop; if (ioctl(fd, CDROMPLAYBLK, &blk)) perror("cdaplay: ioctl(fd, CDROMPLAYBLK, &blk)"); } } int __attribute__ ((visibility ("internal"))) cdPlay(int fd, unsigned long start, unsigned long len) { cfCDAtLineIn=cfGetProfileBool2(cfSoundSec, "sound", "cdsamplelinein", 0, 0); /* moved from global initclose */ cfCDAdigital=cfGetProfileBool2(cfSoundSec, "sound", "digitalcd", 1, 1); doPause=0; lba_next=lba_start=start; lba_stop=start+len; if (cfCDAdigital) { cd_fd=fd; clipbusy=0; rip_pcm_left=0; cdbuflen=88200; /* 0.5 seconds */ if (!(cdbuf=malloc(cdbuflen))) return -1; cdbufpos=0; cdbuffpos=0; cdbufread=1<<(1/* stereo */+1 /*16bit*/); plGetMasterSample=plrGetMasterSample; plGetRealMasterVolume=plrGetRealMasterVolume; plrSetOptions(44100, (PLR_SIGNEDOUT|PLR_16BIT)|PLR_STEREO); stereo=!!(plrOpt&PLR_STEREO); bit16=!!(plrOpt&PLR_16BIT); signedout=!!(plrOpt&PLR_SIGNEDOUT); reversestereo=!!(plrOpt&PLR_REVERSESTEREO); if (!plrOpenPlayer(&plrbuf, &buflen, plrBufSize)) { free(cdbuf); cdbuf=NULL; return -1; } if (!(buf16=malloc(sizeof(uint16_t)*buflen*2))) { plrClosePlayer(); free(cdbuf); cdbuf=NULL; return -1; } bufpos=0; cdSetSpeed(256); cdSetLoop(1); if (!pollInit(cdIdle)) { free(buf16); buf16=NULL; plrClosePlayer(); free(cdbuf); cdbuf=NULL; return -1; } device=2; } else { struct cdrom_blk blk; blk.from=start; blk.len=len; if (!smpSample) device=0; else { void *buf; int len; plGetMasterSample=smpGetMasterSample; plGetRealMasterVolume=smpGetRealMasterVolume; smpSetSource(cfCDAtLineIn?SMP_LINEIN:SMP_CD); smpSetOptions(plsmpRate, plsmpOpt); if (!smpOpenSampler(&buf, &len, smpBufSize)) return -1; device=1; } if (ioctl(fd, CDROMPLAYBLK, &blk)) perror("cdaplay: ioctl(fd, CDROMPLAYBLK, &blk)"); } return 0; } void __attribute__ ((visibility ("internal"))) cdGetStatus(int fd, struct cdStat *stat) { if (!cfCDAdigital) { struct cdrom_subchnl subchn; subchn.cdsc_format=CDROM_LBA; if (ioctl(fd, CDROMSUBCHNL, &subchn)) { perror("cdaplay: ioctl(fd, CDROMSUBCHNL, &subchn)"); stat->paused=0; stat->error=1; stat->looped=0; return; } switch (subchn.cdsc_audiostatus) { case CDROM_AUDIO_NO_STATUS: case CDROM_AUDIO_PLAY: stat->paused=0; stat->error=0; stat->looped=0; break; case CDROM_AUDIO_PAUSED: case CDROM_AUDIO_COMPLETED: stat->paused=0; stat->looped=1; stat->error=0; break; default: stat->error=1; stat->paused=0; stat->looped=0; } stat->position=subchn.cdsc_absaddr.lba; stat->speed=256; } else { /* TODO */ stat->error=0; stat->paused=doPause; stat->position=lba_next; /* TODO, needs feedback */ stat->speed=(doPause?0:speed); stat->looped=(lba_next==lba_stop)&&(!doLoop)&&(!rip_pcm_left)&&cdflushed; } } void __attribute__ ((visibility ("internal"))) cdSetLoop(int loop) { doLoop=loop; } ocp-0.1.21/playcda/cdaudio.h0000644000175000001440000000220111655541726014616 0ustar stianusers#ifndef _CDAUDIO_H #define _CDAUDIO_H struct cdStat { int paused; /* boolean */ int error; /* boolean */ int looped; /* boolean */ uint32_t position; int speed; }; extern int __attribute__ ((visibility ("internal"))) cdIsCDDrive(int fd); extern void __attribute__ ((visibility ("internal"))) cdStop(int fd); extern void __attribute__ ((visibility ("internal"))) cdRestart(int fd); extern void __attribute__ ((visibility ("internal"))) cdRestartAt(int fd, unsigned long start); extern void __attribute__ ((visibility ("internal"))) cdPause(int fd); extern unsigned short __attribute__ ((visibility ("internal"))) cdGetTracks(int fd, unsigned long *starts, unsigned char *first, unsigned short maxtracks); extern int __attribute__ ((visibility ("internal"))) cdPlay(int fd, unsigned long start, unsigned long len); extern void __attribute__ ((visibility ("internal"))) cdGetStatus(int fd, struct cdStat *stat); extern void __attribute__ ((visibility ("internal"))) cdSetSpeed(unsigned short sp); extern void __attribute__ ((visibility ("internal"))) cdSetLoop(int loop); extern void __attribute__ ((visibility ("internal"))) cdIdle(void); #endif ocp-0.1.21/playcda/Makefile0000644000175000001440000000177611655541726014515 0ustar stianusersTOPDIR=../ include $(TOPDIR)Rules.make ifeq ($(CDROM_SUPPORT),1) PLAYCDA_SO=playcda$(LIB_SUFFIX) endif all: $(PLAYCDA_SO) playcda_so=cdaplay.o cdapplay.o playcda$(LIB_SUFFIX): $(playcda_so) $(CC) $(SHARED_FLAGS) -o $@ $^ clean: rm -f *.o *$(LIB_SUFFIX) install: ifeq ($(CDROM_SUPPORT),1) $(CP) $(PLAYCDA_SO) "$(DESTDIR)$(LIBDIR)" endif uninstall: ifeq ($(CDROM_SUPPORT),1) rm -f "$(DESTDIR)$(LIBDIR)/$(PLAYCDA_SO)" endif cdaplay.o: cdaplay.c cdaudio.h \ ../config.h \ ../types.h \ ../boot/plinkman.h \ ../cpiface/cpiface.h \ ../dev/devisamp.h \ ../dev/deviplay.h \ ../dev/player.h \ ../dev/plrasm.h \ ../dev/sampler.h \ ../stuff/imsrtns.h \ ../stuff/poll.h \ cdaudio.h $(CC) cdaplay.c -o $@ -c cdapplay.o: cdapplay.c cdaudio.h \ ../config.h \ ../types.h \ ../boot/psetting.h \ ../cpiface/cpiface.h \ ../dev/deviplay.h \ ../dev/devisamp.h \ ../filesel/mdb.h \ ../stuff/compat.h \ ../stuff/err.h \ ../stuff/poutput.h \ ../stuff/sets.h \ ../filesel/pfilesel.h $(CC) cdapplay.c -o $@ -c ocp-0.1.21/X11-keymap0000644000175000001440000000041311655541726013203 0ustar stianusers9 -> esc 22 -> backspace 23 -> tab 36 -> enter 37 -> left ctrl 50 -> left shift 64 -> left alt 67 -> f1 .. 76 -> f10 95 -> f11 96 -> f12 97 -> home 98 -> up 99 -> page up 100 -> left 102 -> right 103 -> end 104 -> down 105 -> page down 106 -> insert 107 -> delete ocp-0.1.21/goodies/0000755000175000001440000000000011655541726013056 5ustar stianusersocp-0.1.21/goodies/helpc/0000755000175000001440000000000011655541750014146 5ustar stianusersocp-0.1.21/goodies/helpc/ocphhc.c0000644000175000001440000002773311655541726015575 0ustar stianusers/* OpenCP hypertext help compiler (OCPHHC) for use with new help system * * not copyrighted; written by Fabian Giesen (RYG/Chrome Design) * it's simple. it's freeware. it's badly coded. it (hardly) works. * * revision history: (please note changes here) * -fg980811 Fabian Giesen * -first alpha * -fg980812 Fabian Giesen * -bugfixing * -fg980813 Fabian Giesen * -added some commands * -fg980814 Fabian Giesen * -new helpfile format version which is compressed * -compressed using "deflate" algorithm (via zlib), can be decompressed * with OpenCP standard INFLATE.DLL * -fg980815 Fabian Giesen * -added "statistics" screen * -ryg_dunno Fabian Giesen * -fixed some bugs (don't remember which ones) * -changed email address (yeah, i've got a new one) * -now i use "ryg" instead of "fg"; don't ask me why * -ryg981205 Fabian Giesen * -now uses some pseudo-zlib with just the deflation code in it (because * including whole zlib would be just a waste of space) * -this code is ABSOLUTELY NOT SUPPORTED. if it crashes, it's your own * problem. also it will be obselete soon because i'll write some * html->help compiler (which roxxs :) * -there's no documentation for this. read the help definition file and * try and understand it. good luck. * -ryg981211 Fabian Giesen * -fixed some stupid bug in the "parser" which killed almost all escape * seqeunces (oops..) * -fd990519 Felix Domke * -fixed the stupid "backslashed". * * READ THIS SOURCE FILE CAREFULLY. IT'S SURELY ONE OF THE BEST EXAMPLES OF * BAD C CODE YOU'LL EVER GET. * * some other thing: in this file the help pages are called "sections" (don't * ask me why). */ #include "config.h" #include #include #include #include "types.h" #include "zlib.h" #pragma pack (1) /* this is essential */ #define MAXSECTSIZE (256*1024) /* maximum section size 256k */ /* Help file control characters */ #define CMD_NORMAL 1 /* switch colour to normal */ #define CMD_BRIGHT 2 /* switch colour to bright */ #define CMD_HYPERLINK 3 /* hyperlink */ #define CMD_CENTERED 4 /* centered text */ #define CMD_COLOURCHOOSE 5 /* choose colour */ #define CMD_RAWCHAR 6 /* raw character (use for chars<32) */ typedef struct sect { char *name; char *desc; void *data, *compdata; uint32_t datasize, compdatasize, textlines; struct sect *next; } section; char line[2048], sectionbuf[MAXSECTSIZE]; int sectpos=0, quit=0, sectlines=0; section *sections=NULL, *cursect=NULL; FILE *in, *out; char file_id[5]="OCPH"; uint32_t helpver=0x011000; int verbose=0, comment=0; int totdatasize, totcompdatasize; void putfstr(char *what, FILE *to) { if (what) { putc(strlen(what), to); if (strlen(what)) if (fwrite(what, strlen(what), 1, to) != 1) { perror(__FILE__ ": fwrite failed #1: "); exit(1); } } else putc(0, to); } void flush_section(void) { if (!cursect || comment) return; cursect->data=calloc(1, sectpos); memcpy(cursect->data, sectionbuf, sectpos); cursect->datasize=sectpos; cursect->textlines=sectlines; sectpos=0; sectlines=0; } void process_section_line(char *line) { char *p1, *p2; int i; flush_section(); comment=0; if (!strncasecmp(line, ".comment", 9)) { comment=1; return; }; if (!strncasecmp(line, ".end", 4)) { quit=1; return; }; if (cursect) { cursect->next=calloc(sizeof(section), 1); cursect=cursect->next; } else { sections=calloc(sizeof(section), 1); cursect=sections; }; p1=line+1; p2=p1; i=0; while (*p2 && (*p2!=' ')) p2++; if (*p2) i=1; *p2=0; cursect->name=strdup(p1); if (i) cursect->desc=strdup(p2+1); else cursect->desc=NULL; cursect->data=NULL; cursect->next=NULL; } int packhex(char *from) { int val; char buf[3]; strncpy(buf, from, 2); buf[2]=0; val=0; if ((*from>='0') && (*from<='9')) val|=*from-'0'; if ((*from>='A') && (*from<='F')) val|=*from-'A'+10; if ((*from>='a') && (*from<='f')) val|=*from-'a'+10; val<<=4; from++; if ((*from>='0') && (*from<='9')) val|=*from-'0'; if ((*from>='A') && (*from<='F')) val|=*from-'A'+10; if ((*from>='a') && (*from<='f')) val|=*from-'a'+10; return val; } void process_text_line(char *line) { char buffer[2048], buffer2[2048], *p; int len, brightst, i, backslashed; if (comment) return; strcpy(buffer, line); brightst=0; backslashed=0; /* First, process all "bright"-switches */ p=&buffer[0]; i=0; while (*p) { backslashed=(*p=='\\')&&(!backslashed); /* better? (fd) */ if (((unsigned)*p)<32) { strcpy(buffer2, &buffer[i+1]); strcpy(&buffer[i+2], buffer2); buffer[i+1]=*p; buffer[i]=CMD_RAWCHAR; p++; i++; } else if (*p=='~') { if (backslashed) { strcpy(buffer2, p); strcpy(p-1, buffer2); backslashed=0; } else { brightst=1-brightst; if (brightst) *p=CMD_BRIGHT; else *p=CMD_NORMAL; } } else if (*p=='^') { if (backslashed) { strcpy(buffer2, p); strcpy(p-1, buffer2); backslashed=0; } else { *p=CMD_COLOURCHOOSE; p++; i++; *p=packhex(p); strcpy(buffer2, p+2); strcpy(p+1, buffer2); } } else if (*p=='n') { if (backslashed) { *(p-1)=CMD_RAWCHAR; *p='\n'; backslashed=0; } } else if (*p=='r') { if (backslashed) { *(p-1)=CMD_RAWCHAR; *p='\r'; backslashed=0; } } else if (*p=='d') { if (backslashed) { *(p-1)=CMD_RAWCHAR; *p=26; backslashed=0; } } p++; i++; } /* Then check for any special marks. If there are, process them, otherwise, * just copy the text. */ if (strchr(buffer, '[')) { if (*(strchr(buffer, '[')-1)!='\\') { char *fptr;; len=strlen(buffer); fptr=&buffer[0]; while ((fptr=strchr(fptr, '\\'))) { strcpy(fptr, fptr+1); fptr+=1; } *strchr(buffer, '[')=CMD_CENTERED; if (strchr(buffer, ']')) *strchr(buffer, ']')=0; memcpy(§ionbuf[sectpos], buffer, len); sectpos+=len+1; sectionbuf[sectpos-1]='\n'; } else { char *fptr=&buffer[0]; while ((fptr=strchr(fptr, '\\'))) { strcpy(fptr, fptr+1); fptr+=1; } len=strlen(buffer); memcpy(§ionbuf[sectpos], buffer, len); sectpos+=len+1; sectionbuf[sectpos-1]='\n'; } } else if (strchr(buffer, '{')) { if (*(strchr(buffer, '{')-1)!='\\') { char *fptr; len=strlen(buffer); fptr=&buffer[0]; while ((fptr=strchr(fptr, '\\'))) { strcpy(fptr, fptr+1); fptr+=1; }; *strchr(buffer, '{')=CMD_HYPERLINK; if (strchr(buffer, '}')) *strchr(buffer, '}')=0; memcpy(§ionbuf[sectpos], buffer, len); sectpos+=len+1; sectionbuf[sectpos-1]='\n'; } else { char *fptr; strcpy(strchr(buffer, '{')-1, strchr(buffer, '{')); fptr=&buffer[0]; while ((fptr=strchr(fptr, '\\'))) { strcpy(fptr, fptr+1); fptr+=1; } len=strlen(buffer); memcpy(§ionbuf[sectpos], buffer, len); sectpos+=len+1; sectionbuf[sectpos-1]='\n'; } } else { char *fptr=&buffer[0]; while ((fptr=strchr(fptr, '\\'))) { strcpy(fptr, fptr+1); fptr+=1; } len=strlen(buffer); memcpy(§ionbuf[sectpos], buffer, len); sectpos+=len+1; sectionbuf[sectpos-1]='\n'; } sectlines++; } void read_lines(void) { while (!feof(in) && (!quit)) { if (!fgets(line, 2048, in)) break; if (line[strlen(line)-1]=='\n') line[strlen(line)-1]=0; if (line[strlen(line)-1]=='\r') line[strlen(line)-1]=0; if (line[0]=='.') process_section_line(line); else process_text_line(line); } } void compress_sections(void) { uLong insize, outsize; unsigned char *inbuf, *outbuf; section *s; s=sections; while (s) { inbuf=(unsigned char *) s->data; insize=s->datasize; outsize=insize+(insize/1000)+2; outbuf=calloc(outsize, 1); compress2(outbuf, &outsize, inbuf, insize, 9); #if 0 s->compdata=(void *) (outbuf+2); s->compdatasize=outsize-2; /* this is because zlib puts 2 header bytes to the beginning of the data- * stream we don't need */ #else s->compdata=(void *) (outbuf); s->compdatasize=outsize; #endif s=s->next; }; } void write_section_directory(void) { uint32_t numsects; section *s; s=sections; numsects=0; while (s) { s=s->next; numsects++; } numsects = uint32_little(numsects); if (fwrite(&numsects, 4, 1, out) != 1) { perror(__FILE__ ": fwrite failed #2: "); exit(1); } s=sections; while (s) { putfstr(s->name, out); putfstr(s->desc, out); s->datasize=uint32_little(s->datasize); s->textlines=uint32_little(s->textlines); s->compdatasize=uint32_little(s->compdatasize); if (fwrite(&s->datasize, 4, 1, out) != 1) { perror(__FILE__ ": fwrite failed #3: "); exit(1); } if (fwrite(&s->textlines, 4, 1, out) != 1) { perror(__FILE__ ": fwrite failed #4: "); exit(1); } if (fwrite(&s->compdatasize, 4, 1, out) != 1) { perror(__FILE__ ": fwrite failed #5: "); exit(1); } s->datasize=uint32_little(s->datasize); s->textlines=uint32_little(s->textlines); s->compdatasize=uint32_little(s->compdatasize); s=s->next; } } void write_sections(void) { section *s; int i; s=sections; i=0; while (s) { i++; if (fwrite(s->compdata, s->compdatasize, 1, out) != 1) { perror(__FILE__ ": fwrite failed #6: "); exit(1); } if (verbose) printf("Page: %ld, original size %ld bytes, compressed %ld bytes\n", (long)i, (long)s->datasize, (long)s->compdatasize); totdatasize+=s->datasize; totcompdatasize+=s->compdatasize; s=s->next; } } void write_file_header(void) { uint32_t t = uint32_little(helpver); if (fwrite(file_id, 4, 1, out) != 1) { perror(__FILE__ ": fwrite failed #7: "); exit(1); } if (fwrite(&t, 4, 1, out) != 1) { perror(__FILE__ ": fwrite failed #8: "); exit(1); } } int main(int argc, char *argv[]) { printf("OCPHHC - OpenCP hypertext help compiler v1.2a - written by ryg\n\n"); if (argc!=3) { printf("Use: OCPHHC \n\n"); return 0; } in=fopen(argv[1], "rb"); out=fopen(argv[2], "wb"); totdatasize=totcompdatasize=0; printf("Reading input...\n"); read_lines(); printf("Compressing page data...\n"); compress_sections(); printf("Writing output header...\n"); write_file_header(); printf("Writing page directory...\n"); write_section_directory(); printf("Writing pages...\n"); write_sections(); printf("\nDone!\n\n"); printf("Helpfile statistics:\n\n"); printf("Complete data size : %ld bytes (%ld KB)\n", (long)totdatasize, (long)(totdatasize>>10)); printf("Compressed data size: %ld bytes (%ld KB)\n", (long)totcompdatasize, (long)(totcompdatasize>>10)); printf("Ratio : %2.1f:1\n", (float) totdatasize/(float) totcompdatasize); printf("\n"); fclose(in); fclose(out); for(cursect=sections;cursect;cursect=sections) { sections=cursect->next; free(cursect->name); free(cursect->desc); free(cursect->data); free(cursect->compdata); free(cursect); } return 0; } ocp-0.1.21/goodies/helpc/Makefile.in0000644000175000001440000000040011655541726016210 0ustar stianusersTOPDIR=../../ include $(TOPDIR)Rules.make all: ocphhc clean: rm -f ocphhc *.o install: uninstall: ocphhc.o: ocphhc.c \ ../../config.h \ ../../types.h $(CC) -I../../ ocphhc.c -o $@ -c ocphhc: ocphhc.o $(CC) -o $@ $^ -lz @EFENCE_LIBS@ @DUMA_LIBS@ ocp-0.1.21/goodies/tga2wav/0000755000175000001440000000000011655541726014431 5ustar stianusersocp-0.1.21/goodies/tga2wav/makefile.gnu0000644000175000001440000000014211655541726016716 0ustar stianusersCXXFLAGS+= -Wall -O2 tga2wav: tga2wav.o $(CXX) -o $@ $^ -lm clean: rm -f tga2wav *.o *~ *.wav ocp-0.1.21/goodies/tga2wav/makefile.wat0000644000175000001440000000060211655541726016721 0ustar stianuserscopt = /otexan /fpi87 lopt = exefile = tga2wav objects = tga2wav.obj $(exefile).exe: $(objects) *wlink $(lopt) & system dos4g & name $^*.exe & debug watcom all & file {$(objects)} & option map & option eliminate .cpp.obj: *wpp386 $(copt) $< clean: del *.obj del *.err del *.map del *.bak del $(exefile).exe del *.wav ocp-0.1.21/goodies/tga2wav/tga2wav.cpp0000644000175000001440000001350611655541726016515 0ustar stianusers// TGA 2 WAV Converter // written sometime in 1995 by Dirk Jagdmann // then patched by Niklas Beisert to support different phases // then lost // and found again in 2002 by Dirk Jagdmann #ifdef __WATCOMC__ #include #include #include #include #include #include #else #include #include #include #include #include using namespace std; #define _MAX_PATH PATH_MAX #endif #ifdef __unix__ #include #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #if defined(_WIN32) || __GNUC__ >= 3 || defined(__INTEL_COMPILER) || defined(__WATCOMC__) #define P #pragma pack(push, 1) #else #define P __attribute__ ((packed)) #endif struct WAVfmt { char name[4]; /* "fmt " */ unsigned long length; /* 0x10 */ unsigned short type; /* 1=WAVE_FORMAT_PCM see below for more WAVE_FORMAT_... */ unsigned short channels; /* commonly 1,2 but can be >2 */ unsigned long rate; unsigned long bytesPerSecond; /* rate*bytesPerSample */ union { unsigned short blockAlign; unsigned short bytesPerSample; /* channels*(bitsPerSample/8), but bitsPerSample/8 has to be rounded up! */ }; unsigned short bitsPerSample; /* 8,12,16,24 */ } P; struct WAVdata { char name[4]; /* "data" */ unsigned long length; /* length of following sample stream = WAV.length - 0x24 = filelength - 8 - 0x24 */ } P; struct WAV { char name[4]; /* "RIFF" */ unsigned long length; /* filelength - 8 */ char type[4]; /* "WAVE" */ struct WAVfmt fmt; struct WAVdata data; } P; struct TGA { unsigned char idlen; // 0 unsigned char cmtype; // 1 unsigned char type; // 2 unsigned short cmstart; // 3 unsigned short cmlen; // 5 unsigned char cmsize; // 7 unsigned short imgx; // 8 unsigned short imgy; // 10 unsigned short width; // 12 unsigned short height; // 14 unsigned char imgbits; // 15 unsigned char attrbits :4; // 16.0 unsigned char reserved :1; // 16.4 unsigned char origin :1 ; // 16.5 unsigned char interleave :2; // 16.6 } P; #if defined(_WIN32) || __GNUC__ >= 3 || defined(__INTEL_COMPILER) || defined(__WATCOMC__) #pragma pack(pop) #endif #undef P FILE *infile=0, *outfile=0; char ofiles[_MAX_PATH+1]; bool cleanexit=false; unsigned char *bild=0; bool bildSwap=false; TGA tga; unsigned char pixel(int x, int y) { if(bildSwap) y=tga.height-1-y; return bild[y*tga.width+x]; } void cleanup() { if(infile) fclose(infile); if(outfile) fclose(outfile); if(!cleanexit) unlink(ofiles); if(bild) delete [] bild; cout << endl; } int main(int argc, char **argv) { int samplerate=44100; int len=256; int i; double amplify=0.0; char ifiles[_MAX_PATH+1]; atexit(cleanup); if (argc>2) { i=atoi(argv[2]); if(i>0) { amplify=i; goto jumpparam; } strcpy(ifiles,argv[1]); strcpy(ofiles,argv[2]); } if (argc==2) { jumpparam: strcpy(ifiles,argv[1]); strcat(ifiles,".tga"); strcpy(ofiles,argv[1]); strcat(ofiles,".wav"); } if (argc==1) { cout << "filename without suffix: "; char file[_MAX_PATH+1]; cin >> file; strcpy(ifiles,file); strcat(ifiles,".tga"); strcpy(ofiles,file); strcat(ofiles,".wav"); } if(amplify==0.0) { cout << "Amplify: "; cin >> amplify; } if (amplify<1.0) { cerr << "amplification too low!" << endl; return 1; } FILE *infile=fopen(ifiles, "rb"); if(infile==0) { cerr << "could not read " << ifiles << endl; return 1; } fread(&tga, sizeof(tga), 1, infile); if(tga.type!=1) { cerr << "tga file is not of uncompressed palette type" << endl; return 1; } bildSwap=!tga.origin; cout << "height: " << tga.height << endl; cout << "width: " << tga.width << endl; const int wavgros=tga.width*len * 2; cout << "size of wav file: " << wavgros+0x24+8 << endl; const int groesse=tga.width*tga.height; bild=new unsigned char [groesse]; if(!bild) { cerr << "could not alloc memory. Perhaps the picture is too large?" << endl; return 1; } unsigned char palette[256]; for (i=0; i<256; i++) { unsigned char blau,grun,rot; fread(&blau,1,1,infile); fread(&grun,1,1,infile); fread(&rot,1,1,infile); palette[i]=(blau+grun+rot)/3; } fread(bild,groesse, 1, infile); FILE *outfile=fopen(ofiles, "wb"); WAV w = { {'R','I','F','F'}, 0x24 + wavgros, {'W','A','V','E'}, { {'f','m','t',' '}, 0x10, 1, 1, samplerate, samplerate*2, {2}, 16, }, { {'d','a','t','a'}, wavgros, }, }; fwrite(&w, sizeof(w), 1, outfile); double *sample=new double[len]; if(sample==0) { cerr << "could not alloc memory" << endl; return 1; } int offset=0; int oldperc=0; for (int x=0; x oldperc) { oldperc=x*100/tga.width; cout << "\r" << oldperc << "%"; fflush(stdout); } for (i=0; i32700.0) a=32700; else if(sample[i]<-32700.0) a=-32700; fwrite(&a, sizeof(a), 1, outfile); } } delete [] sample; cleanexit=true; return 0; } ocp-0.1.21/goodies/tga2wav/c.tga0000644000175000001440000011755411655541726015365 0ustar stianusersôP ÿÿÿÿÿÿÿÿÿÿÿÿ????#?5Yÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ[__ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿTRUEVISION-XFILE.ocp-0.1.21/goodies/wap/0000755000175000001440000000000011655541726013645 5ustar stianusersocp-0.1.21/goodies/wap/wap.cpp0000644000175000001440000002577511655541726015160 0ustar stianusers// WuerfelAnimator *PROFESSIONAL*, // a totally useless tool, // by Felix Domke // // missing features: - delta-compression (dltrle) // - startframe // - palette optimization(!), not just a "cut-the-first-16-colors", a "search-16-irrelevant-colors-and-remove-them" would be better // features: - input format: pcx // - palette "optimization" // - output format: CPANIM 1.0, 2.0 // - rle-compressed // - strangeframeoptimization for small & slow anims // code needs some cleanup, but works quite perfect ;) #include #include #include #include #include "ptypes.h" int LoadPCX(FILE *fp, uint1 *outpix, uint1 * pal, int* width, int* height); void OptimizePalette(char *picture, int bytes, char *srcpal, char *pal); int GetClosestColor(char *pal, int r, int g, int b); struct cpaniheaderstruct { char id[8]; // CPANI<1a><0><0> char junk[32]; short wuerfelframes; short wuerfelstframes; short flags; // rle=1, dlt=2, 2.0=4 short junk2; short codelenslen; short pallen; }; void main(int argc, char **argv) { printf("WuerfelAnimator *PROFESSIONAL* (c) 1998 by Felix Domke\n"); if(argc!=3) { printf("Usage: %s