/*************************************************************************** player.h - description ------------------- begin : Fri Jun 9 2000 copyright : (C) 2000 by Simon White email : s_a_white@email.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /*************************************************************************** * $Log: player.h,v $ * Revision 1.39 2002/12/03 23:25:53 s_a_white * Prevent PSID digis from playing in real C64 mode. * * Revision 1.38 2002/11/27 00:16:51 s_a_white * Make sure driver info gets reset and exported properly. * * Revision 1.37 2002/11/20 21:44:34 s_a_white * Initial support for external DMA to steal cycles away from the CPU. * * Revision 1.36 2002/11/19 22:55:50 s_a_white * PSIDv2NG/RSID changes to deal with spec updates for recommended * implementation. * * Revision 1.35 2002/11/01 17:36:01 s_a_white * Frame based support for old sidplay1 modes. * * Revision 1.34 2002/10/02 19:45:23 s_a_white * RSID support. * * Revision 1.33 2002/09/12 21:01:31 s_a_white * Added support for simulating the random delay before the user loads a * program on a real C64. * * Revision 1.32 2002/09/09 18:01:30 s_a_white * Prevent m_info driver details getting modified when C64 crashes. * * Revision 1.31 2002/07/21 19:39:41 s_a_white * Proper error handling of reloc info overlapping load image. * * Revision 1.30 2002/07/20 08:34:52 s_a_white * Remove unnecessary and pointless conts. * * Revision 1.29 2002/07/17 21:48:10 s_a_white * PSIDv2NG reloc exclude region extension. * * Revision 1.28 2002/04/14 21:46:50 s_a_white * PlaySID reads fixed to come from RAM only. * * Revision 1.27 2002/03/12 18:43:59 s_a_white * Tidy up handling of envReset on illegal CPU instructions. * * Revision 1.26 2002/03/03 22:01:58 s_a_white * New clock speed & sid model interface. * * Revision 1.25 2002/01/29 21:50:33 s_a_white * Auto switching to a better emulation mode. m_tuneInfo reloaded after a * config. Initial code added to support more than two sids. * * Revision 1.24 2002/01/28 19:32:01 s_a_white * PSID sample improvements. * * Revision 1.23 2001/12/13 08:28:08 s_a_white * Added namespace support to fix problems with xsidplay. * * Revision 1.22 2001/10/18 22:34:04 s_a_white * GCC3 fixes. * * Revision 1.21 2001/10/02 18:26:36 s_a_white * Removed ReSID support and updated for new scheduler. * * Revision 1.20 2001/09/20 19:32:39 s_a_white * Support for a null sid emulation to use when a builder create call fails. * * Revision 1.19 2001/09/17 19:02:38 s_a_white * Now uses fixed point maths for sample output and rtc. * * Revision 1.18 2001/09/01 11:15:46 s_a_white * Fixes sidplay1 environment modes. * * Revision 1.17 2001/08/10 21:01:06 s_a_white * Fixed RTC initialisation order warning. * * Revision 1.16 2001/08/10 20:03:19 s_a_white * Added RTC reset. * * Revision 1.15 2001/07/25 17:01:13 s_a_white * Support for new configuration interface. * * Revision 1.14 2001/07/14 16:46:16 s_a_white * Sync with sidbuilder class project. * * Revision 1.13 2001/07/14 12:50:58 s_a_white * Support for credits and debuging. External filter selection removed. RTC * and samples obtained in a more efficient way. Support for component * and sidbuilder classes. * * Revision 1.12 2001/04/23 17:09:56 s_a_white * Fixed video speed selection using unforced/forced and NTSC clockSpeeds. * * Revision 1.11 2001/03/22 22:45:20 s_a_white * Re-ordered initialisations to match defintions. * * Revision 1.10 2001/03/21 23:28:12 s_a_white * Support new component names. * * Revision 1.9 2001/03/21 22:32:55 s_a_white * Filter redefinition support. VIC & NMI support added. * * Revision 1.8 2001/03/08 22:48:33 s_a_white * Sid reset on player destruction removed. Now handled locally by the sids. * * Revision 1.7 2001/03/01 23:46:37 s_a_white * Support for sample mode to be selected at runtime. * * Revision 1.6 2001/02/28 18:52:55 s_a_white * Removed initBank* related stuff. * * Revision 1.5 2001/02/21 21:41:51 s_a_white * Added seperate ram bank to hold C64 player. * * Revision 1.4 2001/02/07 20:56:46 s_a_white * Samples now delayed until end of simulated frame. * * Revision 1.3 2001/01/23 21:26:28 s_a_white * Only way to load a tune now is by passing in a sidtune object. This is * required for songlength database support. * * Revision 1.2 2001/01/07 15:58:37 s_a_white * SID2_LIB_API now becomes a core define (SID_API). * * Revision 1.1 2000/12/12 19:15:40 s_a_white * Renamed from sidplayer * ***************************************************************************/ #ifndef _player_h_ #define _player_h_ #include #include "config.h" #include "sidplay2.h" #include "sidenv.h" #include "c64env.h" #include "c64/c64xsid.h" #include "c64/c64cia.h" #include "c64/c64vic.h" #include "mos6510/mos6510.h" #include "sid6526/sid6526.h" #include "nullsid.h" #define SID2_MAX_SIDS 2 SIDPLAY2_NAMESPACE_START class Player: private C64Environment, c64env { private: static const double CLOCK_FREQ_NTSC; static const double CLOCK_FREQ_PAL; static const double VIC_FREQ_PAL; static const double VIC_FREQ_NTSC; static const char *TXT_PAL_VBI; static const char *TXT_PAL_VBI_FIXED; static const char *TXT_PAL_CIA; static const char *TXT_PAL_UNKNOWN; static const char *TXT_NTSC_VBI; static const char *TXT_NTSC_VBI_FIXED; static const char *TXT_NTSC_CIA; static const char *TXT_NTSC_UNKNOWN; static const char *TXT_NA; static const char *ERR_CONF_WHILST_ACTIVE; static const char *ERR_UNSUPPORTED_FREQ; static const char *ERR_UNSUPPORTED_PRECISION; static const char *ERR_MEM_ALLOC; static const char *ERR_UNSUPPORTED_MODE; static const char *credit[10]; // 10 credits max static const char *ERR_PSIDDRV_NO_SPACE; static const char *ERR_PSIDDRV_RELOC; EventScheduler m_scheduler; //SID6510 cpu(6510, "Main CPU"); SID6510 sid6510; MOS6510 mos6510; MOS6510 *cpu; // Sid objects to use. NullSID nullsid; c64xsid xsid; c64cia1 cia; c64cia2 cia2; SID6526 sid6526; c64vic vic; sidemu *sid[SID2_MAX_SIDS]; class EventMixer: public Event { private: Player &m_player; void event (void) { m_player.mixer (); } public: EventMixer (Player *player) :Event("Mixer"), m_player(*player) {} } mixerEvent; friend class EventMixer; class EventRTC: public Event { private: EventContext &m_eventContext; event_clock_t m_seconds; event_clock_t m_period; event_clock_t m_clk; void event (void) { // Fixed point 25.7 (approx 2 dp) event_clock_t cycles; m_clk += m_period; cycles = m_clk >> 7; m_clk &= 0x7F; m_seconds++; m_eventContext.schedule (this, cycles); } public: EventRTC (EventContext *context) :Event("RTC"), m_eventContext(*context), m_seconds(0) {;} event_clock_t getTime () const {return m_seconds;} void reset (void) { // Fixed point 25.7 m_seconds = 0; m_clk = m_period & 0x7F; m_eventContext.schedule (this, m_period >> 7); } void clock (float64_t period) { // Fixed point 25.7 m_period = (event_clock_t) (period / 10.0 * (float64_t) (1 << 7)); reset (); } } rtc; // User Configuration Settings SidTuneInfo m_tuneInfo; SidTune *m_tune; uint8_t *m_ram, *m_rom; sid2_info_t m_info; sid2_config_t m_cfg; const char *m_errorString; float64_t m_fastForwardFactor; uint_least32_t m_mileage; int_least32_t m_leftVolume; int_least32_t m_rightVolume; volatile sid2_player_t m_playerState; volatile bool m_running; int m_rand; // Mixer settings event_clock_t m_sampleClock; event_clock_t m_samplePeriod; uint_least32_t m_sampleCount; uint_least32_t m_sampleIndex; char *m_sampleBuffer; // C64 environment settings uint8_t m_bankReg; uint8_t m_playBank; uint_least16_t m_sidAddress[2]; // temp stuff ------------- bool isKernal; bool isBasic; bool isIO; inline void evalBankSelect (uint8_t data); void c64_initialise (void); // ------------------------ private: float64_t clockSpeed (sid2_clock_t clock, sid2_clock_t defaultClock, bool forced); int environment (sid2_env_t env); void fakeIRQ (void); int initialise (void); void nextSequence (void); void mixer (void); void mixerReset (void); void mileageCorrect (void); int sidCreate (sidbuilder *builder, sid2_model_t model, sid2_model_t defaultModel); void sidSamples (bool enable); void reset (); uint8_t iomap (uint_least16_t addr); uint8_t readMemByte_player (uint_least16_t addr); uint8_t readMemByte_plain (uint_least16_t addr); uint8_t readMemByte_io (uint_least16_t addr); uint8_t readMemByte_sidplaytp (uint_least16_t addr); uint8_t readMemByte_sidplaybs (uint_least16_t addr); void writeMemByte_plain (uint_least16_t addr, uint8_t data); void writeMemByte_playsid (uint_least16_t addr, uint8_t data); void writeMemByte_sidplay (uint_least16_t addr, uint8_t data); // Use pointers to please requirements of all the provided // environments. uint8_t (Player::*m_readMemByte) (uint_least16_t); void (Player::*m_writeMemByte) (uint_least16_t, uint8_t); uint8_t (Player::*m_readMemDataByte)(uint_least16_t); uint8_t readMemRamByte (uint_least16_t addr) { return m_ram[addr]; } // Environment Function entry Points void envReset (bool safe); inline void envReset (void) { envReset (true); } uint8_t envReadMemByte (uint_least16_t addr); inline void envWriteMemByte (uint_least16_t addr, uint8_t data); inline bool envCheckBankJump (uint_least16_t addr); inline uint8_t envReadMemDataByte (uint_least16_t addr); inline void envSleep (void); void envLoadFile (char *file) { char name[0x100] = "e:/emulators/c64/games/prgs/"; strcat (name, file); strcat (name, ".sid"); m_tune->load (name); stop (); } // Rev 2.0.3 Added - New Mixer Routines uint_least32_t (Player::*output) (char *buffer); // Rev 2.0.4 (saw) - Added to reduce code size int_least32_t monoOutGenericLeftIn (uint_least8_t bits); int_least32_t monoOutGenericStereoIn (uint_least8_t bits); int_least32_t monoOutGenericRightIn (uint_least8_t bits); // 8 bit output uint_least32_t monoOut8MonoIn (char *buffer); uint_least32_t monoOut8StereoIn (char *buffer); uint_least32_t monoOut8StereoRIn (char *buffer); uint_least32_t stereoOut8MonoIn (char *buffer); uint_least32_t stereoOut8StereoIn (char *buffer); // Rev 2.0.4 (jp) - Added 16 bit support uint_least32_t monoOut16MonoIn (char *buffer); uint_least32_t monoOut16StereoIn (char *buffer); uint_least32_t monoOut16StereoRIn (char *buffer); uint_least32_t stereoOut16MonoIn (char *buffer); uint_least32_t stereoOut16StereoIn (char *buffer); void interruptIRQ (bool state); void interruptNMI (void); void interruptRST (void); void signalBA (bool state) { cpu->rdySignal (state); } void signalAEC (bool state) { cpu->aecSignal (state); } // PSID driver int psidDrvInstall (SidTuneInfo &tuneInfo, sid2_info_t &info); void psidRelocAddr (SidTuneInfo &tuneInfo, int startp, int endp); public: Player (); const sid2_config_t &config (void) const { return m_cfg; } const sid2_info_t &info (void) const { return m_info; } int config (const sid2_config_t &cfg); int fastForward (uint percent); int load (SidTune *tune); uint_least8_t mileage (void) const { return m_mileage + time(); } void pause (void); uint_least32_t play (void *buffer, uint_least32_t length); sid2_player_t state (void) const { return m_playerState; } void stop (void); uint_least32_t time (void) const {return rtc.getTime (); } void debug (bool enable) { cpu->debug (enable); } const char *error (void) const { return m_errorString; } }; inline void Player::envSleep (void) { if (m_info.environment != sid2_envR) { // Start the sample sequence xsid.suppress (false); xsid.suppress (true); } } inline void Player::interruptIRQ (bool state) { if (state) { if (m_info.environment == sid2_envR) cpu->triggerIRQ (); else fakeIRQ (); } else cpu->clearIRQ (); } inline void Player::interruptNMI () { cpu->triggerNMI (); } inline void Player::interruptRST () { stop (); } SIDPLAY2_NAMESPACE_STOP #endif // _player_h_