1 /*
2  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * sng.cpp - SNG Player by Simon Peter <dn.tlp@gmx.net>
20  */
21 
22 #include <string.h>
23 #include "sng.h"
24 
factory(Copl * newopl)25 CPlayer *CsngPlayer::factory(Copl *newopl)
26 {
27   return new CsngPlayer(newopl);
28 }
29 
load(const char * filename,const CFileProvider & fp)30 bool CsngPlayer::load(const char *filename, const CFileProvider &fp)
31 {
32   binistream *f = fp.open(filename); if(!f) return false;
33   int i;
34 
35   // load header
36   f->readString(header.id, 4);
37   header.length = f->readInt(2); header.start = f->readInt(2);
38   header.loop = f->readInt(2); header.delay = f->readInt(1);
39   header.compressed = f->readInt(1) ? true : false;
40 
41   // file validation section
42   if(strncmp(header.id,"ObsM",4)) { fp.close(f); return false; }
43 
44   // load section
45   header.length /= 2; header.start /= 2; header.loop /= 2;
46   data = new Sdata [header.length];
47   for(i = 0; i < header.length; i++) {
48     data[i].val = f->readInt(1);
49     data[i].reg = f->readInt(1);
50   }
51 
52   rewind(0);
53   fp.close(f);
54   return true;
55 }
56 
update()57 bool CsngPlayer::update()
58 {
59   if(header.compressed && del) {
60     del--;
61     return !songend;
62   }
63 
64   while(data[pos].reg) {
65     opl->write(data[pos].reg, data[pos].val);
66     pos++;
67     if(pos >= header.length) {
68       songend = true;
69       pos = header.loop;
70     }
71   }
72 
73   if(!header.compressed)
74     opl->write(data[pos].reg, data[pos].val);
75 
76   if(data[pos].val) del = data[pos].val - 1; pos++;
77   if(pos >= header.length) { songend = true; pos = header.loop; }
78   return !songend;
79 }
80 
rewind(int subsong)81 void CsngPlayer::rewind(int subsong)
82 {
83   pos = header.start; del = header.delay; songend = false;
84   opl->init(); opl->write(1,32);	// go to OPL2 mode
85 }
86