diff options
Diffstat (limited to 'plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h')
-rw-r--r-- | plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h b/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h new file mode 100644 index 00000000..98171d73 --- /dev/null +++ b/plugins/sid/sidplay-libs/libsidplay/src/xsid/xsid.h @@ -0,0 +1,288 @@ +/*************************************************************************** + xsid.h - Support for Playsids Extended + Registers + ------------------- + begin : Tue Jun 20 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: xsid.h,v $ + * Revision 1.21 2002/09/23 19:42:52 s_a_white + * Fixed intel compiler warnings. + * + * Revision 1.20 2002/07/17 19:18:17 s_a_white + * Changed bad #if to #ifdef + * + * Revision 1.19 2002/02/21 20:26:13 s_a_white + * Nolonger default to Galway Mode when Noise samples init incorrectly. Fixes + * VARIOUS/S-Z/Zyron/Bouncy_Balls.sid (HVSC). + * + * Revision 1.18 2002/02/17 16:34:39 s_a_white + * New reset interface + * + * Revision 1.17 2001/11/16 19:22:04 s_a_white + * Removed compiler warning for unused parameter. + * + * Revision 1.16 2001/10/18 22:36:16 s_a_white + * GCC3 fixes. + * + * Revision 1.15 2001/07/14 16:48:35 s_a_white + * Sync with sidbuilder class project. + * + * Revision 1.14 2001/07/14 12:59:39 s_a_white + * XSID effeciency increased. Now uses new component classes and event + * generation. + * + * Revision 1.13 2001/04/20 22:21:06 s_a_white + * inlined updateSidData0x18. + * + * Revision 1.12 2001/03/25 19:51:23 s_a_white + * Performance update. + * + * Revision 1.11 2001/03/19 23:40:46 s_a_white + * Better support for global debug. + * + * Revision 1.10 2001/03/09 22:27:13 s_a_white + * Speed optimisation update. + * + * Revision 1.9 2001/03/01 23:45:58 s_a_white + * Combined both through sid and non-through sid modes. Can be selected + * at runtime now. + * + * Revision 1.8 2001/02/21 21:46:34 s_a_white + * 0x1d = 0 now fixed. Limit checking on sid volume. This helps us determine + * even better what the sample offset should be (fixes Skate and Die). + * + * Revision 1.7 2001/02/07 21:02:30 s_a_white + * Supported for delaying samples for frame simulation. New alogarithm to + * better guess original tunes volume when playing samples. + * + * Revision 1.6 2000/12/12 22:51:01 s_a_white + * Bug Fix #122033. + * + ***************************************************************************/ + +/* +Effectively there is only 1 channel, which can either perform Galway Noise +or Sampling. However, to achieve all the effects on a C64, 2 sampling +channels are required. No divide by 2 is required and is compensated for +automatically in the C64 machine code. + +Confirmed by Warren Pilkington using the tune Turbo Outrun: +A new sample must interrupt an existing sample running on the same channel. + +Confirmed by Michael Schwendt and Antonia Vera using the tune Game Over: +A Galway Sample or Noise sequence cannot interrupt any other. However +the last of these new requested sequences will be played after the current +sequence ends. + +Lastly playing samples through the SIDs volume is not as clean as playing +them on their own channel. Playing through the SID will effect the volume +of the other channels and this will be most noticable at low frequencies. +These effects are however present in the original SID music. + +Some SIDs put values directly into the volume register. Others play samples +with respect to the current volume. We can't for definate know which the author +has chosen originally. We must just make a guess based on what the volume +is initially at the start of a sample sequence and from the details xSID has been +programmed with. +*/ + +#ifndef _xsid_h_ +#define _xsid_h_ + +#include "config.h" +#include "sidbuilder.h" +#include "event.h" + +// XSID configuration settings +//#define XSID_DEBUG 1 + +// Support global debug option +#ifdef DEBUG +# ifndef XSID_DEBUG +# define XSID_DEBUG DEBUG +# endif +#endif + +#ifdef XSID_DEBUG +# include <stdio.h> +#endif + +class XSID; +class channel +{ +private: + // General + const char * const m_name; + EventContext &m_context; + XSID &m_xsid; + friend class XSID; + + class SampleEvent: public Event + { + private: + channel &m_ch; + void event (void) { m_ch.sampleClock (); } + + public: + SampleEvent (channel *ch) + :Event("xSID Sample"), + m_ch(*ch) {} + } sampleEvent; + friend class SampleEvent; + + class GalwayEvent: public Event + { + private: + channel &m_ch; + void event (void) { m_ch.galwayClock (); } + + public: + GalwayEvent (channel *ch) + :Event("xSID Galway"), + m_ch(*ch) {} + } galwayEvent; + friend class GalwayEvent; + + uint8_t reg[0x10]; + enum {FM_NONE = 0, FM_HUELS, FM_GALWAY} mode; + bool active; + uint_least16_t address; + uint_least16_t cycleCount; // Counts to zero and triggers! + uint_least8_t volShift; + uint_least8_t sampleLimit; + int8_t sample; + + // Sample Section + uint_least8_t samRepeat; + uint_least8_t samScale; + enum {SO_LOWHIGH = 0, SO_HIGHLOW = 1}; + uint_least8_t samOrder; + uint_least8_t samNibble; + uint_least16_t samEndAddr; + uint_least16_t samRepeatAddr; + uint_least16_t samPeriod; + + // Galway Section + uint_least8_t galTones; + uint_least8_t galInitLength; + uint_least8_t galLength; + uint_least8_t galVolume; + uint_least8_t galLoopWait; + uint_least8_t galNullWait; + + // For Debugging + event_clock_t cycles; + event_clock_t outputs; + +private: + channel (const char * const name, EventContext *context, XSID *xsid); + void free (void); + void silence (void); + void sampleInit (void); + void sampleClock (void); + void galwayInit (void); + void galwayClock (void); + + // Compress address to not leave so many spaces + uint_least8_t convertAddr(uint_least8_t addr) + { return (((addr) & 0x3) | ((addr) >> 3) & 0x0c); } + + void reset (void); + uint8_t read (uint_least8_t addr) + { return reg[convertAddr (addr)]; } + void write (uint_least8_t addr, uint8_t data) + { reg[convertAddr (addr)] = data; } + int8_t output (void); + bool isGalway (void) + { return mode == FM_GALWAY; } + + uint_least8_t limit (void) + { return sampleLimit; } + + inline void checkForInit (void); + inline int8_t sampleCalculate (void); + inline void galwayTonePeriod (void); + + // Used to indicate if channel is running + operator bool() const { return (active); } +}; + + +class XSID: public sidemu, private Event +{ + friend class channel; + +private: + channel ch4; + channel ch5; + bool muted; + bool suppressed; + static const char *credit; + + uint8_t sidData0x18; + bool _sidSamples; + int8_t sampleOffset; + static const int8_t sampleConvertTable[16]; + bool wasRunning; + +private: + void event (void); + void checkForInit (channel *ch); + inline void setSidData0x18 (void); + inline void recallSidData0x18 (void); + int8_t sampleOutput (void); + void sampleOffsetCalc (void); + virtual uint8_t readMemByte (uint_least16_t addr) = 0; + virtual void writeMemByte (uint8_t data) = 0; + +public: + XSID (EventContext *context); + + // Standard calls + void reset () { sidemu::reset (); } + void reset (uint8_t); + uint8_t read (uint_least8_t) { return 0; } + void write (uint_least8_t, uint8_t) { ; } + const char *credits (void) {return credit;} + + // Specialist calls + uint8_t read (uint_least16_t) { return 0; } + void write (uint_least16_t addr, uint8_t data); + int_least32_t output (uint_least8_t bits = 16); + void mute (bool enable); + bool isMuted (void) { return muted; } + void suppress (bool enable); + + void sidSamples (bool enable) + { _sidSamples = enable; } + // Return whether we care it was changed. + bool storeSidData0x18 (uint8_t data); +}; + + +/*************************************************************************** + * Inline functions + **************************************************************************/ + +inline int_least32_t XSID::output (uint_least8_t bits) +{ + int_least32_t sample; + if (_sidSamples || muted) + return 0; + sample = sampleConvertTable[sampleOutput () + 8]; + return sample << (bits - 8); +} + +#endif // _xsid_h_ |