]> 4ch.mooo.com Git - 16.git/blob - 16/adplug/adplug/src/dro.cpp
renamed: 16/adplug/adplug-2.2.1/.DS_Store -> 16/adplug/adplug/.DS_Store
[16.git] / 16 / adplug / adplug / src / dro.cpp
1 /*
2  * Adplug - Replayer for many OPL2/OPL3 audio file formats.
3  * Copyright (C) 1999 - 2007 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  * dro.c - DOSBox Raw OPL Player by Sjoerd van der Berg <harekiet@zophar.net>
20  *
21  * upgraded by matthew gambrell <zeromus@zeromus.org>
22  * 
23  * NOTES: 3-oct-04: the DRO format is not yet finalized. beware.
24  */
25
26 #include <cstring>
27 #include <stdio.h>
28
29 #include "dro.h"
30
31 /*** public methods *************************************/
32
33 CPlayer *CdroPlayer::factory(Copl *newopl)
34 {
35   return new CdroPlayer(newopl);
36 }
37
38 CdroPlayer::CdroPlayer(Copl *newopl)
39   : CPlayer(newopl), data(0)
40 {
41   if(opl->gettype() == Copl::TYPE_OPL2)
42     opl3_mode = 0;
43   else
44     opl3_mode = 1;
45 }
46
47 bool CdroPlayer::load(const std::string &filename, const CFileProvider &fp)
48 {
49   binistream *f = fp.open(filename); if(!f) return false;
50   char id[8];
51   unsigned long i;
52
53   // file validation section
54   f->readString(id, 8);
55   if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; }
56   int version = f->readInt(4);  // not very useful just yet
57   if(version != 0x10000) { fp.close(f); return false; }
58
59   // load section
60   mstotal = f->readInt(4);      // Total milliseconds in file
61   length = f->readInt(4);       // Total data bytes in file
62   data = new unsigned char [length];
63
64   f->ignore(1);                 // Type of opl data this can contain - ignored
65   for (i=0;i<3;i++)
66         data[i]=f->readInt(1);
67
68   if ((data[0] == 0) || (data[1] == 0) || (data[2] == 0)) {
69         // Some early .DRO files only used one byte for the hardware type, then
70         // later changed to four bytes with no version number change.  If we're
71         // here then this is a later (more popular) file with the full four bytes
72         // for the hardware-type.
73         i = 0; // so ignore the three bytes we just read and start again
74   }
75   for (;i<length;i++)
76     data[i]=f->readInt(1);
77   fp.close(f);
78   rewind(0);
79   return true;
80 }
81
82 bool CdroPlayer::update()
83 {
84   if (delay>500) {
85     delay-=500;
86     return true;
87   } else
88     delay=0;
89
90   while (pos < length) {
91     unsigned char cmd = data[pos++];
92     switch(cmd) {
93     case 0: 
94       delay = 1 + data[pos++];
95       return true;
96     case 1: 
97       delay = 1 + data[pos] + (data[pos+1]<<8);
98       pos+=2;
99       return true;
100     case 2:
101       index = 0;
102       opl->setchip(0);
103       break;
104     case 3:
105       index = 1;
106       opl->setchip(1);
107       break;
108     default:
109       if(cmd==4) cmd = data[pos++]; //data override
110       if(index == 0 || opl3_mode)
111         opl->write(cmd,data[pos++]);
112       break;
113     }
114   }
115
116   return pos<length;
117 }
118
119 void CdroPlayer::rewind(int subsong)
120 {
121   delay=1; 
122   pos = index = 0; 
123   opl->init(); 
124
125   //dro assumes all registers are initialized to 0
126   //registers not initialized to 0 will be corrected
127   //in the data stream
128   for(int i=0;i<256;i++)
129     opl->write(i,0);
130         
131   opl->setchip(1);
132   for(int i=0;i<256;i++)
133     opl->write(i,0);
134   opl->setchip(0);
135 }
136
137 float CdroPlayer::getrefresh()
138 {
139   if (delay > 500) return 1000 / 500;
140   else return 1000 / (double)delay;
141 }