libsidplayfp  0.3.5
player.h
1 /***************************************************************************
2  player.h - description
3  -------------------
4  begin : Fri Jun 9 2000
5  copyright : (C) 2000 by Simon White
6  email : s_a_white@email.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 /***************************************************************************
18  * $Log: player.h,v $
19  * Revision 1.52 2004/06/26 11:02:55 s_a_white
20  * Changes to support new calling convention for event scheduler.
21  * Removed unnecessary cpu emulation.
22  *
23  * Revision 1.51 2004/05/03 22:42:56 s_a_white
24  * Change how port handling is dealt with to provide better C64 compatiiblity.
25  * Add character rom support.
26  *
27  * Revision 1.50 2004/04/13 07:40:47 s_a_white
28  * Add lightpen support.
29  *
30  * Revision 1.49 2004/03/18 20:15:15 s_a_white
31  * Added sidmapper (so support more the 2 sids).
32  *
33  * Revision 1.48 2004/01/31 17:01:44 s_a_white
34  * Add ability to specify the maximum number of sid writes forming the sid2crc.
35  *
36  * Revision 1.47 2003/12/15 23:50:37 s_a_white
37  * Fixup use of inline functions and correct mileage calculations.
38  *
39  * Revision 1.46 2003/10/16 07:42:49 s_a_white
40  * Allow redirection of debug information to file.
41  *
42  * Revision 1.45 2003/06/27 21:15:25 s_a_white
43  * Tidy up mono to stereo sid conversion, only allowing it theres sufficient
44  * support from the emulation. Allow user to override whether they want this
45  * to happen.
46  *
47  * Revision 1.44 2003/05/28 20:11:19 s_a_white
48  * Support the psiddrv overlapping unused parts of the tunes load image.
49  *
50  * Revision 1.43 2003/02/20 19:11:48 s_a_white
51  * sid2crc support.
52  *
53  * Revision 1.42 2003/01/23 17:32:39 s_a_white
54  * Redundent code removal.
55  *
56  * Revision 1.41 2003/01/20 18:37:08 s_a_white
57  * Stealing update. Apparently the cpu does a memory read from any non
58  * write cycle (whether it needs to or not) resulting in those cycles
59  * being stolen.
60  *
61  * Revision 1.40 2003/01/17 08:35:46 s_a_white
62  * Event scheduler phase support.
63  *
64  * Revision 1.39 2002/12/03 23:25:53 s_a_white
65  * Prevent PSID digis from playing in real C64 mode.
66  *
67  * Revision 1.38 2002/11/27 00:16:51 s_a_white
68  * Make sure driver info gets reset and exported properly.
69  *
70  * Revision 1.37 2002/11/20 21:44:34 s_a_white
71  * Initial support for external DMA to steal cycles away from the CPU.
72  *
73  * Revision 1.36 2002/11/19 22:55:50 s_a_white
74  * PSIDv2NG/RSID changes to deal with spec updates for recommended
75  * implementation.
76  *
77  * Revision 1.35 2002/11/01 17:36:01 s_a_white
78  * Frame based support for old sidplay1 modes.
79  *
80  * Revision 1.34 2002/10/02 19:45:23 s_a_white
81  * RSID support.
82  *
83  * Revision 1.33 2002/09/12 21:01:31 s_a_white
84  * Added support for simulating the random delay before the user loads a
85  * program on a real C64.
86  *
87  * Revision 1.32 2002/09/09 18:01:30 s_a_white
88  * Prevent m_info driver details getting modified when C64 crashes.
89  *
90  * Revision 1.31 2002/07/21 19:39:41 s_a_white
91  * Proper error handling of reloc info overlapping load image.
92  *
93  * Revision 1.30 2002/07/20 08:34:52 s_a_white
94  * Remove unnecessary and pointless conts.
95  *
96  * Revision 1.29 2002/07/17 21:48:10 s_a_white
97  * PSIDv2NG reloc exclude region extension.
98  *
99  * Revision 1.28 2002/04/14 21:46:50 s_a_white
100  * PlaySID reads fixed to come from RAM only.
101  *
102  * Revision 1.27 2002/03/12 18:43:59 s_a_white
103  * Tidy up handling of envReset on illegal CPU instructions.
104  *
105  * Revision 1.26 2002/03/03 22:01:58 s_a_white
106  * New clock speed & sid model interface.
107  *
108  * Revision 1.25 2002/01/29 21:50:33 s_a_white
109  * Auto switching to a better emulation mode. m_tuneInfo reloaded after a
110  * config. Initial code added to support more than two sids.
111  *
112  * Revision 1.24 2002/01/28 19:32:01 s_a_white
113  * PSID sample improvements.
114  *
115  * Revision 1.23 2001/12/13 08:28:08 s_a_white
116  * Added namespace support to fix problems with xsidplay.
117  *
118  * Revision 1.22 2001/10/18 22:34:04 s_a_white
119  * GCC3 fixes.
120  *
121  * Revision 1.21 2001/10/02 18:26:36 s_a_white
122  * Removed ReSID support and updated for new scheduler.
123  *
124  * Revision 1.20 2001/09/20 19:32:39 s_a_white
125  * Support for a null sid emulation to use when a builder create call fails.
126  *
127  * Revision 1.19 2001/09/17 19:02:38 s_a_white
128  * Now uses fixed point maths for sample output and rtc.
129  *
130  * Revision 1.18 2001/09/01 11:15:46 s_a_white
131  * Fixes sidplay1 environment modes.
132  *
133  * Revision 1.17 2001/08/10 21:01:06 s_a_white
134  * Fixed RTC initialisation order warning.
135  *
136  * Revision 1.16 2001/08/10 20:03:19 s_a_white
137  * Added RTC reset.
138  *
139  * Revision 1.15 2001/07/25 17:01:13 s_a_white
140  * Support for new configuration interface.
141  *
142  * Revision 1.14 2001/07/14 16:46:16 s_a_white
143  * Sync with sidbuilder class project.
144  *
145  * Revision 1.13 2001/07/14 12:50:58 s_a_white
146  * Support for credits and debuging. External filter selection removed. RTC
147  * and samples obtained in a more efficient way. Support for component
148  * and sidbuilder classes.
149  *
150  * Revision 1.12 2001/04/23 17:09:56 s_a_white
151  * Fixed video speed selection using unforced/forced and NTSC clockSpeeds.
152  *
153  * Revision 1.11 2001/03/22 22:45:20 s_a_white
154  * Re-ordered initialisations to match defintions.
155  *
156  * Revision 1.10 2001/03/21 23:28:12 s_a_white
157  * Support new component names.
158  *
159  * Revision 1.9 2001/03/21 22:32:55 s_a_white
160  * Filter redefinition support. VIC & NMI support added.
161  *
162  * Revision 1.8 2001/03/08 22:48:33 s_a_white
163  * Sid reset on player destruction removed. Now handled locally by the sids.
164  *
165  * Revision 1.7 2001/03/01 23:46:37 s_a_white
166  * Support for sample mode to be selected at runtime.
167  *
168  * Revision 1.6 2001/02/28 18:52:55 s_a_white
169  * Removed initBank* related stuff.
170  *
171  * Revision 1.5 2001/02/21 21:41:51 s_a_white
172  * Added seperate ram bank to hold C64 player.
173  *
174  * Revision 1.4 2001/02/07 20:56:46 s_a_white
175  * Samples now delayed until end of simulated frame.
176  *
177  * Revision 1.3 2001/01/23 21:26:28 s_a_white
178  * Only way to load a tune now is by passing in a sidtune object. This is
179  * required for songlength database support.
180  *
181  * Revision 1.2 2001/01/07 15:58:37 s_a_white
182  * SID2_LIB_API now becomes a core define (SID_API).
183  *
184  * Revision 1.1 2000/12/12 19:15:40 s_a_white
185  * Renamed from sidplayer
186  *
187  ***************************************************************************/
188 
189 #ifndef _player_h_
190 #define _player_h_
191 
192 #include "sid2types.h"
193 #include "SidTune.h"
194 #include "sidbuilder.h"
195 
196 #include "sidenv.h"
197 #include "c64env.h"
198 #include "c64/c64xsid.h"
199 #include "c64/c64cia.h"
200 #include "c64/c64vic.h"
201 
202 #include "mos6510/mos6510.h"
203 #include "sid6526/sid6526.h"
204 #include "nullsid.h"
205 
206 
207 #ifdef HAVE_CONFIG_H
208 # include "config.h"
209 #endif
210 
211 #ifdef PC64_TESTSUITE
212 # include <string.h>
213 #endif
214 
215 #define SID2_MAX_SIDS 2
216 #define SID2_MAPPER_SIZE 32
217 
218 SIDPLAY2_NAMESPACE_START
219 
220 class Player: public C64Environment, private c64env
221 {
222 private:
223  static const double CLOCK_FREQ_NTSC;
224  static const double CLOCK_FREQ_PAL;
225  static const double VIC_FREQ_PAL;
226  static const double VIC_FREQ_NTSC;
227 
228  static const char TXT_PAL_VBI[];
229  static const char TXT_PAL_VBI_FIXED[];
230  static const char TXT_PAL_CIA[];
231  static const char TXT_PAL_UNKNOWN[];
232  static const char TXT_NTSC_VBI[];
233  static const char TXT_NTSC_VBI_FIXED[];
234  static const char TXT_NTSC_CIA[];
235  static const char TXT_NTSC_UNKNOWN[];
236  static const char TXT_NA[];
237 
238  static const char ERR_CONF_WHILST_ACTIVE[];
239  static const char ERR_UNSUPPORTED_FREQ[];
240  static const char ERR_UNSUPPORTED_PRECISION[];
241  static const char ERR_MEM_ALLOC[];
242  static const char ERR_UNSUPPORTED_MODE[];
243  static const char *credit[10]; // 10 credits max
244 
245  static const char ERR_PSIDDRV_NO_SPACE[];
246  static const char ERR_PSIDDRV_RELOC[];
247 
248  EventScheduler m_scheduler;
249 
250  //SID6510 cpu(6510, "Main CPU");
251  SID6510 cpu;
252  // Sid objects to use.
253  NullSID nullsid;
254  c64xsid xsid;
255  c64cia1 cia;
256  c64cia2 cia2;
257  SID6526 sid6526;
258  c64vic vic;
259  sidemu *sid[SID2_MAX_SIDS];
260  int m_sidmapper[32]; // Mapping table in d4xx-d7xx
261 
262  EventCallback<Player> m_mixerEvent;
263 
264  // User Configuration Settings
265  SidTuneInfo m_tuneInfo;
266  SidTune *m_tune;
267  uint8_t *m_ram, *m_rom;
268  sid2_info_t m_info;
269  sid2_config_t m_cfg;
270 
271  const char *m_errorString;
272  int m_fastForwardFactor;
273  uint_least32_t m_mileage;
274  int_least32_t m_leftVolume;
275  int_least32_t m_rightVolume;
276  volatile sid2_player_t m_playerState;
277  volatile bool m_running;
278  int m_rand;
279  uint_least32_t m_sid2crc;
280  uint_least32_t m_sid2crcCount;
281 
282  float64_t m_cpuFreq;
283 
284  // Mixer settings
285  uint_least32_t m_sampleCount;
286  uint_least32_t m_sampleIndex;
287  short *m_sampleBuffer;
288 
289  // C64 environment settings
290  struct
291  {
292  uint8_t pr_out;
293  uint8_t ddr;
294  uint8_t pr_in;
295  } m_port;
296 
297  uint8_t m_playBank;
298 
299  // temp stuff -------------
300  bool isKernal;
301  bool isBasic;
302  bool isIO;
303  bool isChar;
304  void evalBankSelect (const uint8_t data);
305  // ------------------------
306 
307 private:
308  float64_t clockSpeed (sid2_clock_t clock, sid2_clock_t defaultClock,
309  const bool forced);
310  int environment (sid2_env_t env);
311  void fakeIRQ (void);
312  int initialise (void);
313  void mixer (void);
314  void mixerReset (void);
315  void mileageCorrect (void);
316  int sidCreate (sidbuilder *builder, sid2_model_t model,
317  sid2_model_t defaultModel);
318  void sidSamples (const bool enable);
319  void reset ();
320  uint8_t iomap (const uint_least16_t addr);
321  sid2_model_t getModel(const int sidModel,
322  sid2_model_t userModel,
323  sid2_model_t defaultModel);
324 
325  uint8_t readMemByte_plain (const uint_least16_t addr);
326  uint8_t readMemByte_io (const uint_least16_t addr);
327  uint8_t readMemByte_sidplaytp (const uint_least16_t addr);
328  uint8_t readMemByte_sidplaybs (const uint_least16_t addr);
329  void writeMemByte_plain (const uint_least16_t addr, const uint8_t data);
330  void writeMemByte_playsid (const uint_least16_t addr, const uint8_t data);
331  void writeMemByte_sidplay (const uint_least16_t addr, const uint8_t data);
332 
333  // Use pointers to please requirements of all the provided
334  // environments.
335  uint8_t (Player::*m_readMemByte) (const uint_least16_t);
336  void (Player::*m_writeMemByte) (const uint_least16_t, const uint8_t);
337  uint8_t (Player::*m_readMemDataByte)(const uint_least16_t);
338 
339  uint8_t readMemRamByte (const uint_least16_t addr)
340  { return m_ram[addr]; }
341  void sid2crc (const uint8_t data);
342 
343  // Environment Function entry Points
344  void envReset (const bool safe);
345  void envReset (void) { envReset (true); }
346  inline uint8_t envReadMemByte (const uint_least16_t addr);
347  inline void envWriteMemByte (const uint_least16_t addr, const uint8_t data);
348  bool envCheckBankJump (const uint_least16_t addr);
349  inline uint8_t envReadMemDataByte (const uint_least16_t addr);
350  inline void envSleep (void);
351 
352 #ifdef PC64_TESTSUITE
353  void envLoadFile (const char *file)
354  {
355  char name[0x100] = PC64_TESTSUITE;
356  strcat (name, file);
357  strcat (name, ".prg");
358 
359  m_tune->load (name);
360  stop ();
361  }
362 #endif
363 
364  // Rev 2.0.3 Added - New Mixer Routines
365  uint_least32_t (Player::*output) (char *buffer);
366 
367  inline void interruptIRQ (const bool state);
368  inline void interruptNMI (void);
369  inline void interruptRST (void);
370  void signalAEC (const bool state) { cpu.aecSignal (state); }
371  void lightpen () { vic.lightpen (); }
372 
373  // PSID driver
374  int psidDrvReloc (SidTuneInfo &tuneInfo, sid2_info_t &info);
375  void psidDrvInstall (sid2_info_t &info);
376  void psidRelocAddr (SidTuneInfo &tuneInfo, int startp, int endp);
377 
378 public:
379  Player ();
380  ~Player ();
381 
382  const sid2_config_t &config (void) const { return m_cfg; }
383  const sid2_info_t &info (void) const { return m_info; }
384 
385  int config (const sid2_config_t &cfg);
386  int fastForward (uint percent);
387  int load (SidTune *tune);
388  uint_least32_t mileage (void) const { return m_mileage + time(); }
389  float64_t cpuFreq (void) const { return m_cpuFreq; }
390  void pause (void);
391  uint_least32_t play (short *buffer, uint_least32_t samples);
392  sid2_player_t state (void) const { return m_playerState; }
393  void stop (void);
394  uint_least32_t time (void) const {return (uint_least32_t)(context().getTime(EVENT_CLOCK_PHI1) / m_cpuFreq); }
395  void debug (bool enable, FILE *out)
396  { cpu.debug (enable, out); }
397  void mute (int voice, bool enable);
398  const char *error (void) const { return m_errorString; }
399 };
400 
401 
402 uint8_t Player::envReadMemByte (const uint_least16_t addr)
403 { // Read from plain only to prevent execution of rom code
404  return (this->*(m_readMemByte)) (addr);
405 }
406 
407 void Player::envWriteMemByte (const uint_least16_t addr, uint8_t data)
408 { // Writes must be passed to env version.
409  (this->*(m_writeMemByte)) (addr, data);
410 }
411 
412 uint8_t Player::envReadMemDataByte (const uint_least16_t addr)
413 { // Read from plain only to prevent execution of rom code
414  return (this->*(m_readMemDataByte)) (addr);
415 }
416 
417 void Player::envSleep (void)
418 {
419  if (m_info.environment != sid2_envR)
420  { // Start the sample sequence
421  xsid.suppress (false);
422  xsid.suppress (true);
423  }
424 }
425 
426 void Player::interruptIRQ (const bool state)
427 {
428  if (state)
429  {
430  if (m_info.environment == sid2_envR)
431  cpu.triggerIRQ ();
432  else
433  fakeIRQ ();
434  }
435  else
436  cpu.clearIRQ ();
437 }
438 
439 void Player::interruptNMI ()
440 {
441  cpu.triggerNMI ();
442 }
443 
444 void Player::interruptRST ()
445 {
446  stop ();
447 }
448 
449 SIDPLAY2_NAMESPACE_STOP
450 
451 #endif // _player_h_