📄 load_dsm.c
字号:
/* MikMod sound library (c) 1998, 1999, 2000, 2001, 2002 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: load_dsm.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $ DSIK internal format (DSM) module loader==============================================================================*/#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdio.h>#ifdef HAVE_MEMORY_H#include <memory.h>#endif#include <string.h>#include "mikmod_internals.h"#ifdef SUNOSextern int fprintf(FILE *, const char *, ...);#endif/*========== Module structure */#define DSM_MAXCHAN (16)#define DSM_MAXORDERS (128)typedef struct DSMSONG { CHAR songname[28]; UWORD version; UWORD flags; ULONG reserved2; UWORD numord; UWORD numsmp; UWORD numpat; UWORD numtrk; UBYTE globalvol; UBYTE mastervol; UBYTE speed; UBYTE bpm; UBYTE panpos[DSM_MAXCHAN]; UBYTE orders[DSM_MAXORDERS];} DSMSONG;typedef struct DSMINST { CHAR filename[13]; UWORD flags; UBYTE volume; ULONG length; ULONG loopstart; ULONG loopend; ULONG reserved1; UWORD c2spd; UWORD period; CHAR samplename[28];} DSMINST;typedef struct DSMNOTE { UBYTE note,ins,vol,cmd,inf;} DSMNOTE;#define DSM_SURROUND (0xa4)/*========== Loader variables */static CHAR* SONGID="SONG";static CHAR* INSTID="INST";static CHAR* PATTID="PATT";static UBYTE blockid[4];static ULONG blockln;static ULONG blocklp;static DSMSONG* mh=NULL;static DSMNOTE* dsmbuf=NULL;static CHAR DSM_Version[]="DSIK DSM-format";static unsigned char DSMSIG[4+4]={'R','I','F','F','D','S','M','F'};/*========== Loader code */BOOL DSM_Test(void){ UBYTE id[12]; if(!_mm_read_UBYTES(id,12,modreader)) return 0; if(!memcmp(id,DSMSIG,4) && !memcmp(id+8,DSMSIG+4,4)) return 1; return 0;}BOOL DSM_Init(void){ if(!(dsmbuf=(DSMNOTE *)_mm_malloc(DSM_MAXCHAN*64*sizeof(DSMNOTE)))) return 0; if(!(mh=(DSMSONG *)_mm_calloc(1,sizeof(DSMSONG)))) return 0; return 1;}void DSM_Cleanup(void){ _mm_free(dsmbuf); _mm_free(mh);}static BOOL GetBlockHeader(void){ /* make sure we're at the right position for reading the next riff block, no matter how many bytes read */ _mm_fseek(modreader, blocklp+blockln, SEEK_SET); while(1) { _mm_read_UBYTES(blockid,4,modreader); blockln=_mm_read_I_ULONG(modreader); if(_mm_eof(modreader)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } if(memcmp(blockid,SONGID,4) && memcmp(blockid,INSTID,4) && memcmp(blockid,PATTID,4)) {#ifdef MIKMOD_DEBUG fprintf(stderr,"\rDSM: Skipping unknown block type %4.4s\n",blockid);#endif _mm_fseek(modreader, blockln, SEEK_CUR); } else break; } blocklp = _mm_ftell(modreader); return 1;}static BOOL DSM_ReadPattern(void){ int flag,row=0; SWORD length; DSMNOTE *n; /* clear pattern data */ memset(dsmbuf,255,DSM_MAXCHAN*64*sizeof(DSMNOTE)); length=_mm_read_I_SWORD(modreader); while(row<64) { flag=_mm_read_UBYTE(modreader); if((_mm_eof(modreader))||(--length<0)) { _mm_errno = MMERR_LOADING_PATTERN; return 0; } if(flag) { n=&dsmbuf[((flag&0xf)*64)+row]; if(flag&0x80) n->note=_mm_read_UBYTE(modreader); if(flag&0x40) n->ins=_mm_read_UBYTE(modreader); if(flag&0x20) n->vol=_mm_read_UBYTE(modreader); if(flag&0x10) { n->cmd=_mm_read_UBYTE(modreader); n->inf=_mm_read_UBYTE(modreader); } } else row++; } return 1;}static UBYTE *DSM_ConvertTrack(DSMNOTE *tr){ int t; UBYTE note,ins,vol,cmd,inf; UniReset(); for(t=0;t<64;t++) { note=tr[t].note; ins=tr[t].ins; vol=tr[t].vol; cmd=tr[t].cmd; inf=tr[t].inf; if(ins!=0 && ins!=255) UniInstrument(ins-1); if(note!=255) UniNote(note-1); /* normal note */ if(vol<65) UniPTEffect(0xc,vol); if(cmd!=255) { if(cmd==0x8) { if(inf==DSM_SURROUND) UniEffect(UNI_ITEFFECTS0,0x91); else if(inf<=0x80) { inf=(inf<0x80)?inf<<1:255; UniPTEffect(cmd,inf); } } else if(cmd==0xb) { if(inf<=0x7f) UniPTEffect(cmd,inf); } else { /* Convert pattern jump from Dec to Hex */ if(cmd == 0xd) inf = (((inf&0xf0)>>4)*10)+(inf&0xf); UniPTEffect(cmd,inf); } } UniNewline(); } return UniDup();}BOOL DSM_Load(BOOL curious){ int t; DSMINST s; SAMPLE *q; int cursmp=0,curpat=0,track=0; blocklp=0; blockln=12; if(!GetBlockHeader()) return 0; if(memcmp(blockid,SONGID,4)) { _mm_errno = MMERR_LOADING_HEADER; return 0; } _mm_read_UBYTES(mh->songname,28,modreader); mh->version=_mm_read_I_UWORD(modreader); mh->flags=_mm_read_I_UWORD(modreader); mh->reserved2=_mm_read_I_ULONG(modreader); mh->numord=_mm_read_I_UWORD(modreader); mh->numsmp=_mm_read_I_UWORD(modreader); mh->numpat=_mm_read_I_UWORD(modreader); mh->numtrk=_mm_read_I_UWORD(modreader); mh->globalvol=_mm_read_UBYTE(modreader); mh->mastervol=_mm_read_UBYTE(modreader); mh->speed=_mm_read_UBYTE(modreader); mh->bpm=_mm_read_UBYTE(modreader); _mm_read_UBYTES(mh->panpos,DSM_MAXCHAN,modreader); _mm_read_UBYTES(mh->orders,DSM_MAXORDERS,modreader); /* set module variables */ of.initspeed=mh->speed; of.inittempo=mh->bpm; of.modtype=strdup(DSM_Version); of.numchn=mh->numtrk; of.numpat=mh->numpat; of.numtrk=of.numchn*of.numpat; of.songname=DupStr(mh->songname,28,1); /* make a cstr of songname */ of.reppos=0; of.flags |= UF_PANNING; /* XXX whenever possible, we should try to determine the original format. Here we assume it was S3M-style wrt bpmlimit... */ of.bpmlimit = 32; for(t=0;t<DSM_MAXCHAN;t++) of.panning[t]=mh->panpos[t]==DSM_SURROUND?PAN_SURROUND: mh->panpos[t]<0x80?(mh->panpos[t]<<1):255; if(!AllocPositions(mh->numord)) return 0; of.numpos=0; for(t=0;t<mh->numord;t++) { int order=mh->orders[t]; if(order==255) order=LAST_PATTERN; of.positions[of.numpos]=order; if(mh->orders[t]<254) of.numpos++; } of.numins=of.numsmp=mh->numsmp; if(!AllocSamples()) return 0; if(!AllocTracks()) return 0; if(!AllocPatterns()) return 0; while(cursmp<of.numins||curpat<of.numpat) { if(!GetBlockHeader()) return 0; if(!memcmp(blockid,INSTID,4) && cursmp<of.numins) { q=&of.samples[cursmp]; /* try to read sample info */ _mm_read_UBYTES(s.filename,13,modreader); s.flags=_mm_read_I_UWORD(modreader); s.volume=_mm_read_UBYTE(modreader); s.length=_mm_read_I_ULONG(modreader); s.loopstart=_mm_read_I_ULONG(modreader); s.loopend=_mm_read_I_ULONG(modreader); s.reserved1=_mm_read_I_ULONG(modreader); s.c2spd=_mm_read_I_UWORD(modreader); s.period=_mm_read_I_UWORD(modreader); _mm_read_UBYTES(s.samplename,28,modreader); q->samplename=DupStr(s.samplename,28,1); q->seekpos=_mm_ftell(modreader); q->speed=s.c2spd; q->length=s.length; q->loopstart=s.loopstart; q->loopend=s.loopend; q->volume=s.volume; if(s.flags&1) q->flags|=SF_LOOP; if(s.flags&2) q->flags|=SF_SIGNED; /* (s.flags&4) means packed sample, but did they really exist in dsm ?*/ cursmp++; } else if(!memcmp(blockid,PATTID,4) && curpat<of.numpat) { DSM_ReadPattern(); for(t=0;t<of.numchn;t++) if(!(of.tracks[track++]=DSM_ConvertTrack(&dsmbuf[t*64]))) return 0; curpat++; } } return 1;}CHAR *DSM_LoadTitle(void){ CHAR s[28]; _mm_fseek(modreader,12,SEEK_SET); if(!_mm_read_UBYTES(s,28,modreader)) return NULL; return(DupStr(s,28,1));}/*========== Loader information */MIKMODAPI MLOADER load_dsm={ NULL, "DSM", "DSM (DSIK internal format)", DSM_Init, DSM_Test, DSM_Load, DSM_Cleanup, DSM_LoadTitle};/* ex:set ts=4: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -