1 //
2 // /home/ms/source/sidplay/libsidplay/RCS/player.cpp,v
3 //
4
5 #include "player.h"
6 #include "myendian.h"
7 #include "6510_.h"
8
9 extern ubyte playRamRom; // MPU bank-switch setting for player call
10
11 // These texts are used to override the sidtune settings.
12 static const char text_PAL_VBI[] = "50 Hz VBI (PAL)";
13 static const char text_PAL_CIA[] = "CIA 1 Timer A (PAL)";
14 static const char text_NTSC_VBI[] = "60 Hz VBI (NTSC)";
15 static const char text_NTSC_CIA[] = "CIA 1 Timer A (NTSC)";
16
17 static const int FREQ_VBI_PAL = 50; // Hz
18 static const int FREQ_VBI_NTSC = 60; //
19
20 // Table used to check sidtune for usage of PlaySID digis.
21 static const uword c64addrTable[] =
22 {
23 // PlaySID extended SID registers (0xd49d left out).
24 //0xd41d, 0xd41e, 0xd41f, // SID is too often written to as 32 bytes!
25 0xd43d, 0xd43e, 0xd43f,
26 0xd45d, 0xd45e, 0xd45f, 0xd47d, 0xd47e, 0xd47f,
27 //0xd51d, 0xd51e, 0xd51f, // SID is too often written to as 32 bytes!
28 0xd53d, 0xd53e, 0xd53f,
29 0xd55d, 0xd55e, 0xd55f, 0xd57d, 0xd57e, 0xd57f
30 };
31 // Number of addresses in c64addrTable[].
32 static const int numberOfC64addr = sizeof(c64addrTable) / sizeof(uword);
33 static ubyte oldValues[numberOfC64addr];
34
35
sidEmuInitializeSong(emuEngine & thisEmuEngine,sidTune & thisTune,uword songNumber)36 bool sidEmuInitializeSong(emuEngine & thisEmuEngine,
37 sidTune & thisTune,
38 uword songNumber)
39 {
40 // Do a regular song initialization.
41 bool ret = sidEmuInitializeSongOld(thisEmuEngine,thisTune,songNumber);
42 if (ret && (thisEmuEngine.config.digiPlayerScans!=0))
43 {
44 // Run the music player for a couple of player calls and check for
45 // changes in the PlaySID extended SID registers. If no digis are
46 // used, apply a higher amplification on each SID voice. First
47 // check also covers writings of the player INIT routine. Old values
48 // are stored before song INIT.
49 bool useDigis = false;
50 int loops = thisEmuEngine.config.digiPlayerScans;
51 while (loops)
52 {
53 for (int i = 0; i < numberOfC64addr; i++)
54 {
55 if (oldValues[i] != c64mem2[c64addrTable[i]])
56 {
57 useDigis = true;
58 break;
59 }
60 oldValues[i] = c64mem2[c64addrTable[i]];
61 }
62 if (useDigis)
63 {
64 break;
65 }
66 uword replayPC = thisTune.getPlayAddr();
67 // playRamRom was set by sidEmuInitializeSongOld(..).
68 if ( replayPC == 0 )
69 {
70 playRamRom = c64mem1[1];
71 if ((playRamRom & 2) != 0) // isKernal?
72 {
73 replayPC = readLEword(c64mem1+0x0314); // IRQ
74 }
75 else
76 {
77 replayPC = readLEword(c64mem1+0xfffe); // NMI
78 }
79 }
80 interpreter(replayPC,playRamRom,0,0,0);
81 loops--;
82 };
83 thisEmuEngine.amplifyThreeVoiceTunes(!useDigis);
84 // Here re-init song to start at beginning.
85 ret = sidEmuInitializeSongOld(thisEmuEngine,thisTune,songNumber);
86 }
87 return ret;
88 }
89
90
sidEmuInitializeSongOld(emuEngine & thisEmuEngine,sidTune & thisTune,uword songNumber)91 bool sidEmuInitializeSongOld(emuEngine & thisEmuEngine,
92 sidTune & thisTune,
93 uword songNumber)
94 {
95 if (!thisEmuEngine.isReady || !thisTune.status )
96 {
97 return false;
98 }
99 else
100 {
101 // ------------------------------------------- Determine clock/speed.
102
103 // Get speed/clock setting for song and preselect
104 // speed/clock descriptions strings, reg = song init akkumulator.
105 ubyte reg = thisTune.selectSong(songNumber) -1;
106
107 const char* the_description;
108
109 ubyte the_clock = thisTune.info.clockSpeed;
110 // Choose clock speed emu user prefers. If sidtune doesn't
111 // contain clock speed setting (=0), use emu setting.
112 if ( the_clock == SIDTUNE_CLOCK_ANY )
113 the_clock &= thisEmuEngine.config.clockSpeed;
114 else if ( !the_clock )
115 the_clock = thisEmuEngine.config.clockSpeed;
116
117 ubyte the_speed = thisTune.info.songSpeed;
118
119 if (thisEmuEngine.config.forceSongSpeed)
120 {
121 the_clock = thisEmuEngine.config.clockSpeed;
122 }
123
124 // Select speed description string.
125 if (the_clock == SIDTUNE_CLOCK_PAL)
126 {
127 if (the_speed == SIDTUNE_SPEED_VBI)
128 {
129 the_description = text_PAL_VBI;
130 }
131 else //if (thisTune.info.songSpeed == SIDTUNE_SPEED_CIA_1A)
132 {
133 the_description = text_PAL_CIA;
134 }
135 }
136 else //if (the_clock == SIDTUNE_CLOCK_NTSC)
137 {
138 if (the_speed == SIDTUNE_SPEED_VBI)
139 {
140 the_description = text_NTSC_VBI;
141 }
142 else //if (thisTune.info.songSpeed == SIDTUNE_SPEED_CIA_1A)
143 {
144 the_description = text_NTSC_CIA;
145 }
146 }
147
148 // Substitute correct VBI frequency.
149 if ((the_clock==SIDTUNE_CLOCK_PAL) &&
150 (the_speed==SIDTUNE_SPEED_VBI))
151 {
152 the_speed = FREQ_VBI_PAL;
153 }
154
155 if ((the_clock==SIDTUNE_CLOCK_NTSC) &&
156 (the_speed==SIDTUNE_SPEED_VBI))
157 {
158 the_speed = FREQ_VBI_NTSC;
159 }
160
161 // Transfer the speed settings to the emulator engine.
162 // From here on we don't touch the SID clock speed setting.
163 extern void sidEmuConfigureClock( int );
164 sidEmuConfigureClock( the_clock );
165 extern void sidEmuSetReplayingSpeed(int clockMode, uword callsPerSec); // --> 6581_.cpp
166 sidEmuSetReplayingSpeed(the_clock,the_speed);
167
168 // Make available chosen speed setting in userspace.
169 thisTune.info.clockSpeed = the_clock;
170 thisTune.info.songSpeed = the_speed;
171 thisTune.info.speedString = the_description;
172
173 // ------------------------------------------------------------------
174
175 thisEmuEngine.MPUreset();
176
177 if ( !thisTune.placeSidTuneInC64mem(thisEmuEngine.MPUreturnRAMbase()) )
178 {
179 return false;
180 }
181
182 if (thisTune.info.musPlayer)
183 {
184 thisTune.MUS_installPlayer(thisEmuEngine.MPUreturnRAMbase());
185 }
186
187 thisEmuEngine.amplifyThreeVoiceTunes(false); // assume digis are used
188 if ( !thisEmuEngine.reset() ) // currently always returns true
189 {
190 return false;
191 }
192
193 if (thisEmuEngine.config.digiPlayerScans!=0)
194 {
195 // Save the SID registers to allow later comparison.
196 for (int i = 0; i < numberOfC64addr; i++)
197 {
198 oldValues[i] = c64mem2[c64addrTable[i]];
199 }
200 }
201
202 // In PlaySID-mode the interpreter will ignore some of the parameters.
203 //bool retcode =
204 interpreter(thisTune.info.initAddr,c64memRamRom(thisTune.info.initAddr),reg,reg,reg);
205 playRamRom = c64memRamRom(thisTune.info.playAddr);
206
207 // This code is only used to be able to print out the initial IRQ address.
208 if (thisTune.info.playAddr == 0)
209 {
210 // Get the address of the interrupt handler.
211 if ((c64mem1[1] & 2) != 0) // isKernal?
212 {
213 thisTune.setIRQaddress(readEndian(c64mem1[0x0315],c64mem1[0x0314])); // IRQ
214 }
215 else
216 {
217 thisTune.setIRQaddress(readEndian(c64mem1[0xffff],c64mem1[0xfffe])); // NMI
218 }
219 }
220 else
221 {
222 thisTune.setIRQaddress(0);
223 }
224
225 #if defined(SIDEMU_TIME_COUNT)
226 thisEmuEngine.resetSecondsThisSong();
227 #endif
228 return true;
229
230 } // top else (emu&sidtune okay)
231 }
232