munitrk.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:8k
源码类别:
Windows CE
开发平台:
C/C++
- /* MikMod sound library
- (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
- for complete list.
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU Library 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 Library General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
- */
- /*==============================================================================
- $Id: munitrk.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
- All routines dealing with the manipulation of UNITRK streams
- ==============================================================================*/
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include "mikmod_internals.h"
- #include <string.h>
- /* Unibuffer chunk size */
- #define BUFPAGE 128
- UWORD unioperands[UNI_LAST]={
- 0, /* not used */
- 1, /* UNI_NOTE */
- 1, /* UNI_INSTRUMENT */
- 1, /* UNI_PTEFFECT0 */
- 1, /* UNI_PTEFFECT1 */
- 1, /* UNI_PTEFFECT2 */
- 1, /* UNI_PTEFFECT3 */
- 1, /* UNI_PTEFFECT4 */
- 1, /* UNI_PTEFFECT5 */
- 1, /* UNI_PTEFFECT6 */
- 1, /* UNI_PTEFFECT7 */
- 1, /* UNI_PTEFFECT8 */
- 1, /* UNI_PTEFFECT9 */
- 1, /* UNI_PTEFFECTA */
- 1, /* UNI_PTEFFECTB */
- 1, /* UNI_PTEFFECTC */
- 1, /* UNI_PTEFFECTD */
- 1, /* UNI_PTEFFECTE */
- 1, /* UNI_PTEFFECTF */
- 1, /* UNI_S3MEFFECTA */
- 1, /* UNI_S3MEFFECTD */
- 1, /* UNI_S3MEFFECTE */
- 1, /* UNI_S3MEFFECTF */
- 1, /* UNI_S3MEFFECTI */
- 1, /* UNI_S3MEFFECTQ */
- 1, /* UNI_S3MEFFECTR */
- 1, /* UNI_S3MEFFECTT */
- 1, /* UNI_S3MEFFECTU */
- 0, /* UNI_KEYOFF */
- 1, /* UNI_KEYFADE */
- 2, /* UNI_VOLEFFECTS */
- 1, /* UNI_XMEFFECT4 */
- 1, /* UNI_XMEFFECT6 */
- 1, /* UNI_XMEFFECTA */
- 1, /* UNI_XMEFFECTE1 */
- 1, /* UNI_XMEFFECTE2 */
- 1, /* UNI_XMEFFECTEA */
- 1, /* UNI_XMEFFECTEB */
- 1, /* UNI_XMEFFECTG */
- 1, /* UNI_XMEFFECTH */
- 1, /* UNI_XMEFFECTL */
- 1, /* UNI_XMEFFECTP */
- 1, /* UNI_XMEFFECTX1 */
- 1, /* UNI_XMEFFECTX2 */
- 1, /* UNI_ITEFFECTG */
- 1, /* UNI_ITEFFECTH */
- 1, /* UNI_ITEFFECTI */
- 1, /* UNI_ITEFFECTM */
- 1, /* UNI_ITEFFECTN */
- 1, /* UNI_ITEFFECTP */
- 1, /* UNI_ITEFFECTT */
- 1, /* UNI_ITEFFECTU */
- 1, /* UNI_ITEFFECTW */
- 1, /* UNI_ITEFFECTY */
- 2, /* UNI_ITEFFECTZ */
- 1, /* UNI_ITEFFECTS0 */
- 2, /* UNI_ULTEFFECT9 */
- 2, /* UNI_MEDSPEED */
- 0, /* UNI_MEDEFFECTF1 */
- 0, /* UNI_MEDEFFECTF2 */
- 0, /* UNI_MEDEFFECTF3 */
- 2, /* UNI_OKTARP */
- };
- /* Sparse description of the internal module format
- ------------------------------------------------
- A UNITRK stream is an array of bytes representing a single track of a pattern.
- It's made up of 'repeat/length' bytes, opcodes and operands (sort of a assembly
- language):
- rrrlllll
- [REP/LEN][OPCODE][OPERAND][OPCODE][OPERAND] [REP/LEN][OPCODE][OPERAND]..
- ^ ^ ^
- |-------ROWS 0 - 0+REP of a track---------| |-------ROWS xx - xx+REP of a track...
- The rep/len byte contains the number of bytes in the current row, _including_
- the length byte itself (So the LENGTH byte of row 0 in the previous example
- would have a value of 5). This makes it easy to search through a stream for a
- particular row. A track is concluded by a 0-value length byte.
- The upper 3 bits of the rep/len byte contain the number of times -1 this row
- is repeated for this track. (so a value of 7 means this row is repeated 8 times)
- Opcodes can range from 1 to 255 but currently only opcodes 1 to 62 are being
- used. Each opcode can have a different number of operands. You can find the
- number of operands to a particular opcode by using the opcode as an index into
- the 'unioperands' table.
- */
- /*========== Reading routines */
- static UBYTE *rowstart; /* startadress of a row */
- static UBYTE *rowend; /* endaddress of a row (exclusive) */
- static UBYTE *rowpc; /* current unimod(tm) programcounter */
- static UBYTE lastbyte; /* for UniSkipOpcode() */
- void UniSetRow(UBYTE* t)
- {
- rowstart = t;
- rowpc = rowstart;
- rowend = t?rowstart+(*(rowpc++)&0x1f):t;
- }
- UBYTE UniGetByte(void)
- {
- return lastbyte = (rowpc<rowend)?*(rowpc++):0;
- }
- UWORD UniGetWord(void)
- {
- return ((UWORD)UniGetByte()<<8)|UniGetByte();
- }
- void UniSkipOpcode(void)
- {
- if (lastbyte < UNI_LAST) {
- UWORD t = unioperands[lastbyte];
- while (t--)
- UniGetByte();
- }
- }
- /* Finds the address of row number 'row' in the UniMod(tm) stream 't' returns
- NULL if the row can't be found. */
- UBYTE *UniFindRow(UBYTE* t,UWORD row)
- {
- UBYTE c,l;
- if(t)
- while(1) {
- c = *t; /* get rep/len byte */
- if(!c) return NULL; /* zero ? -> end of track.. */
- l = (c>>5)+1; /* extract repeat value */
- if(l>row) break; /* reached wanted row? -> return pointer */
- row -= l; /* haven't reached row yet.. update row */
- t += c&0x1f; /* point t to the next row */
- }
- return t;
- }
- /*========== Writing routines */
- static UBYTE *unibuf; /* pointer to the temporary unitrk buffer */
- static UWORD unimax; /* buffer size */
- static UWORD unipc; /* buffer cursor */
- static UWORD unitt; /* current row index */
- static UWORD lastp; /* previous row index */
- /* Resets index-pointers to create a new track. */
- void UniReset(void)
- {
- unitt = 0; /* reset index to rep/len byte */
- unipc = 1; /* first opcode will be written to index 1 */
- lastp = 0; /* no previous row yet */
- unibuf[0] = 0; /* clear rep/len byte */
- }
- /* Expands the buffer */
- static BOOL UniExpand(int wanted)
- {
- if ((unipc+wanted)>=unimax) {
- UBYTE *newbuf;
- /* Expand the buffer by BUFPAGE bytes */
- newbuf=(UBYTE*)realloc(unibuf,(unimax+BUFPAGE)*sizeof(UBYTE));
- /* Check if realloc succeeded */
- if(newbuf) {
- unibuf = newbuf;
- unimax+=BUFPAGE;
- return 1;
- } else
- return 0;
- }
- return 1;
- }
- /* Appends one byte of data to the current row of a track. */
- void UniWriteByte(UBYTE data)
- {
- if (UniExpand(1))
- /* write byte to current position and update */
- unibuf[unipc++]=data;
- }
- void UniWriteWord(UWORD data)
- {
- if (UniExpand(2)) {
- unibuf[unipc++]=data>>8;
- unibuf[unipc++]=data&0xff;
- }
- }
- static BOOL MyCmp(UBYTE* a,UBYTE* b,UWORD l)
- {
- UWORD t;
- for(t=0;t<l;t++)
- if(*(a++)!=*(b++)) return 0;
- return 1;
- }
- /* Closes the current row of a unitrk stream (updates the rep/len byte) and sets
- pointers to start a new row. */
- void UniNewline(void)
- {
- UWORD n,l,len;
- n = (unibuf[lastp]>>5)+1; /* repeat of previous row */
- l = (unibuf[lastp]&0x1f); /* length of previous row */
- len = unipc-unitt; /* length of current row */
- /* Now, check if the previous and the current row are identical.. when they
- are, just increase the repeat field of the previous row */
- if(n<8 && len==l && MyCmp(&unibuf[lastp+1],&unibuf[unitt+1],len-1)) {
- unibuf[lastp]+=0x20;
- unipc = unitt+1;
- } else {
- if (UniExpand(unitt-unipc)) {
- /* current and previous row aren't equal... update the pointers */
- unibuf[unitt] = len;
- lastp = unitt;
- unitt = unipc++;
- }
- }
- }
- /* Terminates the current unitrk stream and returns a pointer to a copy of the
- stream. */
- UBYTE* UniDup(void)
- {
- UBYTE *d;
- if (!UniExpand(unitt-unipc)) return NULL;
- unibuf[unitt] = 0;
- if(!(d=(UBYTE *)_mm_malloc(unipc))) return NULL;
- memcpy(d,unibuf,unipc);
- return d;
- }
- BOOL UniInit(void)
- {
- unimax = BUFPAGE;
- if(!(unibuf=(UBYTE*)_mm_malloc(unimax*sizeof(UBYTE)))) return 0;
- return 1;
- }
- void UniCleanup(void)
- {
- if(unibuf) free(unibuf);
- unibuf = NULL;
- }
- /* ex:set ts=4: */