1 /*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2012-2014 Leandro Nini <drfiemost@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include <fcntl.h>
22 #include <sys/soundcard.h>
23 #include <sys/ioctl.h>
24 #include <unistd.h>
25
26 #include <stdlib.h>
27 #include <cstring>
28
29 #include <fstream>
30 #include <memory>
31 #include <vector>
32 #include <iostream>
33
34 #include <sidplayfp/sidplayfp.h>
35 #include <sidplayfp/SidTune.h>
36 #include <sidplayfp/SidInfo.h>
37 #include <sidplayfp/builders/residfp.h>
38
39 /**
40 * Compile with
41 * g++ `pkg-config --cflags libsidplayfp` `pkg-config --libs libsidplayfp` demo.cpp
42 */
43
44 /*
45 * Adjust these paths to point to existing ROM dumps if needed.
46 */
47 #define KERNAL_PATH ""
48 #define BASIC_PATH ""
49 #define CHARGEN_PATH ""
50
51 #define SAMPLERATE 48000
52
53 /*
54 * Load ROM dump from file.
55 * Allocate the buffer if file exists, otherwise return 0.
56 */
loadRom(const char * path,size_t romSize)57 char* loadRom(const char* path, size_t romSize)
58 {
59 char* buffer = 0;
60 std::ifstream is(path, std::ios::binary);
61 if (is.good())
62 {
63 buffer = new char[romSize];
64 is.read(buffer, romSize);
65 }
66 is.close();
67 return buffer;
68 }
69
70 /*
71 * Sample application that shows how to use libsidplayfp
72 * to play a SID tune from a file.
73 * It uses OSS for audio output.
74 */
main(int argc,char * argv[])75 int main(int argc, char* argv[])
76 {
77 sidplayfp m_engine;
78
79 { // Load ROM files
80 char *kernal = loadRom(KERNAL_PATH, 8192);
81 char *basic = loadRom(BASIC_PATH, 8192);
82 char *chargen = loadRom(CHARGEN_PATH, 4096);
83
84 m_engine.setRoms((const uint8_t*)kernal, (const uint8_t*)basic, (const uint8_t*)chargen);
85
86 delete [] kernal;
87 delete [] basic;
88 delete [] chargen;
89 }
90
91 // Set up a SID builder
92 std::auto_ptr<ReSIDfpBuilder> rs(new ReSIDfpBuilder("Demo"));
93
94 // Get the number of SIDs supported by the engine
95 unsigned int maxsids = (m_engine.info ()).maxsids();
96
97 // Create SID emulators
98 rs->create(maxsids);
99
100 // Check if builder is ok
101 if (!rs->getStatus())
102 {
103 std::cerr << rs->error() << std::endl;
104 return -1;
105 }
106
107 // Load tune from file
108 std::auto_ptr<SidTune> tune(new SidTune(argv[1]));
109
110 // CHeck if the tune is valid
111 if (!tune->getStatus())
112 {
113 std::cerr << tune->statusString() << std::endl;
114 return -1;
115 }
116
117 // Select default song
118 tune->selectSong(0);
119
120 // Configure the engine
121 SidConfig cfg;
122 cfg.frequency = SAMPLERATE;
123 cfg.samplingMethod = SidConfig::INTERPOLATE;
124 cfg.fastSampling = false;
125 cfg.playback = SidConfig::MONO;
126 cfg.sidEmulation = rs.get();
127 if (!m_engine.config(cfg))
128 {
129 std::cerr << m_engine.error() << std::endl;
130 return -1;
131 }
132
133 // Load tune into engine
134 if (!m_engine.load(tune.get()))
135 {
136 std::cerr << m_engine.error() << std::endl;
137 return -1;
138 }
139
140 // Setup audio device
141 int handle=::open("/dev/dsp", O_WRONLY, 0);
142 int format=AFMT_S16_LE;
143 ioctl(handle, SNDCTL_DSP_SETFMT, &format);
144 int chn=1;
145 ioctl(handle, SNDCTL_DSP_CHANNELS, &chn);
146 int sampleRate=SAMPLERATE;
147 ioctl(handle, SNDCTL_DSP_SPEED, &sampleRate);
148 int bufferSize;
149 ioctl(handle, SNDCTL_DSP_GETBLKSIZE, &bufferSize);
150
151 int bufferSamples = bufferSize / sizeof(short);
152
153 // Play
154 std::vector<short> buffer(bufferSamples);
155 for (int i=0; i<1000; i++)
156 {
157 m_engine.play(&buffer.front(), bufferSamples);
158 ::write(handle, &buffer.front(), bufferSize);
159 }
160
161 ::close(handle);
162 }
163