diff --git a/RetroCade_Sketch/MIDI.cpp b/RetroCade_Sketch/MIDI.cpp deleted file mode 100644 index 132b91e..0000000 --- a/RetroCade_Sketch/MIDI.cpp +++ /dev/null @@ -1,1176 +0,0 @@ -/*! - * @file MIDI.cpp - * Project MIDI Library - * @brief MIDI Library for the Arduino - * @version 3.2 - * @author Francois Best - * @date 24/02/11 - * license GPL Forty Seven Effects - 2011 - */ - -#include "MIDI.h" -#include -#include "Arduino.h" // If using an old (pre-1.0) version of Arduino, use WConstants.h instead of Arduino.h -#include "HardwareSerial.h" - - //HardwareSerial Serial1(11); //This is to define Serial1 for the ZPUino. - -/*! \brief Main instance (the class comes pre-instantiated). */ -MIDI_Class MIDI; - - -/*! \brief Default constructor for MIDI_Class. */ -MIDI_Class::MIDI_Class() -{ - -#if USE_CALLBACKS - - // Initialise callbacks to NULL pointer - mNoteOffCallback = NULL; - mNoteOnCallback = NULL; - mAfterTouchPolyCallback = NULL; - mControlChangeCallback = NULL; - mProgramChangeCallback = NULL; - mAfterTouchChannelCallback = NULL; - mPitchBendCallback = NULL; - mSystemExclusiveCallback = NULL; - mTimeCodeQuarterFrameCallback = NULL; - mSongPositionCallback = NULL; - mSongSelectCallback = NULL; - mTuneRequestCallback = NULL; - mClockCallback = NULL; - mStartCallback = NULL; - mContinueCallback = NULL; - mStopCallback = NULL; - mActiveSensingCallback = NULL; - mSystemResetCallback = NULL; - -#endif - -} - - -/*! \brief Default destructor for MIDI_Class. - - This is not really useful for the Arduino, as it is never called... - */ -MIDI_Class::~MIDI_Class() -{ - -} - - -/*! \brief Call the begin method in the setup() function of the Arduino. - - All parameters are set to their default values: - - Input channel set to 1 if no value is specified - - Full thru mirroring - */ -void MIDI_Class::begin(const byte inChannel) -{ - serPortPTR = &USE_SERIAL_PORT; - // Initialise the Serial port - serPortPTR->begin(MIDI_BAUDRATE); - - -#if COMPILE_MIDI_OUT - -#if USE_RUNNING_STATUS - - mRunningStatus_TX = InvalidType; - -#endif // USE_RUNNING_STATUS - -#endif // COMPILE_MIDI_OUT - - -#if COMPILE_MIDI_IN - - mInputChannel = inChannel; - mRunningStatus_RX = InvalidType; - mPendingMessageIndex = 0; - mPendingMessageExpectedLenght = 0; - - mMessage.valid = false; - mMessage.type = InvalidType; - mMessage.channel = 0; - mMessage.data1 = 0; - mMessage.data2 = 0; - -#endif // COMPILE_MIDI_IN - - -#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru - - mThruFilterMode = Full; - mThruActivated = true; - -#endif // Thru - -} - - -#if COMPILE_MIDI_OUT - -// Private method for generating a status byte from channel and type -const byte MIDI_Class::genstatus(const kMIDIType inType, - const byte inChannel) const -{ - - return ((byte)inType | ((inChannel-1) & 0x0F)); - -} - - -/*! \brief Generate and send a MIDI message from the values given. - \param type The message type (see type defines for reference) - \param data1 The first data byte. - \param data2 The second data byte (if the message contains only 1 data byte, set this one to 0). - \param channel The output channel on which the message will be sent (values from 1 to 16). Note: you cannot send to OMNI. - - This is an internal method, use it only if you need to send raw data from your code, at your own risks. - */ -void MIDI_Class::send(kMIDIType type, - byte data1, - byte data2, - byte channel) -{ - - // Then test if channel is valid - if (channel >= MIDI_CHANNEL_OFF || channel == MIDI_CHANNEL_OMNI || type < NoteOff) { - -#if USE_RUNNING_STATUS - mRunningStatus_TX = InvalidType; -#endif - - return; // Don't send anything - } - - if (type <= PitchBend) { - // Channel messages - - // Protection: remove MSBs on data - data1 &= 0x7F; - data2 &= 0x7F; - - byte statusbyte = genstatus(type,channel); - -#if USE_RUNNING_STATUS - // Check Running Status - if (mRunningStatus_TX != statusbyte) { - // New message, memorise and send header - mRunningStatus_TX = statusbyte; - serPortPTR->write(mRunningStatus_TX); - } -#else - // Don't care about running status, send the Control byte. - serPortPTR->write(statusbyte); -#endif - - // Then send data - serPortPTR->write(data1); - if (type != ProgramChange && type != AfterTouchChannel) { - serPortPTR->write(data2); - } - return; - } - if (type >= TuneRequest && type <= SystemReset) { - // System Real-time and 1 byte. - sendRealTime(type); - } - -} - - -/*! \brief Send a Note On message - \param NoteNumber Pitch value in the MIDI format (0 to 127). Take a look at the values, names and frequencies of notes here: http://www.phys.unsw.edu.au/jw/notes.html\n - \param Velocity Note attack velocity (0 to 127). A NoteOn with 0 velocity is considered as a NoteOff. - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendNoteOn(byte NoteNumber, - byte Velocity, - byte Channel) -{ - - send(NoteOn,NoteNumber,Velocity,Channel); - -} - - -/*! \brief Send a Note Off message (a real Note Off, not a Note On with null velocity) - \param NoteNumber Pitch value in the MIDI format (0 to 127). Take a look at the values, names and frequencies of notes here: http://www.phys.unsw.edu.au/jw/notes.html\n - \param Velocity Release velocity (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendNoteOff(byte NoteNumber, - byte Velocity, - byte Channel) -{ - - send(NoteOff,NoteNumber,Velocity,Channel); - -} - - -/*! \brief Send a Program Change message - \param ProgramNumber The Program to select (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendProgramChange(byte ProgramNumber, - byte Channel) -{ - - send(ProgramChange,ProgramNumber,0,Channel); - -} - - -/*! \brief Send a Control Change message - \param ControlNumber The controller number (0 to 127). See the detailed description here: http://www.somascape.org/midi/tech/spec.html#ctrlnums - \param ControlValue The value for the specified controller (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendControlChange(byte ControlNumber, - byte ControlValue, - byte Channel) -{ - - send(ControlChange,ControlNumber,ControlValue,Channel); - -} - - -/*! \brief Send a Polyphonic AfterTouch message (applies to only one specified note) - \param NoteNumber The note to apply AfterTouch to (0 to 127). - \param Pressure The amount of AfterTouch to apply (0 to 127). - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendPolyPressure(byte NoteNumber, - byte Pressure, - byte Channel) -{ - - send(AfterTouchPoly,NoteNumber,Pressure,Channel); - -} - - -/*! \brief Send a MonoPhonic AfterTouch message (applies to all notes) - \param Pressure The amount of AfterTouch to apply to all notes. - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendAfterTouch(byte Pressure, - byte Channel) -{ - - send(AfterTouchChannel,Pressure,0,Channel); - -} - - -/*! \brief Send a Pitch Bend message using a signed integer value. - \param PitchValue The amount of bend to send (in a signed integer format), between -8192 (maximum downwards bend) and 8191 (max upwards bend), center value is 0. - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendPitchBend(int PitchValue, - byte Channel) -{ - - unsigned int bend = PitchValue + 8192; - sendPitchBend(bend,Channel); - -} - - -/*! \brief Send a Pitch Bend message using an unsigned integer value. - \param PitchValue The amount of bend to send (in a signed integer format), between 0 (maximum downwards bend) and 16383 (max upwards bend), center value is 8192. - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendPitchBend(unsigned int PitchValue, - byte Channel) -{ - - send(PitchBend,(PitchValue & 0x7F),(PitchValue >> 7) & 0x7F,Channel); - -} - - -/*! \brief Send a Pitch Bend message using a floating point value. - \param PitchValue The amount of bend to send (in a floating point format), between -1.0f (maximum downwards bend) and +1.0f (max upwards bend), center value is 0.0f. - \param Channel The channel on which the message will be sent (1 to 16). - */ -void MIDI_Class::sendPitchBend(double PitchValue, - byte Channel) -{ - - unsigned int pitchval = (PitchValue+1.f)*8192; - if (pitchval > 16383) pitchval = 16383; // overflow protection - sendPitchBend(pitchval,Channel); - -} - - -/*! \brief Generate and send a System Exclusive frame. - \param length The size of the array to send - \param array The byte array containing the data to send - \param ArrayContainsBoundaries When set to 'true', 0xF0 & 0xF7 bytes (start & stop SysEx) will NOT be sent (and therefore must be included in the array). - default value is set to 'false' for compatibility with previous versions of the library. - */ -void MIDI_Class::sendSysEx(int length, - const byte *const array, - bool ArrayContainsBoundaries) -{ - - if (ArrayContainsBoundaries == false) { - - serPortPTR->write(0xF0); - - for (int i=0;iwrite(array[i]); - - } - - serPortPTR->write(0xF7); - - } - else { - - for (int i=0;iwrite(array[i]); - - } - - } - -#if USE_RUNNING_STATUS - mRunningStatus_TX = InvalidType; -#endif - -} - - -/*! \brief Send a Tune Request message. - - When a MIDI unit receives this message, it should tune its oscillators (if equipped with any) - */ -void MIDI_Class::sendTuneRequest() -{ - - sendRealTime(TuneRequest); - -} - - -/*! \brief Send a MIDI Time Code Quarter Frame. - - See MIDI Specification for more information. - \param TypeNibble MTC type - \param ValuesNibble MTC data - */ -void MIDI_Class::sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble) -{ - - byte data = ( ((TypeNibble & 0x07) << 4) | (ValuesNibble & 0x0F) ); - sendTimeCodeQuarterFrame(data); - -} - - -/*! \brief Send a MIDI Time Code Quarter Frame. - - See MIDI Specification for more information. - \param data if you want to encode directly the nibbles in your program, you can send the byte here. - */ -void MIDI_Class::sendTimeCodeQuarterFrame(byte data) -{ - - serPortPTR->write((byte)TimeCodeQuarterFrame); - serPortPTR->write(data); - -#if USE_RUNNING_STATUS - mRunningStatus_TX = InvalidType; -#endif - -} - - -/*! \brief Send a Song Position Pointer message. - \param Beats The number of beats since the start of the song. - */ -void MIDI_Class::sendSongPosition(unsigned int Beats) -{ - - serPortPTR->write((byte)SongPosition); - serPortPTR->write(Beats & 0x7F); - serPortPTR->write((Beats >> 7) & 0x7F); - -#if USE_RUNNING_STATUS - mRunningStatus_TX = InvalidType; -#endif - -} - - -/*! \brief Send a Song Select message */ -void MIDI_Class::sendSongSelect(byte SongNumber) -{ - - serPortPTR->write((byte)SongSelect); - serPortPTR->write(SongNumber & 0x7F); - -#if USE_RUNNING_STATUS - mRunningStatus_TX = InvalidType; -#endif - -} - - -/*! \brief Send a Real Time (one byte) message. - - \param Type The available Real Time types are: Start, Stop, Continue, Clock, ActiveSensing and SystemReset. - You can also send a Tune Request with this method. - @see kMIDIType - */ -void MIDI_Class::sendRealTime(kMIDIType Type) -{ - switch (Type) { - case TuneRequest: // Not really real-time, but one byte anyway. - case Clock: - case Start: - case Stop: - case Continue: - case ActiveSensing: - case SystemReset: - serPortPTR->write((byte)Type); - break; - default: - // Invalid Real Time marker - break; - } - - // Do not cancel Running Status for real-time messages as they can be interleaved within any message. - // Though, TuneRequest can be sent here, and as it is a System Common message, it must reset Running Status. -#if USE_RUNNING_STATUS - if (Type == TuneRequest) mRunningStatus_TX = InvalidType; -#endif - -} - -#endif // COMPILE_MIDI_OUT - - - -#if COMPILE_MIDI_IN - -/*! \brief Read a MIDI message from the serial port using the main input channel (see setInputChannel() for reference). - - Returned value: true if any valid message has been stored in the structure, false if not. - A valid message is a message that matches the input channel. \n\n - If the Thru is enabled and the messages matches the filter, it is sent back on the MIDI output. - */ -bool MIDI_Class::read() -{ - serPortPTR = &USE_SERIAL_PORT; - return read(mInputChannel); - -} - -/*! \brief Read a MIDI message from the serial port using the main input channel (see setInputChannel() for reference). - - Returned value: true if any valid message has been stored in the structure, false if not. - A valid message is a message that matches the input channel. \n\n - If the Thru is enabled and the messages matches the filter, it is sent back on the MIDI output. - */ -bool MIDI_Class::read(HardwareSerial* sPort) -{ - serPortPTR = sPort; - return read(mInputChannel); - -} - - -/*! \brief Reading/thru-ing method, the same as read() with a given input channel to read on. */ -bool MIDI_Class::read(const byte inChannel) -{ - - if (inChannel >= MIDI_CHANNEL_OFF) return false; // MIDI Input disabled. - - if (parse(inChannel)) { - - if (input_filter(inChannel)) { - -#if (COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) - thru_filter(inChannel); -#endif - -#if USE_CALLBACKS - launchCallback(); -#endif - - return true; - } - - } - - return false; - -} - - -// Private method: MIDI parser -bool MIDI_Class::parse(byte inChannel) -{ - - const int bytes_available = serPortPTR->available(); - - if (bytes_available <= 0) { - // No data available. - return false; - } - - // If the buffer is full -> Don't Panic! Call the Vogons to destroy it. - if (bytes_available == 128) { - serPortPTR->flush(); - } - else { - - /* Parsing algorithm: - Get a byte from the serial buffer. - * If there is no pending message to be recomposed, start a new one. - - Find type and channel (if pertinent) - - Look for other bytes in buffer, call parser recursively, until the message is assembled or the buffer is empty. - * Else, add the extracted byte to the pending message, and check validity. When the message is done, store it. - */ - - - const byte extracted = serPortPTR->read(); - - if (mPendingMessageIndex == 0) { // Start a new pending message - mPendingMessage[0] = extracted; - - // Check for running status first - switch (getTypeFromStatusByte(mRunningStatus_RX)) { - // Only these types allow Running Status: - case NoteOff: - case NoteOn: - case AfterTouchPoly: - case ControlChange: - case ProgramChange: - case AfterTouchChannel: - case PitchBend: - - // If the status byte is not received, prepend it to the pending message - if (extracted < 0x80) { - mPendingMessage[0] = mRunningStatus_RX; - mPendingMessage[1] = extracted; - mPendingMessageIndex = 1; - } - // Else: well, we received another status byte, so the running status does not apply here. - // It will be updated upon completion of this message. - - break; - - default: - // No running status - break; - } - - - switch (getTypeFromStatusByte(mPendingMessage[0])) { - - // 1 byte messages - case Start: - case Continue: - case Stop: - case Clock: - case ActiveSensing: - case SystemReset: - case TuneRequest: - // Handle the message type directly here. - mMessage.type = getTypeFromStatusByte(mPendingMessage[0]); - mMessage.channel = 0; - mMessage.data1 = 0; - mMessage.data2 = 0; - mMessage.valid = true; - - // \fix Running Status broken when receiving Clock messages. - // Do not reset all input attributes, Running Status must remain unchanged. - //reset_input_attributes(); - - // We still need to reset these - mPendingMessageIndex = 0; - mPendingMessageExpectedLenght = 0; - - return true; - break; - - // 2 bytes messages - case ProgramChange: - case AfterTouchChannel: - case TimeCodeQuarterFrame: - case SongSelect: - mPendingMessageExpectedLenght = 2; - break; - - // 3 bytes messages - case NoteOn: - case NoteOff: - case ControlChange: - case PitchBend: - case AfterTouchPoly: - case SongPosition: - mPendingMessageExpectedLenght = 3; - break; - - case SystemExclusive: - mPendingMessageExpectedLenght = MIDI_SYSEX_ARRAY_SIZE; // As the message can be any lenght between 3 and MIDI_SYSEX_ARRAY_SIZE bytes - mRunningStatus_RX = InvalidType; - break; - - case InvalidType: - default: - // This is obviously wrong. Let's get the hell out'a here. - reset_input_attributes(); - return false; - break; - } - - // Then update the index of the pending message. - mPendingMessageIndex++; - -#if USE_1BYTE_PARSING - // Message is not complete. - return false; -#else - // Call the parser recursively - // to parse the rest of the message. - return parse(inChannel); -#endif - - } - else { - - // First, test if this is a status byte - if (extracted >= 0x80) { - - // Reception of status bytes in the middle of an uncompleted message - // are allowed only for interleaved Real Time message or EOX - switch (extracted) { - case Clock: - case Start: - case Continue: - case Stop: - case ActiveSensing: - case SystemReset: - - /* - This is tricky. Here we will have to extract the one-byte message, - pass it to the structure for being read outside the MIDI class, - and recompose the message it was interleaved into. - - Oh, and without killing the running status.. - - This is done by leaving the pending message as is, it will be completed on next calls. - */ - - mMessage.type = (kMIDIType)extracted; - mMessage.data1 = 0; - mMessage.data2 = 0; - mMessage.channel = 0; - mMessage.valid = true; - return true; - - break; - - // End of Exclusive - case 0xF7: - if (getTypeFromStatusByte(mPendingMessage[0]) == SystemExclusive) { - - // Store System Exclusive array in midimsg structure - for (byte i=0;i> 8; - - mMessage.channel = 0; - mMessage.valid = true; - - reset_input_attributes(); - - return true; - } - else { - // Well well well.. error. - reset_input_attributes(); - return false; - } - - break; - default: - break; - } - - - - } - - - // Add extracted data byte to pending message - mPendingMessage[mPendingMessageIndex] = extracted; - - - // Now we are going to check if we have reached the end of the message - if (mPendingMessageIndex >= (mPendingMessageExpectedLenght-1)) { - - // "FML" case: fall down here with an overflown SysEx.. - // This means we received the last possible data byte that can fit the buffer. - // If this happens, try increasing MIDI_SYSEX_ARRAY_SIZE. - if (getTypeFromStatusByte(mPendingMessage[0]) == SystemExclusive) { - reset_input_attributes(); - return false; - } - - - mMessage.type = getTypeFromStatusByte(mPendingMessage[0]); - mMessage.channel = (mPendingMessage[0] & 0x0F)+1; // Don't check if it is a Channel Message - - mMessage.data1 = mPendingMessage[1]; - - // Save data2 only if applicable - if (mPendingMessageExpectedLenght == 3) mMessage.data2 = mPendingMessage[2]; - else mMessage.data2 = 0; - - // Reset local variables - mPendingMessageIndex = 0; - mPendingMessageExpectedLenght = 0; - - mMessage.valid = true; - - // Activate running status (if enabled for the received type) - switch (mMessage.type) { - case NoteOff: - case NoteOn: - case AfterTouchPoly: - case ControlChange: - case ProgramChange: - case AfterTouchChannel: - case PitchBend: - // Running status enabled: store it from received message - mRunningStatus_RX = mPendingMessage[0]; - break; - - default: - // No running status - mRunningStatus_RX = InvalidType; - break; - } - return true; - } - else { - // Then update the index of the pending message. - mPendingMessageIndex++; - -#if USE_1BYTE_PARSING - // Message is not complete. - return false; -#else - // Call the parser recursively - // to parse the rest of the message. - return parse(inChannel); -#endif - - } - - } - - } - - // What are our chances to fall here? - return false; -} - - -// Private method: check if the received message is on the listened channel -bool MIDI_Class::input_filter(byte inChannel) -{ - - - // This method handles recognition of channel (to know if the message is destinated to the Arduino) - - - if (mMessage.type == InvalidType) return false; - - - // First, check if the received message is Channel - if (mMessage.type >= NoteOff && mMessage.type <= PitchBend) { - - // Then we need to know if we listen to it - if ((mMessage.channel == mInputChannel) || (mInputChannel == MIDI_CHANNEL_OMNI)) { - return true; - - } - else { - // We don't listen to this channel - return false; - } - - } - else { - - // System messages are always received - return true; - } - -} - - -// Private method: reset input attributes -void MIDI_Class::reset_input_attributes() -{ - - mPendingMessageIndex = 0; - mPendingMessageExpectedLenght = 0; - mRunningStatus_RX = InvalidType; - -} - - -// Getters -/*! \brief Get the last received message's type - - Returns an enumerated type. @see kMIDIType - */ -kMIDIType MIDI_Class::getType() const -{ - - return mMessage.type; - -} - - -/*! \brief Get the channel of the message stored in the structure. - - Channel range is 1 to 16. For non-channel messages, this will return 0. - */ -byte MIDI_Class::getChannel() const -{ - - return mMessage.channel; - -} - - -/*! \brief Get the first data byte of the last received message. */ -byte MIDI_Class::getData1() const -{ - - return mMessage.data1; - -} - - -/*! \brief Get the second data byte of the last received message. */ -byte MIDI_Class::getData2() const -{ - - return mMessage.data2; - -} - - -/*! \brief Get the System Exclusive byte array. - - @see getSysExArrayLength to get the array's length in bytes. - */ -const byte * MIDI_Class::getSysExArray() const -{ - - return mMessage.sysex_array; - -} - -/*! \brief Get the lenght of the System Exclusive array. - - It is coded using data1 as LSB and data2 as MSB. - \return The array's length, in bytes. - */ -unsigned int MIDI_Class::getSysExArrayLength() const -{ - - unsigned int coded_size = ((unsigned int)(mMessage.data2) << 8) | mMessage.data1; - - return (coded_size > MIDI_SYSEX_ARRAY_SIZE) ? MIDI_SYSEX_ARRAY_SIZE : coded_size; - -} - - -/*! \brief Check if a valid message is stored in the structure. */ -bool MIDI_Class::check() const -{ - - return mMessage.valid; - -} - - -// Setters -/*! \brief Set the value for the input MIDI channel - \param Channel the channel value. Valid values are 1 to 16, - MIDI_CHANNEL_OMNI if you want to listen to all channels, and MIDI_CHANNEL_OFF to disable MIDI input. - */ -void MIDI_Class::setInputChannel(const byte Channel) -{ - - mInputChannel = Channel; - -} - - -#if USE_CALLBACKS - -void MIDI_Class::setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOffCallback = fptr; } -void MIDI_Class::setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)) { mNoteOnCallback = fptr; } -void MIDI_Class::setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)) { mAfterTouchPolyCallback = fptr; } -void MIDI_Class::setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)) { mControlChangeCallback = fptr; } -void MIDI_Class::setHandleProgramChange(void (*fptr)(byte channel, byte number)) { mProgramChangeCallback = fptr; } -void MIDI_Class::setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)) { mAfterTouchChannelCallback = fptr; } -void MIDI_Class::setHandlePitchBend(void (*fptr)(byte channel, int bend)) { mPitchBendCallback = fptr; } -void MIDI_Class::setHandleSystemExclusive(void (*fptr)(byte * array, byte size)) { mSystemExclusiveCallback = fptr; } -void MIDI_Class::setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)) { mTimeCodeQuarterFrameCallback = fptr; } -void MIDI_Class::setHandleSongPosition(void (*fptr)(unsigned int beats)) { mSongPositionCallback = fptr; } -void MIDI_Class::setHandleSongSelect(void (*fptr)(byte songnumber)) { mSongSelectCallback = fptr; } -void MIDI_Class::setHandleTuneRequest(void (*fptr)(void)) { mTuneRequestCallback = fptr; } -void MIDI_Class::setHandleClock(void (*fptr)(void)) { mClockCallback = fptr; } -void MIDI_Class::setHandleStart(void (*fptr)(void)) { mStartCallback = fptr; } -void MIDI_Class::setHandleContinue(void (*fptr)(void)) { mContinueCallback = fptr; } -void MIDI_Class::setHandleStop(void (*fptr)(void)) { mStopCallback = fptr; } -void MIDI_Class::setHandleActiveSensing(void (*fptr)(void)) { mActiveSensingCallback = fptr; } -void MIDI_Class::setHandleSystemReset(void (*fptr)(void)) { mSystemResetCallback = fptr; } - - -/*! \brief Detach an external function from the given type. - - Use this method to cancel the effects of setHandle********. - \param Type The type of message to unbind. When a message of this type is received, no function will be called. - */ -void MIDI_Class::disconnectCallbackFromType(kMIDIType Type) -{ - - switch (Type) { - case NoteOff: mNoteOffCallback = NULL; break; - case NoteOn: mNoteOnCallback = NULL; break; - case AfterTouchPoly: mAfterTouchPolyCallback = NULL; break; - case ControlChange: mControlChangeCallback = NULL; break; - case ProgramChange: mProgramChangeCallback = NULL; break; - case AfterTouchChannel: mAfterTouchChannelCallback = NULL; break; - case PitchBend: mPitchBendCallback = NULL; break; - case SystemExclusive: mSystemExclusiveCallback = NULL; break; - case TimeCodeQuarterFrame: mTimeCodeQuarterFrameCallback = NULL; break; - case SongPosition: mSongPositionCallback = NULL; break; - case SongSelect: mSongSelectCallback = NULL; break; - case TuneRequest: mTuneRequestCallback = NULL; break; - case Clock: mClockCallback = NULL; break; - case Start: mStartCallback = NULL; break; - case Continue: mContinueCallback = NULL; break; - case Stop: mStopCallback = NULL; break; - case ActiveSensing: mActiveSensingCallback = NULL; break; - case SystemReset: mSystemResetCallback = NULL; break; - default: - break; - } - -} - - -// Private - launch callback function based on received type. -void MIDI_Class::launchCallback() -{ - - // The order is mixed to allow frequent messages to trigger their callback faster. - - switch (mMessage.type) { - // Notes - case NoteOff: if (mNoteOffCallback != NULL) mNoteOffCallback(mMessage.channel,mMessage.data1,mMessage.data2); break; - case NoteOn: if (mNoteOnCallback != NULL) mNoteOnCallback(mMessage.channel,mMessage.data1,mMessage.data2); break; - - // Real-time messages - case Clock: if (mClockCallback != NULL) mClockCallback(); break; - case Start: if (mStartCallback != NULL) mStartCallback(); break; - case Continue: if (mContinueCallback != NULL) mContinueCallback(); break; - case Stop: if (mStopCallback != NULL) mStopCallback(); break; - case ActiveSensing: if (mActiveSensingCallback != NULL) mActiveSensingCallback(); break; - - // Continuous controllers - case ControlChange: if (mControlChangeCallback != NULL) mControlChangeCallback(mMessage.channel,mMessage.data1,mMessage.data2); break; - case PitchBend: if (mPitchBendCallback != NULL) mPitchBendCallback(mMessage.channel,(int)((mMessage.data1 & 0x7F) | ((mMessage.data2 & 0x7F)<< 7)) - 8192); break; // TODO: check this - case AfterTouchPoly: if (mAfterTouchPolyCallback != NULL) mAfterTouchPolyCallback(mMessage.channel,mMessage.data1,mMessage.data2); break; - case AfterTouchChannel: if (mAfterTouchChannelCallback != NULL) mAfterTouchChannelCallback(mMessage.channel,mMessage.data1); break; - - case ProgramChange: if (mProgramChangeCallback != NULL) mProgramChangeCallback(mMessage.channel,mMessage.data1); break; - case SystemExclusive: if (mSystemExclusiveCallback != NULL) mSystemExclusiveCallback(mMessage.sysex_array,mMessage.data1); break; - - // Occasional messages - case TimeCodeQuarterFrame: if (mTimeCodeQuarterFrameCallback != NULL) mTimeCodeQuarterFrameCallback(mMessage.data1); break; - case SongPosition: if (mSongPositionCallback != NULL) mSongPositionCallback((mMessage.data1 & 0x7F) | ((mMessage.data2 & 0x7F)<< 7)); break; - case SongSelect: if (mSongSelectCallback != NULL) mSongSelectCallback(mMessage.data1); break; - case TuneRequest: if (mTuneRequestCallback != NULL) mTuneRequestCallback(); break; - - case SystemReset: if (mSystemResetCallback != NULL) mSystemResetCallback(); break; - case InvalidType: - default: - break; - } - -} - - -#endif // USE_CALLBACKS - - -#endif // COMPILE_MIDI_IN - - - - -#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru - -/*! \brief Set the filter for thru mirroring - \param inThruFilterMode a filter mode - - @see kThruFilterMode - */ -void MIDI_Class::setThruFilterMode(kThruFilterMode inThruFilterMode) -{ - - mThruFilterMode = inThruFilterMode; - if (mThruFilterMode != Off) mThruActivated = true; - else mThruActivated = false; - -} - - -/*! \brief Setter method: turn message mirroring on. */ -void MIDI_Class::turnThruOn(kThruFilterMode inThruFilterMode) -{ - - mThruActivated = true; - mThruFilterMode = inThruFilterMode; - -} - - -/*! \brief Setter method: turn message mirroring off. */ -void MIDI_Class::turnThruOff() -{ - - mThruActivated = false; - mThruFilterMode = Off; - -} - - -// This method is called upon reception of a message and takes care of Thru filtering and sending. -void MIDI_Class::thru_filter(byte inChannel) -{ - - /* - This method handles Soft-Thru filtering. - - Soft-Thru filtering: - - All system messages (System Exclusive, Common and Real Time) are passed to output unless filter is set to Off - - Channel messages are passed to the output whether their channel is matching the input channel and the filter setting - - */ - - // If the feature is disabled, don't do anything. - if (!mThruActivated || (mThruFilterMode == Off)) return; - - - // First, check if the received message is Channel - if (mMessage.type >= NoteOff && mMessage.type <= PitchBend) { - - const bool filter_condition = ((mMessage.channel == mInputChannel) || (mInputChannel == MIDI_CHANNEL_OMNI)); - - // Now let's pass it to the output - switch (mThruFilterMode) { - case Full: - send(mMessage.type,mMessage.data1,mMessage.data2,mMessage.channel); - return; - break; - case SameChannel: - if (filter_condition) { - send(mMessage.type,mMessage.data1,mMessage.data2,mMessage.channel); - return; - } - break; - case DifferentChannel: - if (!filter_condition) { - send(mMessage.type,mMessage.data1,mMessage.data2,mMessage.channel); - return; - } - break; - case Off: - // Do nothing. - // Technically it's impossible to get there because the case was already tested earlier. - break; - default: - break; - } - - } - else { - - // Send the message to the output - switch (mMessage.type) { - // Real Time and 1 byte - case Clock: - case Start: - case Stop: - case Continue: - case ActiveSensing: - case SystemReset: - case TuneRequest: - sendRealTime(mMessage.type); - return; - break; - - case SystemExclusive: - // Send SysEx (0xF0 and 0xF7 are included in the buffer) - sendSysEx(mMessage.data1,mMessage.sysex_array,true); - return; - break; - - case SongSelect: - sendSongSelect(mMessage.data1); - return; - break; - - case SongPosition: - sendSongPosition(mMessage.data1 | ((unsigned)mMessage.data2<<7)); - return; - break; - - case TimeCodeQuarterFrame: - sendTimeCodeQuarterFrame(mMessage.data1,mMessage.data2); - return; - break; - default: - break; - - } - - } - -} - - -#endif // Thru - - diff --git a/RetroCade_Sketch/MIDI.h b/RetroCade_Sketch/MIDI.h deleted file mode 100644 index 63f4671..0000000 --- a/RetroCade_Sketch/MIDI.h +++ /dev/null @@ -1,319 +0,0 @@ -/*! - * @file MIDI.h - * Project MIDI Library - * @brief MIDI Library for the Arduino - * Version 3.2 - * @author Francois Best - * @date 24/02/11 - * License GPL Forty Seven Effects - 2011 - */ - -#ifndef LIB_MIDI_H_ -#define LIB_MIDI_H_ - -#include -#include "HardwareSerial.h" - - -/* - ############################################################### - # # - # CONFIGURATION AREA # - # # - # Here are a few settings you can change to customize # - # the library for your own project. You can for example # - # choose to compile only parts of it so you gain flash # - # space and optimise the speed of your sketch. # - # # - ############################################################### - */ - - -#define COMPILE_MIDI_IN 1 // Set this setting to 1 to use the MIDI input. -#define COMPILE_MIDI_OUT 1 // Set this setting to 1 to use the MIDI output. -#define COMPILE_MIDI_THRU 0 // Set this setting to 1 to use the MIDI Soft Thru feature - // Please note that the Thru will work only when both COMPILE_MIDI_IN and COMPILE_MIDI_OUT set to 1. - - -#define USE_SERIAL_PORT Serial // Change the number (to Serial1 for example) if you want - // to use a different serial port for MIDI I/O. - - -#define USE_RUNNING_STATUS 0 // Running status enables short messages when sending multiple values - // of the same type and channel. - // Set to 0 if you have troubles with controlling you hardware. - - -#define USE_CALLBACKS 1 // Set this to 1 if you want to use callback handlers (to bind your functions to the library). - // To use the callbacks, you need to have COMPILE_MIDI_IN set to 1 - -#define USE_1BYTE_PARSING 1 // Each call to MIDI.read will only parse one byte (might be faster). - - -// END OF CONFIGURATION AREA -// (do not modify anything under this line unless you know what you are doing) - - -#define MIDI_BAUDRATE 115200 - -#define MIDI_CHANNEL_OMNI 0 -#define MIDI_CHANNEL_OFF 17 // and over - -#define MIDI_SYSEX_ARRAY_SIZE 255 // Maximum size is 65535 bytes. - -/*! Type definition for practical use (because "unsigned char" is a bit long to write.. )*/ -typedef uint8_t byte; -typedef uint16_t word; - -/*! Enumeration of MIDI types */ -enum kMIDIType { - NoteOff = 0x80, ///< Note Off - NoteOn = 0x90, ///< Note On - AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch - ControlChange = 0xB0, ///< Control Change / Channel Mode - ProgramChange = 0xC0, ///< Program Change - AfterTouchChannel = 0xD0, ///< Channel (monophonic) AfterTouch - PitchBend = 0xE0, ///< Pitch Bend - SystemExclusive = 0xF0, ///< System Exclusive - TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame - SongPosition = 0xF2, ///< System Common - Song Position Pointer - SongSelect = 0xF3, ///< System Common - Song Select - TuneRequest = 0xF6, ///< System Common - Tune Request - Clock = 0xF8, ///< System Real Time - Timing Clock - Start = 0xFA, ///< System Real Time - Start - Continue = 0xFB, ///< System Real Time - Continue - Stop = 0xFC, ///< System Real Time - Stop - ActiveSensing = 0xFE, ///< System Real Time - Active Sensing - SystemReset = 0xFF, ///< System Real Time - System Reset - InvalidType = 0x00 ///< For notifying errors -}; - -/*! Enumeration of Thru filter modes */ -enum kThruFilterMode { - Off = 0, ///< Thru disabled (nothing passes through). - Full = 1, ///< Fully enabled Thru (every incoming message is sent back). - SameChannel = 2, ///< Only the messages on the Input Channel will be sent back. - DifferentChannel = 3 ///< All the messages but the ones on the Input Channel will be sent back. -}; - - -/*! The midimsg structure contains decoded data of a MIDI message read from the serial port with read() or thru(). \n */ -struct midimsg { - /*! The MIDI channel on which the message was recieved. \n Value goes from 1 to 16. */ - byte channel; - /*! The type of the message (see the define section for types reference) */ - kMIDIType type; - /*! The first data byte.\n Value goes from 0 to 127.\n */ - byte data1; - /*! The second data byte. If the message is only 2 bytes long, this one is null.\n Value goes from 0 to 127. */ - byte data2; - /*! System Exclusive dedicated byte array. \n Array length is stocked on 16 bits, in data1 (LSB) and data2 (MSB) */ - byte sysex_array[MIDI_SYSEX_ARRAY_SIZE]; - /*! This boolean indicates if the message is valid or not. There is no channel consideration here, validity means the message respects the MIDI norm. */ - bool valid; -}; - - - - -/*! \brief The main class for MIDI handling.\n - See member descriptions to know how to use it, - or check out the examples supplied with the library. - */ -class MIDI_Class { - - -public: - // Constructor and Destructor - MIDI_Class(); - ~MIDI_Class(); - - - void begin(const byte inChannel = 1); - - - - -/* ####### OUTPUT COMPILATION BLOCK ####### */ -#if COMPILE_MIDI_OUT - -public: - - void sendNoteOn(byte NoteNumber,byte Velocity,byte Channel); - void sendNoteOff(byte NoteNumber,byte Velocity,byte Channel); - void sendProgramChange(byte ProgramNumber,byte Channel); - void sendControlChange(byte ControlNumber, byte ControlValue,byte Channel); - void sendPitchBend(int PitchValue,byte Channel); - void sendPitchBend(unsigned int PitchValue,byte Channel); - void sendPitchBend(double PitchValue,byte Channel); - void sendPolyPressure(byte NoteNumber,byte Pressure,byte Channel); - void sendAfterTouch(byte Pressure,byte Channel); - void sendSysEx(int length, const byte *const array,bool ArrayContainsBoundaries = false); - void sendTimeCodeQuarterFrame(byte TypeNibble, byte ValuesNibble); - void sendTimeCodeQuarterFrame(byte data); - void sendSongPosition(unsigned int Beats); - void sendSongSelect(byte SongNumber); - void sendTuneRequest(); - void sendRealTime(kMIDIType Type); - - void send(kMIDIType type, byte param1, byte param2, byte channel); - -private: - - const byte genstatus(const kMIDIType inType,const byte inChannel) const; - - - // Attributes -#if USE_RUNNING_STATUS - byte mRunningStatus_TX; -#endif // USE_RUNNING_STATUS - -#endif // COMPILE_MIDI_OUT - - - -/* ####### INPUT COMPILATION BLOCK ####### */ -#if COMPILE_MIDI_IN - -public: - - bool read(); - bool read(HardwareSerial* sPort); - bool read(const byte Channel); - - // Getters - kMIDIType getType() const; - byte getChannel() const; - byte getData1() const; - byte getData2() const; - const byte * getSysExArray() const; - unsigned int getSysExArrayLength() const; - bool check() const; - - byte getInputChannel() const - { - return mInputChannel; - } - - // Setters - void setInputChannel(const byte Channel); - - /*! \brief Extract an enumerated MIDI type from a status byte. - - This is a utility static method, used internally, made public so you can handle kMIDITypes more easily. - */ - static inline const kMIDIType getTypeFromStatusByte(const byte inStatus) - { - if ((inStatus < 0x80) - || (inStatus == 0xF4) - || (inStatus == 0xF5) - || (inStatus == 0xF9) - || (inStatus == 0xFD)) return InvalidType; // data bytes and undefined. - if (inStatus < 0xF0) return (kMIDIType)(inStatus & 0xF0); // Channel message, remove channel nibble. - else return (kMIDIType)inStatus; - } - - -#if USE_CALLBACKS - - void setHandleNoteOff(void (*fptr)(byte channel, byte note, byte velocity)); - void setHandleNoteOn(void (*fptr)(byte channel, byte note, byte velocity)); - void setHandleAfterTouchPoly(void (*fptr)(byte channel, byte note, byte pressure)); - void setHandleControlChange(void (*fptr)(byte channel, byte number, byte value)); - void setHandleProgramChange(void (*fptr)(byte channel, byte number)); - void setHandleAfterTouchChannel(void (*fptr)(byte channel, byte pressure)); - void setHandlePitchBend(void (*fptr)(byte channel, int bend)); - void setHandleSystemExclusive(void (*fptr)(byte * array, byte size)); - void setHandleTimeCodeQuarterFrame(void (*fptr)(byte data)); - void setHandleSongPosition(void (*fptr)(unsigned int beats)); - void setHandleSongSelect(void (*fptr)(byte songnumber)); - void setHandleTuneRequest(void (*fptr)(void)); - void setHandleClock(void (*fptr)(void)); - void setHandleStart(void (*fptr)(void)); - void setHandleContinue(void (*fptr)(void)); - void setHandleStop(void (*fptr)(void)); - void setHandleActiveSensing(void (*fptr)(void)); - void setHandleSystemReset(void (*fptr)(void)); - - void disconnectCallbackFromType(kMIDIType Type); - -#endif // USE_CALLBACKS - - -private: - - bool input_filter(byte inChannel); - bool parse(byte inChannel); - void reset_input_attributes(); - HardwareSerial* serPortPTR; - - // Attributes - byte mRunningStatus_RX; - byte mInputChannel; - - byte mPendingMessage[MIDI_SYSEX_ARRAY_SIZE]; - unsigned int mPendingMessageExpectedLenght; - unsigned int mPendingMessageIndex; // Extended to unsigned int for larger sysex payloads. - - midimsg mMessage; - -#if USE_CALLBACKS - - void launchCallback(); - - void (*mNoteOffCallback)(byte channel, byte note, byte velocity); - void (*mNoteOnCallback)(byte channel, byte note, byte velocity); - void (*mAfterTouchPolyCallback)(byte channel, byte note, byte velocity); - void (*mControlChangeCallback)(byte channel, byte, byte); - void (*mProgramChangeCallback)(byte channel, byte); - void (*mAfterTouchChannelCallback)(byte channel, byte); - void (*mPitchBendCallback)(byte channel, int); - void (*mSystemExclusiveCallback)(byte * array, byte size); - void (*mTimeCodeQuarterFrameCallback)(byte data); - void (*mSongPositionCallback)(unsigned int beats); - void (*mSongSelectCallback)(byte songnumber); - void (*mTuneRequestCallback)(void); - void (*mClockCallback)(void); - void (*mStartCallback)(void); - void (*mContinueCallback)(void); - void (*mStopCallback)(void); - void (*mActiveSensingCallback)(void); - void (*mSystemResetCallback)(void); - -#endif // USE_CALLBACKS - - -#endif // COMPILE_MIDI_IN - - -/* ####### THRU COMPILATION BLOCK ####### */ -#if (COMPILE_MIDI_IN && COMPILE_MIDI_OUT && COMPILE_MIDI_THRU) // Thru - -public: - - // Getters - kThruFilterMode getFilterMode() const { return mThruFilterMode; } - bool getThruState() const { return mThruActivated; } - - - // Setters - void turnThruOn(kThruFilterMode inThruFilterMode = Full); - void turnThruOff(); - - void setThruFilterMode(const kThruFilterMode inThruFilterMode); - - -private: - - void thru_filter(byte inChannel); - - bool mThruActivated; - kThruFilterMode mThruFilterMode; - -#endif // Thru - -}; - -extern MIDI_Class MIDI; - -#endif // LIB_MIDI_H_ diff --git a/RetroCade_Sketch/RetroCade_Sketch.ino b/RetroCade_Sketch/RetroCade_Sketch.ino index 6b916b7..2c9c4a0 100644 --- a/RetroCade_Sketch/RetroCade_Sketch.ino +++ b/RetroCade_Sketch/RetroCade_Sketch.ino @@ -21,6 +21,10 @@ http://www.gadgetfactory.net License: GPL ChangeLog: +9/26/2013 Version 1.1 + -Added SID Analog Filters!!!!!!!! Thanks to Alvie for writing the VHDL code. + -Added SidPlayer library to process SID files from smallFS and SD Cards. Thanks to Alvie for porting to the ZPUino. + 1/9/2013 Version 1.02 -NoteOff fix from Lee O'D @@ -86,7 +90,7 @@ ChangeLog: #include "SmallFS.h" #include #include -#include "VolumeController.h" +//#include "VolumeController.h" #include "ymplayer.h" #include "modplayer.h" #include "ramFS.h" @@ -112,9 +116,9 @@ void setup(){ Serial.begin(115200); Serial1.begin(31250); - for (input=0; input<8; input++) { - VolumeController.set(input, 255, 255); - } +// for (input=0; input<8; input++) { +// VolumeController.set(input, 255, 255); +// } //Setup pins for RetroCade MegaWing retrocade.setupMegaWing(); @@ -383,4 +387,4 @@ void loop(){ retrocade.handleJoystick(); retrocade.sidplayer.audiofill(); } - + diff --git a/RetroCade_Sketch/SID.h b/RetroCade_Sketch/SID.h deleted file mode 100644 index aeb227d..0000000 --- a/RetroCade_Sketch/SID.h +++ /dev/null @@ -1,120 +0,0 @@ -/*! - * @file SID.h - * Project SID Library - * @brief SID Library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ - -#ifndef LIB_SID_H_ -#define LIB_SID_H_ - -#include -#include -#include -#include "Arduino.h" - -#define SID_ADDR_BASE_V1 0x00 -#define SID_ADDR_BASE_V2 0x07 -#define SID_ADDR_BASE_V3 0x0E - -#define SID_ADDR_FILTER_FC_LOW 0x15 -#define SID_ADDR_FILTER_FC_HI 0x16 -#define SID_ADDR_FILTER_RES_FILT 0x17 -#define SID_ADDR_FILTER_MODE_VOL 0x18 - -#define SID_ADDR_MISC_ENV3 0x1C - -#define SIDBASE IO_SLOT(14) -#define SIDREG(x) REGISTER(SIDBASE,x) - -class SIDVoice -{ - public: - SIDVoice(); - SIDVoice(int address); - void setBase(int address); - void setNote(int note, boolean active); - void setFreq(int freq); - void setPWLo(byte dutyCycle); - void setPWHi(byte dutyCycle); - void setGate(boolean active); - void setSync(boolean active); - void setRingMod(boolean active); - void setTest(boolean active); - void setTriangle(boolean active); - void setSawtooth(boolean active); - void setSquare(boolean active); - void setSquare(boolean active, int pwm); - void setNoise(boolean active); - void setEnvelopeAttack(byte rate); - void setEnvelopeDecay(byte rate); - void setEnvelopeSustain(byte level); - void setEnvelopeRelease(byte rate); - void setInstrument(const char* name, byte attack, byte decay, byte sustain, byte release, bool noise, bool square, bool sawtooth, bool triangle, int pwm); - void loadInstrument(byte instrument); - void handleCC(byte number, byte value); - void reset(); - int getCurrentFreq(); - private: - void writeData(unsigned char address, unsigned char data); - void ringMod(byte baseOffset, byte valueOffset, byte value); - int baseAddress; - int currentFreq; - int SID_ADDR_FREQ_LOW; - int SID_ADDR_FREQ_HI; - int SID_ADDR_PW_LOW; - int SID_ADDR_PW_HI; - int SID_ADDR_CONTROLREG; - int SID_ADDR_ATTACK_DECAY; - int SID_ADDR_SUSTAIN_RELEASE; - char instrumentName[25]; - struct SID_REG_CONTROLREG_STRUCT{ - unsigned int NOISE_WAVE : 1; - unsigned int SQUARE_WAVE : 1; - unsigned int SAWTOOTH_WAVE : 1; - unsigned int TRIANGLE_WAVE : 1; - unsigned int TEST : 1; - unsigned int RING_MOD : 1; - unsigned int SYNC : 1; - unsigned int GATE : 1; - } ; - SID_REG_CONTROLREG_STRUCT SID_REG_CONTROLREG; - - struct SID_REG_ATTACK_DECAY_STRUCT{ - unsigned int ATTACK : 4; - unsigned int DECAY : 4; - }; - SID_REG_ATTACK_DECAY_STRUCT SID_REG_ATTACK_DECAY; - - struct SID_REG_SUSTAIN_RELEASE_STRUCT{ - unsigned int SUSTAIN : 4; - unsigned int RELEASE : 4; - }; - SID_REG_SUSTAIN_RELEASE_STRUCT SID_REG_SUSTAIN_RELEASE; -}; - -class SID -{ - public: - SIDVoice V1; - SIDVoice V2; - SIDVoice V3; - SID(); - static void writeData(unsigned char address, unsigned char data); - void setVolume(byte volume); - void reset(); - static const int MIDI2freq[129]; - private: - struct SID_REG_MODE_VOLUME_STRUCT{ - unsigned int OFF : 1; - unsigned int HP : 1; - unsigned int BP : 1; - unsigned int LP : 1; - unsigned int VOLUME : 4; - } ; - SID_REG_MODE_VOLUME_STRUCT SID_REG_MODE_VOLUME; -}; -#endif // LIB_SID_H_ diff --git a/RetroCade_Sketch/VolumeController.cpp b/RetroCade_Sketch/VolumeController.cpp deleted file mode 100644 index 12a1ddc..0000000 --- a/RetroCade_Sketch/VolumeController.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "VolumeController.h" - -VolumeController_class::VolumeController_class(int slot) -{ - base=IO_SLOT(slot); -} - -void VolumeController_class::set(int input, int left, int right) -{ - left&=0xff; - right&=0xff; - input&=7; - REGISTER( base, input ) = left; - REGISTER( base, input + 32 ) = right; -} - - -VolumeController_class VolumeController; diff --git a/RetroCade_Sketch/VolumeController.h b/RetroCade_Sketch/VolumeController.h deleted file mode 100644 index cbed951..0000000 --- a/RetroCade_Sketch/VolumeController.h +++ /dev/null @@ -1,15 +0,0 @@ -#include - -class VolumeController_class -{ -public: - VolumeController_class(int slot=12); - - void set(int input, int left, int right); - -private: - unsigned base; -}; - -extern VolumeController_class VolumeController; - diff --git a/RetroCade_Sketch/YM2149.cpp b/RetroCade_Sketch/YM2149.cpp deleted file mode 100644 index 4acc6dd..0000000 --- a/RetroCade_Sketch/YM2149.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/*! - * @file YM2149.cpp - * Project YM2149 Library - * @brief YM2149 Library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ -#include "YM2149.h" - -const int YM2149::MIDI2freq[129] = {//MIDI note number - 15289, 14431, 13621, 12856, 12135, 11454, 10811, 10204,//0-7 - 9631, 9091, 8581, 8099, 7645, 7215, 6810, 6428,//8-15 - 6067, 5727, 5405, 5102, 4816, 4545, 4290, 4050,//16-23 - 3822, 3608, 3405, 3214, 3034, 2863, 2703, 2551,//24-31 - 2408, 2273, 2145, 2025, 1911, 1804, 1703, 1607,//32-39 - 1517, 1432, 1351, 1276, 1204, 1136, 1073, 1012,//40-47 - 956, 902, 851, 804, 758, 716, 676, 638,//48-55 - 602, 568, 536, 506, 478, 451, 426, 402,//56-63 - 379, 358, 338, 319, 301, 284, 268, 253,//64-71 - 239, 225, 213, 201, 190, 179, 169, 159,//72-79 - 150, 142, 134, 127, 119, 113, 106, 100,//80-87 - 95, 89, 84, 80, 75, 71, 67, 63,//88-95 - 60, 56, 53, 50, 47, 45, 42, 40,//96-103 - 38, 36, 34, 32, 30, 28, 27, 25,//104-111 - 24, 22, 21, 20, 19, 18, 17, 16,//112-119 - 15, 14, 13, 13, 12, 11, 11, 10,//120-127 - 0//off -}; - -//TODO: This is not the right place for this -struct YM_REG_MIXER_STRUCT{ - unsigned int EMPTY : 2; - unsigned int NOISEC : 1; - unsigned int NOISEB : 1; - unsigned int NOISEA : 1; - unsigned int TONEC : 1; - unsigned int TONEB : 1; - unsigned int TONEA : 1; -} ; -YM_REG_MIXER_STRUCT YM_REG_MIXER; - -struct YM_REG_ENVSHAPE_STRUCT{ - unsigned int EMPTY : 4; - unsigned int CONT : 1; - unsigned int ATT : 1; - unsigned int ALT : 1; - unsigned int HOLD : 1; -} ; -YM_REG_ENVSHAPE_STRUCT YM_REG_ENVSHAPE; - -void YMVoice::setBase(int freqAddress, int volumeAddress) -{ - YM_ADDR_FREQ = freqAddress; - YM_ADDR_LEVEL = volumeAddress; -} - -/*! -@par Description -Set a voice to a MIDI Note -@par Syntax -ym2149.V1.setNote(note, active)\n -ym2149.V2.setNote(note, active)\n -ym2149.V3.setNote(note, active) - -@param note The MIDI note to use -@param active Whether to activate the gate and play the note. 1 plays the note 0 does not - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - ym2149.V1.setNote(51, 1) - ym2149.V2.setNote(52, 1) - ym2149.V3.setNote(53, 1) -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMVoice::setNote(int note, boolean active) -{ - //setTone(active); - YM2149::writeData(YM_ADDR_FREQ, YM2149::MIDI2freq[note]); - YM2149::writeData(YM_ADDR_FREQ+1, (YM2149::MIDI2freq[note] >> 8)); - currentFreq = YM2149::MIDI2freq[note]; -} - -/*! -@par Description -Set the frequency of the YM2149 voice -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![Freq] (freq1.png) -![Freq] (freq2.png) -@par Syntax -ym2149.V1.setFreq(freq)\n -ym2149.V2.setFreq(freq)\n -ym2149.V3.setFreq(freq) - -@param freq The frequency to use for the voice. - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - ym2149.V1.setFreq(6207) - ym2149.V2.setFreq(6577) - ym2149.V3.setFreq(6968) -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMVoice::setFreq(int freq) -{ - YM2149::writeData(YM_ADDR_FREQ, freq); - YM2149::writeData(YM_ADDR_FREQ+1, (freq >> 8)); -} - -/*! -@par Description -Return what the current frequency is set to. -@par Syntax -int frequency = ym2149.V1.getCurrentFreq() -@par Returns -the frequency of the voice (int) - -\n -*/ -int YMVoice::getCurrentFreq() -{ - return currentFreq; -} - -/*! -@par Description -Sets the Noise bit of the control register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![Noise] (noise.png) - -@par Syntax -ym2149.V1.setNoise(active) - -@param active 1 on 0 turns off - -\n -*/ -void YMVoice::setNoise(boolean active) -{ - switch (YM_ADDR_FREQ) { - case 0: - YM_REG_MIXER.NOISEA = !active; - break; - case 2: - YM_REG_MIXER.NOISEB = !active; - break; - case 4: - YM_REG_MIXER.NOISEC = !active; - break; - default: - return; - break; - } - YM2149REG(YM_ADDR_MIXER) = *(char*)&YM_REG_MIXER; -} - -/*! -@par Description -Sets the Envelope bit of the level register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![Envelope] (level.png) - -@par Syntax -ym2149.V1.setEnvelope(active) - -@param active 1 on 0 turns off - -\n -*/ -void YMVoice::setEnvelope(boolean active) -{ - YM_REG_LEVEL.MODE = active; - YM2149REG(YM_ADDR_LEVEL) = *(char*)&YM_REG_LEVEL; -} - -/*! -@par Description -Sets the Tone bit of the Mixer register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![Tone] (mixer.png) - -@par Syntax -ym2149.V1.setTone(active) - -@param active 1 on 0 turns off - -\n -*/ -void YMVoice::setTone(boolean active) -{ - int tmp; - if (active == true) - tmp = 0; - else - tmp = 1; - switch (YM_ADDR_LEVEL) { - case 0x08: - YM_REG_MIXER.TONEA = tmp; - break; - case 0x09: - YM_REG_MIXER.TONEB = tmp; - break; - case 0x0A: - YM_REG_MIXER.TONEC = tmp; - break; - default: - return; - break; - } - YM2149REG(YM_ADDR_MIXER) = *(char*)&YM_REG_MIXER; - //Serial.println(*(char*)&YM_REG_MIXER, BIN); -} - -/*! -@par Description -Sets the Volume bit of the level register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![Volume] (level.png) - -@par Syntax -ym2149.V1.setVolume(volume) - -@param volume byte from 0 to 15 sets the volume, 15 is loudest. - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - //Turn volume to the max value - ym2149.setVolume(15); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMVoice::setVolume(byte volume) -{ - YM_REG_LEVEL.LEVEL = volume; - YM2149REG(YM_ADDR_LEVEL) = *(char*)&YM_REG_LEVEL; - //YM2149::writeData(YM_ADDR_LEVEL, volume & 0x0f); -} - -/*! -@par Description -Return what the current volume is set to. -@par Syntax -int frequency = ym2149.V1.getVolume() -@par Returns -the volume of the voice (int) - -\n -*/ -byte YMVoice::getVolume() -{ - return YM_REG_LEVEL.LEVEL; -} - -/*! -@par Description -Reset a specific voice to zeroes. -@par Syntax -ym2149.V1.reset() -ym2149.V2.reset() -ym2149.V3.reset() -@par Parameters -none -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - ym2149.V1.reset(); - ym2149.V2.reset(); - ym2149.V3.reset(); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMVoice::reset() -{ - //set frequency to no freq - setNote(128,true); - - //set volume to zero and envelope mode off - YM_REG_LEVEL.EMPTY = 0; - YM_REG_LEVEL.MODE = 0; - YM_REG_LEVEL.LEVEL = 0; - YM2149REG(YM_ADDR_LEVEL) = *(char*)&YM_REG_LEVEL; -} - -void YMVoice::handleCC(byte number, byte value) -{ - //Handle the Control Changes for YM2149 - switch (number) { - case 2: - YM2149::setEnvelopeCONT(value); - break; - case 3: - YM2149::setEnvelopeATT(value); - break; - case 4: - YM2149::setEnvelopeALT(value); - break; - case 5: - YM2149::setEnvelopeHOLD(value); - break; - case 6: - setNoise(value); - break; - case 7: - setTone(value); - break; - case 8: - setEnvelope(value); - break; - case 71: - setVolume(value/8); - break; - case 74: - YM2149::setNoiseFrequency(value); - break; - case 75: - YM2149::setEnvelopeFrequencyLo(value << 1); - break; - case 76: - YM2149::setEnvelopeFrequencyHi(value << 1); - break; - default: - return; - break; - } -} - -/*! -@par Description - Contructor that creates an instance of the YM2149 object that contains three YM2149Voice objects. V1, V2, V3 -These objects are used to interact with and control the registers for the YM2149 hardware implemented inside the Papilio FPGA board. -Calling this contructor will initialize the YM2149 and YM2149Voice objects to their default values. -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -A list of the YM2149 Registers: -![Register] (registers.png) -@par Syntax - YM2149() -@par Parameters - none -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - ym2149.setVolume(15); - ym2149.V1.setNote(51, 1); - ym2149.V2.setNote(51, 1); - ym2149.V3.setNote(51, 1); -} - -void loop() {} -~~~~~~~~ -\n -*/ -YM2149::YM2149(){ - V1.setBase(YM_ADDR_FREQ_A, YM_ADDR_LEVEL_A); - V2.setBase(YM_ADDR_FREQ_B, YM_ADDR_LEVEL_B); - V3.setBase(YM_ADDR_FREQ_C, YM_ADDR_LEVEL_C); - reset(); -} - -/*! -@par Description -Use this public function to bypass the YM2149 and YM2149Voice functions and write directly to the registers of the YM2149 hardware. -@par Syntax -YM2149::writeData(address, data) -@param address the address from the YM2149 datasheet for the register you want to write to. -@param data what you want to write to the YM2149 register - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - //This will set Voice 1 Freq Lo to 0 - YM2149::writeData(0, 0); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YM2149::writeData(unsigned char address, unsigned char data) -{ - YM2149REG(address) = data; -} - -/*! -@par Description -Sets the Noise frequency bits of the Noise Frequency register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![noise] (noise.png) - -@par Syntax -ym2149.V1.setNoiseFrequency(freq) - -@param freq 5 bit noise frequency - -\n -*/ -void YM2149::setNoiseFrequency(byte freq) -{ - writeData(YM_ADDR_NOISE, freq); -} - -/*! -@par Description -Sets the 16 bit Envelope Frequency registers -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![envelope] (envelope.png) - -@par Syntax -ym2149.V1.setEnvelopeFrequency(freq) - -@param freq 16 bit Envelope Frequency - -\n -*/ -void YM2149::setEnvelopeFrequency(int freq) -{ - writeData(YM_ADDR_FREQ_E, freq); - writeData(YM_ADDR_FREQ_E+1, (freq >> 8)); -} - -void YM2149::setEnvelopeFrequencyLo(byte freq) -{ - writeData(YM_ADDR_FREQ_E, freq); -} - -void YM2149::setEnvelopeFrequencyHi(byte freq) -{ - writeData(YM_ADDR_FREQ_E+1, (freq >> 8)); -} - -/*! -@par Description -Sets the CONT bit of the Envelope Shape Register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![envelope] (envshape1.png) -![envelope] (envshape2.png) - -@par Syntax -ym2149.V1.setEnvelopeCONT(active) - -@param active 1 for on 0 for off - -\n -*/ -void YM2149::setEnvelopeCONT(boolean active) -{ - YM_REG_ENVSHAPE.CONT = active; - YM2149REG(YM_ADDR_SHAPE_E) = *(char*)&YM_REG_ENVSHAPE; -} - -/*! -@par Description -Sets the ATT bit of the Envelope Shape Register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![envelope] (envshape1.png) -![envelope] (envshape2.png) - -@par Syntax -ym2149.V1.setEnvelopeATT(active) - -@param active 1 for on 0 for off - -\n -*/ -void YM2149::setEnvelopeATT(boolean active) -{ - YM_REG_ENVSHAPE.ATT = active; - YM2149REG(YM_ADDR_SHAPE_E) = *(char*)&YM_REG_ENVSHAPE; -} - -/*! -@par Description -Sets the ALT bit of the Envelope Shape Register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![envelope] (envshape1.png) -![envelope] (envshape2.png) - -@par Syntax -ym2149.V1.setEnvelopeALT(active) - -@param active 1 for on 0 for off - -\n -*/ -void YM2149::setEnvelopeALT(boolean active) -{ - YM_REG_ENVSHAPE.ALT = active; - YM2149REG(YM_ADDR_SHAPE_E) = *(char*)&YM_REG_ENVSHAPE; -} - -/*! -@par Description -Sets the HOLD bit of the Envelope Shape Register -@par Datasheet -[From Datasheet] (https://github.com/GadgetFactory/RetroCade_Synth/blob/master/docs/ym2149.pdf?raw=true)\n -![envelope] (envshape1.png) -![envelope] (envshape2.png) - -@par Syntax -ym2149.V1.setEnvelopeHOLD(active) - -@param active 1 for on 0 for off - -\n -*/ -void YM2149::setEnvelopeHOLD(boolean active) -{ - YM_REG_ENVSHAPE.HOLD = active; - YM2149REG(YM_ADDR_SHAPE_E) = *(char*)&YM_REG_ENVSHAPE; -} - -/*! -@par Description -Set all YM2149 registers to their default values. -@par Syntax -ym2149.reset() -@par Parameters -none -@par Example -~~~~~~~~{.c} -#include "YM2149.h" - -YM2149 ym2149; - -void setup() -{ - ym2149.reset(); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YM2149::reset(){ - //no noise - writeData(YM_ADDR_NOISE, 0x00); - - //turn off noise and audio channels - YM_REG_MIXER.EMPTY = 0; - YM_REG_MIXER.NOISEC = 1; - YM_REG_MIXER.NOISEB = 1; - YM_REG_MIXER.NOISEA = 1; - YM_REG_MIXER.TONEC = 0; - YM_REG_MIXER.TONEB = 0; - YM_REG_MIXER.TONEA = 0; - YM2149REG(YM_ADDR_MIXER) = *(char*)&YM_REG_MIXER; - - //set freq of envelope to zero - setEnvelopeFrequency(0); - - //set shape of envelope to defaults - YM_REG_ENVSHAPE.EMPTY = 0; - YM_REG_ENVSHAPE.CONT = 1; - YM_REG_ENVSHAPE.ATT = 1; - YM_REG_ENVSHAPE.ALT = 1; - YM_REG_ENVSHAPE.HOLD = 1; - YM2149REG(YM_ADDR_SHAPE_E) = *(char*)&YM_REG_ENVSHAPE; - - //reset voices - V1.reset(); - V2.reset(); - V3.reset(); -} diff --git a/RetroCade_Sketch/YM2149.h b/RetroCade_Sketch/YM2149.h deleted file mode 100644 index b565c24..0000000 --- a/RetroCade_Sketch/YM2149.h +++ /dev/null @@ -1,82 +0,0 @@ -/*! - * @file YM2149.h - * Project YM2149 Library - * @brief YM2149 Library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ - -#ifndef LIB_YM2149_H_ -#define LIB_YM2149_H_ - -#include -#include -#include -#include "Arduino.h" - - -#define YM_ADDR_FREQ_A 0x00 -#define YM_ADDR_FREQ_B 0x02 -#define YM_ADDR_FREQ_C 0x04 -#define YM_ADDR_NOISE 0x06 -#define YM_ADDR_MIXER 0x07 -#define YM_ADDR_LEVEL_A 0x08 -#define YM_ADDR_LEVEL_B 0x09 -#define YM_ADDR_LEVEL_C 0x0A -#define YM_ADDR_FREQ_E 0x0B -#define YM_ADDR_SHAPE_E 0x0D - -#define YM2149BASE IO_SLOT(13) -#define YM2149REG(x) REGISTER(YM2149BASE,x) - -class YMVoice -{ - public: - void setBase(int freqAddress, int volumeAddress); - void setNote(int note, boolean active); - void setFreq(int freq); - void setVolume(byte volume); - void setEnvelope(boolean active); - void setTone(boolean active); - void setNoise(boolean active); - void reset(); - void handleCC(byte number, byte value); - int getCurrentFreq(); - byte getVolume(); - private: - int baseAddress; - int currentFreq; - int YM_ADDR_FREQ; - int YM_ADDR_LEVEL; - struct YM_REG_LEVEL_STRUCT{ - unsigned int EMPTY : 3; - unsigned int MODE : 1; - unsigned int LEVEL : 4; - } ; - YM_REG_LEVEL_STRUCT YM_REG_LEVEL; -}; - -class YM2149 -{ - public: - YMVoice V1; - YMVoice V2; - YMVoice V3; - YM2149(); - static void writeData(unsigned char address, unsigned char data); - static void setNoiseFrequency(byte freq); - static void setEnvelopeFrequency(int freq); - static void setEnvelopeFrequencyLo(byte freq); - static void setEnvelopeFrequencyHi(byte freq); - static void setEnvelopeCONT(boolean active); - static void setEnvelopeATT(boolean active); - static void setEnvelopeALT(boolean active); - static void setEnvelopeHOLD(boolean active); - void reset(); - static const int MIDI2freq[129]; - private: - -}; -#endif // LIB_YM2149_H_ diff --git a/RetroCade_Sketch/cbuffer.h b/RetroCade_Sketch/cbuffer.h deleted file mode 100644 index 23afac7..0000000 --- a/RetroCade_Sketch/cbuffer.h +++ /dev/null @@ -1,62 +0,0 @@ -/*! - * @file cbuffer.h - * Project RetroCade Library - * @brief RetroCade Library for the ZPUino - * Version 1.0 - * @author Alvaro Lopes - * @date 9/11/12 - * License FreeBSD - */ - -#ifndef __CBUFFER_H__ -#define __CBUFFER_H__ - - - -template struct CircularBuffer -{ - CircularBuffer():head(0),tail(0) {} - - static const unsigned int mask = (1< -#include "ptplay.h" -#include "RetroCade.h" - -#define DEBUG - -MODPLAYER::MODPLAYER(){ - -} - -void MODPLAYER::setup(){ - underruns = 0; - playing = false; - fileLoaded = false; -} - -void MODPLAYER::loadFile(const char* name) -{ - fileLoaded = false; - modSmallFSfile = SmallFS.open(name); - modSDfile =SD.open(name); - boolean smallFsCheck = modSmallFSfile.valid(); - boolean sdFsCheck = modSDfile; - if (sdFsCheck){ - Serial.println("Opening Mod File from SD Card."); - modRAMfile = RamFS.open(&modSDfile); - modSDfile.close(); - fileLoaded = true; - } - else if (smallFsCheck){ - Serial.println("Opening Mod File from SmallFS."); - modRAMfile = RamFS.open(&modSmallFSfile); - fileLoaded = true; - } - else { - Serial.println("No mod files to play in SmallFS or on SD card."); - fileLoaded = false; - } - mod = pt_init_smallfs(); -} - -void MODPLAYER::play(boolean play) -{ - if (fileLoaded) - playing = play; - else - Serial.println("No mod file to play."); -} - -void MODPLAYER::volume(int volume) -{ - mod->mastervolume = volume; -} - -void MODPLAYER::audiofill() -{ - int i; - pt_render(modRAMfile, mod, buf, NULL, 2, 16 /* Samples */, 1, 16, 1); - for (i=0;i<32;i+=2) { - unsigned v = buf[i]; - v += buf[i+1]<<8; - v += buf[i]<<16; - v += buf[i+1]<<24; - v+=0x80008000; - while (audioBuffer.isFull()); - audioBuffer.push(v); - } -} - -boolean MODPLAYER::getPlaying() -{ - return playing; -} - -void MODPLAYER::zpu_interrupt() -{ - // Play mod file - if (audioBuffer.hasData()) { - unsigned v = audioBuffer.pop(); - SIGMADELTADATA = v; - } else { - underruns++; - } - TMR0CTL &= ~(BIT(TCTLIF)); //TODO: This should probably go into main interupt -} - - -//extern unsigned char __end__; -pt_mod_s *MODPLAYER::pt_init_smallfs() -{ -// Serial.println("Starting pt_init"); - unsigned char buf[256]; // Some buffer. Let's hope this fits on stack. - unsigned char *bp=&buf[0]; - - int i, j, k; - //double tempf; - pt_mod_s *mod; - pt_sample_s *s; - //pt_pattern_s *pat; - //int i2, i3; - //pt_patterndata_s *p; - - /* M.K. signature */ - - // smallfs bp = buf + 0x438; - - modRAMfile.seek(0x438, SEEK_SET); - - - -//#ifdef DEBUG - - modRAMfile.read(&bp[0], 4); - - - Serial.print(bp[0], HEX); - Serial.print(" "); - Serial.print(bp[1], HEX); - Serial.print(" "); - Serial.print(bp[2], HEX); - Serial.print(" "); - Serial.print(bp[3], HEX); - Serial.print(" "); - Serial.println(" "); - - if (!(bp[0] == 'M' && bp[1] == '.' && bp[2] == 'K' && bp[3] == '.')) { - Serial.println("Invalid MOD file"); - return NULL; - } -//#endif - - /* determine number of patterns */ - - k = 0; - // smallfs bp = buf + 952; - modRAMfile.seek(952, SEEK_SET); - modRAMfile.read(&buf,128); - - - for (i = 0; i < 128; ++i) - { - j = *bp++; - if (j > k) k = j; - } - k++; - -#ifdef DO_CHECKS - if (bufsize < 1084 + (k << 8)) - { - return NULL; /* incomplete */ - } -#endif - - Serial.print("Number of patterns: "); - Serial.println(k); - - - - //if (mod == NULL) - //{ - /* return the required size in bytes */ - // return sizeof(*mod) + k * sizeof( pt_pattern_s); - //} - - // TODO: alternative to this, please - - //mod=(pt_mod_s *)calloc(1,sizeof(*mod) + k * sizeof( pt_pattern_s)); - Serial.print("Memory needed: "); - Serial.println( sizeof(*mod) + k * sizeof( pt_pattern_s)); -/* while (1) { - }*/ - //while(1) {} - - //mod = (pt_mod_s*)&__end__; - mod = (pt_mod_s*)malloc(sizeof(pt_mod_s)); - memset(mod, 0, sizeof(*mod)); - - - mod->numpat = k; - //mod->pattern = ( pt_pattern_s *) (mod + 1); - - for (i = 0; i < 4; ++i) - { - mod->chan[i].sp = -1; - } - - mod->chan[0].pan = 0; - mod->chan[1].pan = 255; - mod->chan[2].pan = 255; - mod->chan[3].pan = 0; - - mod->mastervolume = 256; - // mod->flags = 0; //MODF_ALLOWPANNING; - mod->flags = MODF_ALLOWFILTER; //MODF_ALLOWPANNING; - - mod->speed = 6; - mod->ciaspeed = 125; - // mod->freq = freq; - mod->vbllen = FREQ / 50; - -#if 0 - for(i = 0; i < 20; ++i) - mod->name[i] = buf[i]; -#endif - - - /* samples */ - - // smallfs bp = buf + 20; - - modRAMfile.seek(20, SEEK_SET); - - - - for (i = 1; i < 32; ++i) - { - s = &mod->sample[i]; - modRAMfile.read(buf,30); -#ifdef DEBUG -// Serial.print("Name: "); -// for(l = 0; l < 22, buf[l]; ++l) { -// Serial.write(buf[l]); -// } -// Serial.println(""); -#endif - -#if 0 - for(l = 0; l < 22; ++l) - s->name[l] = bp[l]; -#endif - // SmallFS - read everything - j = buf[22]; - k = buf[23]; - s->length = ((j << 8) + k) << 1; -#ifdef DEBUG -// Serial.print("Sample "); -// Serial.print(i); -// Serial.print(" size is "); -// Serial.print(s->length); -// Serial.println(" bytes"); -#endif - j = buf[24]; - s->ft = j & 15; - j = buf[25]; - s->volume = j; - j = buf[26]; - k = buf[27]; - s->repeat = ((j << 8) + k) << 1; - j = buf[28]; - k = buf[29]; - s->replen = ((j << 8) + k) << 1; - bp += 30; - } - /* mod length */ - - - modRAMfile.seek(950, SEEK_SET); - modRAMfile.read(buf,1); - - - //j = buf[950]; - mod->length = buf[0];//j; - - /* positions */ - - modRAMfile.seek(952, SEEK_SET); - modRAMfile.read(buf,128); - - // bp = buf + 952; - bp=&buf[0]; - for (i = 0; i < 128; ++i) - { - j = *bp++; - mod->pos[i] = j; - } - - /* patterns */ - - /* - file.seek(1084); - - file.read(buf,256); // 64 * 4 - Serial.print("Loading patterns:"); - Serial.println(mod->numpat); - */ -#if 0 - - //bp = buf + 1084; - bp = &buf[0]; - unsigned offset = 1084; - - for (i = 0; i < mod->numpat; ++i) - { - for (i2 = 0; i2 < 64; ++i2) - { - for (i3 = 0; i3 < 4; ++i3) - { - Serial.print("PAT "); - Serial.print(i); Serial.print(" "); - Serial.print(i2); Serial.print(" "); - Serial.print(i3); Serial.print(" "); - Serial.println(offset); - offset+=4; - } - } - } -#endif - - Serial.println("Loading sample data ptr"); - /* ptrs to sampledata */ - - bp = (unsigned char*)(1084 + ((64*4*4)*mod->numpat)); - - for (i = 1; i < 32; ++i) - { - s = &mod->sample[i]; - - s->offset = (unsigned)bp; - bp += s->length; -#ifdef DO_CHECKS - if (bp - buf > bufsize) - { - return FALSE; /* sample ptr past end of file */ - } -#endif - - s->length <<= 14; /* include oversampling precision */ - s->repeat <<= 14; - s->replen <<= 14; - s->repend = s->repeat + s->replen; - } - - Serial.println("All loaded"); - /* init lowpass filter */ - mod->filter =FALSE; - -#ifdef DO_LOWPASS - mod->flags |= MODF_ALLOWFILTER; - - - tempf = 3.14159265358979 * 4000 / freq; - tempf = atan(tempf); - tempf = -(tempf-1)/(1+tempf); - mod->fltb = (float) tempf; - mod->flta = (float) ((1 - tempf) / 2); -#endif - - mod->state=PT_STATE_PLAYSONG; - - return mod; -} diff --git a/RetroCade_Sketch/modplayer.h b/RetroCade_Sketch/modplayer.h deleted file mode 100644 index dc45466..0000000 --- a/RetroCade_Sketch/modplayer.h +++ /dev/null @@ -1,52 +0,0 @@ -/*! - * @file modplayer.h - * Project modplayer Library - * @brief modplayer wrapper for the ptplay library for the ZPUino, ported by Alvaro Lopes - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ - -#ifndef LIB_MODPLAYER_H_ -#define LIB_MODPLAYER_H_ - -#include -#include -#include -#include "Arduino.h" -#include "SmallFS.h" -#include "cbuffer.h" -#include -#include "ramFS.h" -#include "ptplay.h" -//#include "RetroCade.h" -#include "retrocade_defs.h" - -class MODPLAYER -{ - public: - MODPLAYER(); - void setup(); - void loadFile(const char* name); - void play(boolean play); - boolean getPlaying(); - void audiofill(); - void zpu_interrupt(); - void volume(int volume); - private: - CircularBuffer audioBuffer; - unsigned underruns; - pt_mod_s *pt_init_smallfs(); - SmallFSFile modSmallFSfile; - File modSDfile; - RamFSFile modRAMfile; - char buf[128]; - pt_mod_s * mod; - boolean playing; - boolean fileLoaded; - kFileType fileType; -}; - - -#endif // LIB_MODPLAYER_H_ diff --git a/RetroCade_Sketch/ptplay.cpp b/RetroCade_Sketch/ptplay.cpp deleted file mode 100644 index ac24d41..0000000 --- a/RetroCade_Sketch/ptplay.cpp +++ /dev/null @@ -1,1599 +0,0 @@ -/* -** protracker 2.3a player -** (C) 2001, 2003 Ronald Hof, Timm S. M�ller & Per Johansson ;) -** -** TODO: check exact clipping behavior at places -** where finetuning is involved -*/ - -/* -Bugfixes so far: 6xx command -4xx command -E6x command -Fxx command (when setting F0x and Fxx on the same row) -E1x command -E2x command -E5x command -There are more fixes than these, but i forgot to write them here. ;-/ , especially under pt_dotick() - -Finally also supports EFx command. :) - - -The "Certified 100%" means that the effect works 100% when used in a single use mode. However -it�s not 100% sure it works in all conditions with combined effects. - - -\Per Johansson - -*/ - - -#include -#include -#include "ramFS.h" -#include "ptplay.h" -#include -#include -#include -#include - -#define CHNF_SLIDESKIP 0x0001 /* skip slide fx in first tick */ -#define CHNF_APPLYTONEP 0x0002 /* tone-portamento is active */ - -#define PER_LOW 113 /* Lowest allowable period */ -#define PER_HI 856 /* Highest allowable period */ - - - -static const unsigned char tab_funk[16]= -{ -0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128 - -}; - - -static const unsigned char tab_vib[32] = -{ -0,24,49,74,97,120,141,161, -180,197,212,224,235,244,250,253, -255,253,250,244,235,224,212,197, -180,161,141,120,97,74,49,24 -}; - - -static const short tab_tunes[16][36] = -{ -{856,808,762,720,678,640,604,570,538,508,480,453, -428,404,381,360,339,320,302,285,269,254,240,226, -214,202,190,180,170,160,151,143,135,127,120,113}, - -{850,802,757,715,674,637,601,567,535,505,477,450, -425,401,379,357,337,318,300,284,268,253,239,225, -213,201,189,179,169,159,150,142,134,126,119,113}, - -{844,796,752,709,670,632,597,563,532,502,474,447, -422,398,376,355,335,316,298,282,266,251,237,224, -211,199,188,177,167,158,149,141,133,125,118,112}, - -{838,791,746,704,665,628,592,559,528,498,470,444, -419,395,373,352,332,314,296,280,264,249,235,222, -209,198,187,176,166,157,148,140,132,125,118,111}, - -{832,785,741,699,660,623,588,555,524,495,467,441, -416,392,370,350,330,312,294,278,262,247,233,220, -208,196,185,175,165,156,147,139,131,124,117,110}, - -{826,779,736,694,655,619,584,551,520,491,463,437, -413,390,368,347,328,309,292,276,260,245,232,219, -206,195,184,174,164,155,146,138,130,123,116,109}, - -{820,774,730,689,651,614,580,547,516,487,460,434, -410,387,365,345,325,307,290,274,258,244,230,217, -205,193,183,172,163,154,145,137,129,122,115,109}, - -{814,768,725,684,646,610,575,543,513,484,457,431, -407,384,363,342,323,305,288,272,256,242,228,216, -204,192,181,171,161,152,144,136,128,121,114,108}, - -{907,856,808,762,720,678,640,604,570,538,508,480, -453,428,404,381,360,339,320,302,285,269,254,240, -226,214,202,190,180,170,160,151,143,135,127,120}, - -{900,850,802,757,715,675,636,601,567,535,505,477, -450,425,401,379,357,337,318,300,284,268,253,238, -225,212,200,189,179,169,159,150,142,134,126,119}, - -{894,844,796,752,709,670,632,597,563,532,502,474, -447,422,398,376,355,335,316,298,282,266,251,237, -223,211,199,188,177,167,158,149,141,133,125,118}, - -{887,838,791,746,704,665,628,592,559,528,498,470, -444,419,395,373,352,332,314,296,280,264,249,235, -222,209,198,187,176,166,157,148,140,132,125,118}, - -{881,832,785,741,699,660,623,588,555,524,494,467, -441,416,392,370,350,330,312,294,278,262,247,233, -220,208,196,185,175,165,156,147,139,131,123,117}, - -{875,826,779,736,694,655,619,584,551,520,491,463, -437,413,390,368,347,328,309,292,276,260,245,232, -219,206,195,184,174,164,155,146,138,130,123,116}, - -{868,820,774,730,689,651,614,580,547,516,487,460, -434,410,387,365,345,325,307,290,274,258,244,230, -217,205,193,183,172,163,154,145,137,129,122,115}, - -{862,814,768,725,684,646,610,575,543,513,484,457, -431,407,384,363,342,323,305,288,272,256,242,228, -216,203,192,181,171,161,152,144,136,128,121,114}, -}; - - -pt_mod_s * pt_load(char *filename, int freq) -{ - FILE *fp; - int len = 0; - pt_mod_s *mod; - - char *buf=0; - -if ((fp=fopen(filename,"rb"))) -{ -fseek(fp,0,SEEK_END); -len=ftell(fp); -fseek(fp,0,SEEK_SET); -buf=(char *)malloc(len); -fread(buf,len,1,fp); -fclose(fp); -} -if(buf==0) return 0; - - mod=pt_init((unsigned char *)buf,len,freq); - if(mod==0) free(buf); - //mod->buf=buf; - return mod; -} - -void pt_free(pt_mod_s * mod) -{ - if(mod==0) return; -// if(mod->buf!=0) free(mod->buf); - free(mod); -} - -/************************************************************************** -** -** numbytes/success = pt_init(mod, data, size, freq) -** Init module ure from data. If mod is NULL, returns the size -** of the required mod data ure. Otherwise, the return value is -** boolean and indicates whether initialization succeeded. -*/ -#if 0 - -pt_mod_s *pt_init(unsigned char *buf, int bufsize, int freq) -{ -unsigned char *bp; -int i, j, k,l; -double tempf; -pt_mod_s *mod; -pt_sample_s *s; -pt_pattern_s *pat; -int i2, i3; -pt_patterndata_s *p; - -if (buf == NULL) return NULL; -if (bufsize < 1084) return NULL; -/* M.K. signature */ - -bp = buf + 0x438; -if (!(bp[0] == 'M' && bp[1] == '.' && bp[2] == 'K' && bp[3] == '.')) return NULL; - -/* determine number of patterns */ - -k = 0; -bp = buf + 952; -for (i = 0; i < 128; ++i) -{ -j = *bp++; -if (j > k) k = j; -} -k++; -if (bufsize < 1084 + (k << 8)) -{ -return NULL; /* incomplete */ -} - -//if (mod == NULL) -//{ -/* return the required size in bytes */ -// return sizeof(*mod) + k * sizeof( pt_pattern_s); -//} - -mod=(pt_mod_s *)calloc(1,sizeof(*mod) + k * sizeof( pt_pattern_s)); -memset(mod, 0, sizeof(*mod)); -mod->numpat = k; -#ifndef EMBEDDED -mod->pattern = ( pt_pattern_s *) (mod + 1); -#endif - -for (i = 0; i < 4; ++i) -{ -mod->chan[i].sp = -1; -} - -mod->chan[0].pan = 0; -mod->chan[1].pan = 255; -mod->chan[2].pan = 255; -mod->chan[3].pan = 0; -mod->mastervolume = 256; -// mod->flags = 0; //MODF_ALLOWPANNING; -mod->flags = MODF_ALLOWFILTER; //MODF_ALLOWPANNING; - -mod->speed = 6; -mod->ciaspeed = 125; -#ifndef CONSTANT_FREQ -mod->freq = freq; -#endif -mod->vbllen = FREQ / 50; - - -for(i = 0; i < 20; ++i) -mod->name[i] = buf[i]; - - - -/* samples */ - -bp = buf + 20; -for (i = 1; i < 32; ++i) -{ -s = &mod->sample[i]; - -for(l = 0; l < 22; ++l) -s->name[l] = bp[l]; - -j = bp[22]; -k = bp[23]; -s->length = ((j << 8) + k) << 1; -j = bp[24]; -s->ft = j & 15; -j = bp[25]; -s->volume = j; -j = bp[26]; -k = bp[27]; -s->repeat = ((j << 8) + k) << 1; -j = bp[28]; -k = bp[29]; -s->replen = ((j << 8) + k) << 1; -bp += 30; -} - -/* mod length */ - -j = buf[950]; -mod->length = j; -/* positions */ - -bp = buf + 952; -for (i = 0; i < 128; ++i) -{ -j = *bp++; -mod->pos[i] = j; -} - -/* patterns */ - -bp = buf + 1084; -for (i = 0; i < mod->numpat; ++i) -{ -pat = mod->pattern + i; -for (i2 = 0; i2 < 64; ++i2) -{ -for (i3 = 0; i3 < 4; ++i3) -{ -p = &pat->data[i2][i3]; -j = *bp++; -k = *bp++; -p->period = ((j & 15) << 8) + k; -k = *bp++; -p->sample = (j & 240) + (k >> 4); -p->effect = k & 15; -j = *bp++; -p->efd1 = j >> 4; -p->efd2 = j & 15; -p->efboth = j; -} -} -} -/* ptrs to sampledata */ - -for (i = 1; i < 32; ++i) -{ -s = &mod->sample[i]; - -s->data = (char *)bp; -bp += s->length; - -if (bp - buf > bufsize) -{ -return FALSE; /* sample ptr past end of file */ -} -s->length <<= 14; /* include oversampling precision */ -s->repeat <<= 14; -s->replen <<= 14; -s->repend = s->repeat + s->replen; -} - - -/* init lowpass filter */ -mod->filter =FALSE; - -#ifdef DO_LOWPASS -mod->flags |= MODF_ALLOWFILTER; - -tempf = 3.14159265358979 * 4000 / freq; -tempf = atan(tempf); -tempf = -(tempf-1)/(1+tempf); -mod->fltb = (float) tempf; -mod->flta = (float) ((1 - tempf) / 2); -#endif - -mod->state=PT_STATE_PLAYSONG; - -return mod; -} - -#endif - -static int getperiod(int note, int finetune, int delta) -{ -int i = 0; -while (tab_tunes[0][i] != note) -i++; - -i += delta; -if (i > 35) -i = 35; - -return tab_tunes[finetune][i]; -} - - -/************************************************************************** -** -** pt_donote(mod) -** Interprete per new note -*/ - -static void pt_donote( RamFSFile &file, pt_mod_s *mod) -{ -int ppos, spos; -int i, j, k; -char UsePreviousVolume; -#ifdef EMBEDDED -//pt_pattern_s p; -pt_patterndata_s ptd; -unsigned char buf[4]; -#else -pt_pattern_s *p; -pt_patterndata_s *ptd; -#endif -pt_channel_s *c; -pt_sample_s *s; -int newsp; -//int repeat; -//int replen; - //static int debugpos=0; - - -if (mod->patdelay) -{ -mod->patdelay--; -} -else -{ - -c = mod->chan; - -mod->skiptopos = 0; - -ppos = mod->ppos; -spos = mod->spos; -mod->cppos=ppos; -mod->cspos=spos; - -#ifdef EMBEDDED -/* Load pattern data */ - -/* Each pattern has 64 positions, 4 channels, each 4 bytes */ - -file.seek(PATTERN_OFFSET + (1024*mod->pos[spos]) + (16*ppos), SEEK_SET); - -#else -p = mod->pattern + mod->pos[spos]; /* pattern */ -ptd = p->data[ppos]; /* patterndata */ -#endif -for (i = 0; i < 4; ++i) -{ - -#ifdef EMBEDDED -/* Read in pattern data */ - -file.read(buf,4); -j = buf[0]; -k = buf[1]; -ptd.period = ((j & 15) << 8) + k; - -k = buf[2]; - -ptd.sample = (j & 240) + (k >> 4); -ptd.effect = k & 15; - -j = buf[3]; -ptd.efd1 = j >> 4; -ptd.efd2 = j & 15; - -ptd.efboth = j; -#endif - -#if 0 -// DEBUG -Serial.print(debugpos++); Serial.print(" "); -Serial.print(mod->pos[spos]); Serial.print(" "); -Serial.print(spos); Serial.print(" "); -Serial.print(ppos); Serial.print(" "); -Serial.print(ptd.period); Serial.print(" "); -Serial.print(ptd.sample); Serial.print(" "); -Serial.print(ptd.effect); Serial.println(" "); -#endif -#if 0 -Serial.print(PATTERN_OFFSET + (1024*mod->pos[spos]) + (16*ppos) ); Serial.print(" "); -Serial.print(" buf "); -Serial.print((unsigned)buf[0]); Serial.print(" "); -Serial.print((unsigned)buf[1]); Serial.print(" "); -Serial.print((unsigned)buf[2]); Serial.print(" "); -Serial.print((unsigned)buf[3]); -Serial.println(""); -#endif - -//Serial.println(""); - -s=0; -newsp = c->sp; - -/* next period and sample */ -k = ptd.period; -j = ptd.sample; - -UsePreviousVolume=FALSE; - -c->prevvol=c->basevol; /* Keep previous volume. */ -if(j!=0) -{ -c->prevsample=j; /* Keep previous sample nr. */ -} - - -/* -If someone does like Jogeir and sets the sample -once and then uses notes without a sample-nr, Protracker 3.xx does not support his -behaviour, but we should for compability as alot of trackers used this bug / feature. -*/ - -if ( k != 0 && j==0 ) /* Period is set, and sample nr is 0 */ -if( ptd.effect == 0 || ptd.effect == 12 || ptd.effect == 15 ) -{ -j=c->prevsample; -c->basevol = c->prevvol; -UsePreviousVolume=TRUE; -} - - - -/* Reset period to last base note if vibrato was on -** and no new period is given */ - -if( k != 0 && ptd.effect != 3 ) -{ -c->tpsrc=c->per; -} - - -/* Bugfix, for combined use of vibrato and volume sliding. */ -if ( k == 0 && c->avibspeed && ptd.effect != 4 && ptd.effect !=6 ) -{ -k = c->per; -c->tpsrc=c->per; -} - - -/* Temporary fix for vibrato problem. 4xx (now behaves like Protracker 2.3d) */ -if( c->avibspeed != 0 ) -{ -k = ptd.period; -} - - - -c->flags &= ~CHNF_APPLYTONEP; -c->avibspeed = 0; -c->atrespeed = 0; -c->dvol = 0; -c->dp = 0; -c->arp = 0; -c->delay = 0; -c->retrig = 0; - - - -if (j > 0 && j < 32) -{ - -/* new sample */ - -if (k) -{ -/* period given, ok */ -c->delaysample = 0; -c->sample = j; -} -else -{ -/* no period: delay this sample, but don't change it now */ -c->delaysample = j; -} - -s = &mod->sample[j]; - - -j = s->volume; - -if (j > 63) -j = 63; - -if( UsePreviousVolume == FALSE ) -{ -c->basevol = j; -c->vol = j; -} - - -if (k == 0) -goto noper; /* no sample restart if no period */ - -c->ft = s->ft; /* set finetune */ -newsp = 0; /* restart sample */ -} -else -{ -if (k == 0) -goto noper; -} - -/* new period */ - -c->arpbase = k; /* ...is also new arpeggio baseperiod */ -c->avibindex = 0; -c->atreindex = 0; - -j = ptd.effect; /* get effect */ - - -if (j == 3 || j == 5) -goto noper; /* don't override active tonesliding */ - - -newsp = 0; /* restart sample */ - -k = getperiod(k, c->ft, 0); - -c->per = k; /* new period */ -c->tptarget = k; /* is also toneportamento target */ -c->tpsrc=k; - - - - -/* new period */ -//c->freq = (16383 / (50 * 0.000000279365)) / (mod->freq / 50 * k); - -c->freq = 1172874197 / (FREQ * k / 50); - -noper: - - -/* Do Funkit here */ - -s = &mod->sample[c->sample]; -j=c->glissando >> 4; - -if(j != 0) -{ -#if 0 /* NOTE: we cannot modify samples down there */ -j=tab_funk[j]; -c->funkoffset+=j; - -if( !(c->funkoffset & 7)) -{ -repeat=s->repeat >> 14; -replen=s->replen >> 14; - -c->funkoffset=0; -c->funkcnt+=1; - -if( !(c->funkcnt <= replen) ) -{ -c->funkcnt=0; -} - -/* Only modify sample if it has a loop, important */ -if(repeat !=0 ) -{ -/* Manipulates sample-data, nasty. ;) */ -j=-1; -j=j-s->data[repeat+c->funkcnt]; -s->data[repeat+c->funkcnt]=j; -c->sp=newsp=c->oldsp=c->sp+c->funkcnt; -} -} -#endif -} -/* End of Funkit */ - - - - -/* interprete effect command */ - - -j = ptd.efboth; - - -switch (ptd.effect & 15) -{ -/* 0xx - Arpeggio Certified 100% */ -case 0: -if(j) -c->arp=j; -break; - -/* 1xx - Portamento Up Certified 100% */ -case 1: -c->dp = -j; -c->flags |= CHNF_SLIDESKIP; -break; - -/* 2xx - Portamento Down Certified 100% */ -case 2: -c->dp = j; -c->flags |= CHNF_SLIDESKIP; -break; - -/* 3xx - Toneportamento Certified 100% */ -case 3: -if (j) -c->dtp=j; - -j = ptd.period; -if(j) -{ -c->tptarget = getperiod(j, c->ft, 0); -} -if (c->dtp) -{ -c->flags |= CHNF_APPLYTONEP | CHNF_SLIDESKIP; -} -newsp = c->sp; // no NOT reset samplepos -break; - -/* 4xx - Vibrato Certified 100% */ -case 4: -j=ptd.efd2; -if(j) -c->vibdepth=j; -j=ptd.efd1; -if (j) -c->vibspeed=j; -c->avibspeed=c->vibspeed; -c->flags |= CHNF_SLIDESKIP; -break; - - -/* 5xx - Toneportamento + Volslide Certified 100% */ -case 5: -c->dvol=-(j & 15); -j >>= 4; -if(j) -c->dvol=j; - -j = ptd.period; /* new target period? */ -if(j) -{ -c->tptarget = getperiod(j, c->ft, 0); -} -if (c->dtp) -{ -c->flags |= CHNF_APPLYTONEP | CHNF_SLIDESKIP; -} -newsp = c->sp; /* no NOT reset samplepos */ -break; - - -/* 6xx - Vibrato + Volslide Certified 100% */ -case 6: -c->dvol=-(j & 15); -j >>=4; -if(j) -c->dvol=j; - -c->avibspeed=c->vibspeed; -c->flags |= CHNF_SLIDESKIP; -break; - - -/* 7xx - Tremolo Certified 100% */ -case 7: -j=ptd.efd2; -if(j) -c->tredepth=j << 1; -j=ptd.efd1; -if(j) -c->trespeed=j; -c->atrespeed=c->trespeed; -break; - - -/* 9xx - pt_sample_soffset Certified 100% */ -case 9: -if(ptd.period) -{ -j <<= 22; -if(j == 0) -j=c->oldsp; -if(s==NULL) -j+=c->oldsp; -c->oldsp=j; -newsp=j; -} -break; - - -/* Axx - Volumeslide Certified 100% */ -case 10: -c->dvol=-(j & 15); -j >>= 4; -if(j) -c->dvol=j; -break; - - -/* Bxx - Position jump Certified 100% */ -case 11: -spos=j-1; -ppos=63; -break; - - -/* Cxx - Set volume Certified 100% */ -case 12: -if(j > 63) -j = 63; -c->basevol=j; -break; - - -/* Dxx - pt_pattern_sbreak Certified 100% */ -case 13: -if(j) -{ -j=(j >> 4) * 10 + (j & 15); -if (j < 64) -{ -mod->skiptopos=j; -break; -} -} -ppos=63; -break; - - - -/* Exx */ -case 14: -k=ptd.efd1; -j=ptd.efd2; - -switch (k & 15) -{ - -/* E0x - Filter On / Off Certified 100% */ -case 0: -if(mod->flags & MODF_ALLOWFILTER) -{ -mod->filter = (j & 1) ^ 1; -} -break; - - -/* E1x - Fineslide up Certified 100% */ -case 1: -if(j) -{ -j=-j; -j += c->per; -c->tptarget=j; -c->per=j; -c->freq = 1172874197 / (FREQ * j / 50); -} -break; - -/* E2x - Fineslide down Certified 100% */ -case 2: -if(j) -{ -j += c->per; -c->tptarget=j; -c->per=j; -c->freq = 1172874197 / (FREQ * j / 50); -} -break; - -/* E3x - Glissando control Certified 100% */ -case 3: -c->glissando=j; -break; - -/* E4x - Vibrato control Certified 100% */ -case 4: -c->vibwave=j; -break; - - -/* E5x = Set Finetune Certified 100% */ -case 5: -j=ptd.period; -if(j) -{ -newsp=0; -k=ptd.efd2; -c->ft=k; -j=getperiod(j,c->ft,0); -c->per=j; -c->tptarget=j; -c->freq = 1172874197 / (FREQ * j / 50); -} -break; - - -/* E6x - pt_pattern_sloop Certified 100% */ -case 6: -if(c->loopflg==0) -if(j==0) -{ -c->loopstart=ppos; -c->loopflg=1; -break; -} - -/* Countdown */ -if (j != 0) -{ -if(c->loopflg!=2) -c->loopcount=j; - -c->loopflg=2; -if(c->loopcount <=0) -{ -c->loopcount=0; -c->loopflg=0; -break; -} -else -{ -ppos=c->loopstart-1; -spos--; -c->loopcount--; -break; -} -} -break; - -/* E7x - Tremolo control Certified 100% */ -case 7: -c->tremwave=j; -break; - -/* E9x - Retrig note Certified 100% */ -case 9: -newsp=0; -c->retrig=j; -c->delay=j+1; -break; - -/* EAx - Finevol up Certified 100% */ -case 10: -j+=c->basevol; -if(j > 63) -j=63; -c->basevol=j; -c->vol=j; -break; - -/* EBx - Finevol down Certified 100% */ -case 11: -j=c->basevol-j; -if(j < 0) -j=0; -c->basevol=j; -c->vol=j; -break; - -/* ECx - Notecut Certified 100% */ -case 12: -c->cutoff=j+1; -break; - -/* EDx - Notedelay Certified 100% */ -case 13: -if(ptd.period) -{ -c->delay=j+1; -newsp=c->sp; -} -break; - -/* EEx - pt_pattern_sdelay Certified 100% */ -case 14: -mod->patdelay=j; -break; - - -/* EFx - Invert loop Certified 100% */ -case 15: -{ -c->glissando=j << 4; -} -break; - - -} /* End switch Exx commands */ -break; - -/* Fxx - Set speed Certified 100% */ -case 0xF: -if(j >= 32) -{ -mod->ciaspeed=j; -mod->vbllen=FREQ * 60 / (24 * j); -break; /* Bugfix (mod.stave 2 control / polka brothers) */ -} -else -if(j > 0) -{ -mod->speed=j; -} -else -{ -mod->flags |= MODF_SONGEND; - -if(mod->flags & MODF_DOSONGEND) -{ -mod->songloopcount++; -} -} -break; -} -c->sp=newsp; -c++; -// ptd++; // No need, we will read next pattern channel -} - - -/* handle pattern and song position and skipping */ -j = mod->skiptopos; -if(j) -{ -ppos=j; -} -else -{ -ppos=(ppos+1) & 63; -if(ppos) -goto nopwrap; -} - -if(mod->state==PT_STATE_PLAYSONG) spos++; - -if (spos >= mod->length) -{ -spos=0; -mod->flags |= MODF_SONGEND; -mod->songloopcount++; -} -mod->spos=spos; -nopwrap: -mod->ppos=ppos; - -} - -} - - - -/************************************************************************** -** -** pt_dotick(mod) -** Interprete per tick -*/ - -static void pt_dotick( RamFSFile &file, pt_mod_s *mod) -{ - -int i, j, k; -pt_channel_s *c = &mod->chan[0]; - - -if (mod->tick == 0) - { - if(mod->state!=PT_STATE_STOP) -pt_donote(file, mod); - mod->tick=mod->speed; - } - -mod->tick--; - -for (i = 0; i < 4; ++i) -{ - - -if (c->flags & CHNF_SLIDESKIP) -{ -c->flags &= ~CHNF_SLIDESKIP; /* no slide fx in first tick */ -goto chperdone; -} - - -/* persistent changes to base period (slide, tone portamento) */ - -j = c->dp; /* delta pitch (slide) */ -if (j) -goto chdodelta; - - -if (c->flags & CHNF_APPLYTONEP) -goto chtonep; /* apply tone portamento */ - - -/* nonpersistent changes to base period (arpeggio, vibrato) */ - -k = c->arp; /* arpeggio */ -if (k) -{ -j = mod->tick % 3; -k = (k >> ((2 - j) << 2)) & 15; /* get arpeggio nibble */ -j = c->arpbase; /* arpeggio base period */ -j = getperiod(j, c->ft, k); /* find finetuned + arpeggio offset */ -//if (j < 113) j = 113; -goto newperiod; -} - - -k = c->avibspeed; - -if (k == 0) -goto chperdone; - - -j = c->avibindex; -k += j; -c->avibindex = k & 63; - - -switch (c->vibwave & 3) -{ -default: -k = j << 3; -if (j >= 32) k -= 512; -break; - -case 2: -k = 255; -goto vibchk; - -case 0: -k = tab_vib[j & 31]; - -vibchk: -if (j >= 32) k = -k; -break; -} - - -j = (c->vibdepth * k) >> 7; -j += c->per; - - -if (j < PER_LOW) -j = PER_LOW; -if (j > PER_HI) -j = PER_HI; - -c->freq = 1172874197 / (FREQ * j / 50); - -c->tpsrc=j; - -goto chperdone; - -chtonep: -j = c->tptarget; /* target period */ -j -= c->tpsrc; /* - temporary source period */ - -if(j == 0) -goto chperdone; /* Reached */ - -k = c->dtp; - -if (j < 0) -{ -if (-k > j) -j = -k; /* period goes down (slide up) */ -} -else -{ -if (k < j) -j = k; /* period goes up (slide down) */ -} - - -chdodelta: -j += c->tpsrc; - -if(j < PER_LOW) -j = PER_LOW; -if(j > PER_HI) -j = PER_HI; - -c->per = j; -c->tpsrc=j; - - -if(c->glissando) -{ -// find closest _finetuned_ note - -k = 0; -while (tab_tunes[c->ft][k] > j) k++; -j = tab_tunes[c->ft][k]; -} - - -newperiod: - -c->freq = 1172874197 / (FREQ * j / 50); - - -chperdone: - -j = c->basevol; - -k = c->dvol; -if (k) /* apply volslide */ -{ -j += k; -if (j > 63) j = 63; -if (j < 0) j = 0; -c->basevol = j; -} - -k = c->atrespeed; - -if (k) /* apply tremolo */ -{ -j = c->atreindex; -k += j; -c->atreindex = k & 63; -switch (c->tremwave & 3) -{ -default: -k = j << 3; -if (j >= 32) k -= 512; -break; -case 2: -k = 255; -goto tremchk; - -case 0: -k = tab_vib[j & 31]; -tremchk: -if (j >= 32) k = -k; -break; -} -j = (k * c->tredepth) >> 8; -j += c->basevol; -if (j > 63) j = 63; -if (j < 0) j = 0; -} - - -if (c->cutoff) -{ -if (--c->cutoff == 0) -{ -j = c->basevol = 0; /* turn off volume */ -} -} - -if (c->delay) -{ -if (--c->delay == 0) -{ -c->sp = 0; -c->delay = c->retrig; -} -} - -c->vol = j; -c++; -} -} - -/************************************************************************** -** -** pt_render(mod, destbuf1, destbuf2, bufmodulo, numsmp, freqscale, depth, channels) -** Render protracker to sample buffer -** -** destbuf1 destptr for channel 1 -** destbuf2 destptr for channel 2 (may be NULL) -** bufmodulo number of bytes to proceed from one sample to the next -** freqscale: 1, 2 oversampling factor -** depth: 8, 16 number of bits per output sample -** channels: 1, 2 mono or stereo -*/ - -LIBAPI void pt_render( RamFSFile &file, pt_mod_s *mod, char *buf, char *buf2, -int bufmodulo, int numsmp, int scale, int depth, int channels) -{ -int writeselect = 0; -int accul = 0; -int accur = 0; -int i, j,k,sr, sl; -pt_channel_s *c; -pt_sample_s* s; -#ifdef DO_LOWPASS -float inp, outp; -float flta; -float fltb; -float *fltpip; -float *fltpop; -#endif - -numsmp *= scale; - -while ((scale >>= 1)) writeselect += 4; - -writeselect += ((depth >> 3) - 1) << 1; -writeselect += channels - 1; - -while (numsmp--) -{ - -#ifdef DO_SONGEND -if (mod->songloopcount && (mod->flags & MODF_DOSONGEND)) -{ -sr = 0; /* mute */ -sl = 0; -} -else -#endif -{ -c = &mod->chan[0]; -#if 0 -Serial.print("BPOS "); -Serial.print(mod->bpos); - -Serial.print(" VBLLEN "); -Serial.println(mod->vbllen); -#endif - -j = mod->bpos - mod->vbllen; -if (j >= 0) -{ -mod->bpos = j; -pt_dotick(file,mod); /* apply changes per tick */ -} - -mod->bpos++; - -/* mix */ - -sl = 0; - -if (writeselect & 1) -{ -/* stereo */ - -sr = 0; -for (i = 0; i < 4; ++i) -{ -j = c->sp; -if (j >= 0) -{ -s = &mod->sample[c->sample]; -k = s->replen; - -if (k > 32768) -{ -if (j >= s->repend) -{ -j -= k; -k = c->delaysample; -if (k) c->sample = k; -} -} -else -{ -if (j >= s->length) -{ -c->sp = -1; -continue; -} -} - -c->sp = j + c->freq; - -/* Load sample data */ -file.seek(s->offset + (j>>14) ,SEEK_SET); -signed char dat; - file.read(&dat,1); -// j = c->vol * (s->data[j >> 14]); -j = c->vol * dat;//(s->data[j >> 14]); - -k = c->pan; -sr += j * k; -sl += j * (255 - k); -} -c++; -} - -/* <<8(8->16bit) >>2(numchannels) >>6(volume) >>7(panning) */ - -// sr >>= 8; // Seem to improve audio, however if this is wrong, please restore previous 7 -// sl >>= 8; -sr >>= 7; -sl >>= 7; - -#ifdef DO_LOWPASS -if (mod->filter) -{ -flta = mod->flta; -fltb = mod->fltb; -fltpip = mod->fltpi; -fltpop = mod->fltpo; - -inp = sl; -outp = flta * (inp + *fltpip) + fltb * *fltpop; -*fltpip++ = inp; -*fltpop++ = outp; -inp = outp; -outp = flta * (inp + *fltpip) + fltb * *fltpop; -*fltpip++ = inp; -*fltpop++ = outp; -sl = outp; - -inp = sr; -outp = flta * (inp + *fltpip) + fltb * *fltpop; -*fltpip++ = inp; -*fltpop++ = outp; -inp = outp; -outp = flta * (inp + *fltpip) + fltb * *fltpop; -*fltpip = inp; -*fltpop = outp; -sr = outp; -} -#endif - - -#ifdef DO_CLAMPING -if (sl < -32768) sl = -32768; -if (sl > 32767) sl = 32767; -if (sr < -32768) sr = -32768; -if (sr > 32767) sr = 32767; -#endif - - -} -else -{ -/* mono */ - -for (i = 0; i < 4; ++i) -{ -j = c->sp; -if (j >= 0) -{ -s = &mod->sample[c->sample]; -k = s->replen; - -if (k > 32768) -{ -if (j >= s->repend) -{ -j -= k; -k = c->delaysample; -if (k) c->sample = k; -} -} -else -{ -if (j >= s->length) -{ -c->sp = -1; -continue; -} -} - -c->sp = j + c->freq; - -file.seek(s->offset + (j>>14) ,SEEK_SET); -signed char dat; -file.read(&dat,1); -#if 0 -Serial.print("NS "); -Serial.print(c->sample); -Serial.print(" off "); -Serial.println(s->offset); - -Serial.print("SAMP: data for j=="); Serial.print(j>>14); -Serial.print(": "); -Serial.print((int)dat); -Serial.print(" vol "); -Serial.println(c->vol); -#endif -//sl += (short) c->vol * (short) (s->data[j >> 14]); - - // short ?? -sl += (int) c->vol * (int)dat; -} -c++; -} - -#ifdef DO_LOWPASS -if (mod->filter) -{ - -flta = mod->flta; -fltb = mod->fltb; -fltpip = mod->fltpi; -fltpop = mod->fltpo; - -inp = sl; -outp = flta * (inp + *fltpip) + fltb * *fltpop; -*fltpip++ = inp; -*fltpop++ = outp; -inp = outp; -outp = flta * (inp + *fltpip) + fltb * *fltpop; -*fltpip = inp; -*fltpop = outp; -sl = outp; -} -#endif - -#ifdef DO_CLAMPING -if (sl < -32768) sl = -32768; -if (sl > 32767) sl = 32767; -#endif - -sr = sl; -} -} - -/* write to destination */ - -#ifdef DO_MASTERVOLUME -j = mod->mastervolume; - unsigned val; -switch (writeselect & 7) -{ -case 0: *buf = (j * ((sr + sl) >> 1)) >> 16; /* 1-8-mono */ -break; - -case 1: *buf = (j * sr) >> 16; /* 1-8-stereo */ -*buf2 = (j * sl) >> 16; -break; - -case 2: //*(short *) buf = (j * (sr + sl)) >> 9; /* 1-16-mono */ -val = (j * (sr + sl)) >> 9; -//Serial.print("D: "); -//Serial.println(val); -buf[0] = val; - buf[1] = val >> 8; -break; - -case 3: -*(short *) buf = (j * sr) >> 8; /* 1-16-stereo */ -*(short *) buf2 = (j * sl) >> 8; -break; - -case 4: accul += sr + sl; /* 2-8-mono */ -if (numsmp & 1) continue; -*buf = (accul * j) >> 18; -accul = 0; -break; - -case 5: accur += sr; /* 2-8-stereo */ -accul += sl; -if (numsmp & 1) continue; -*buf = (accur * j) >> 17; -*buf2 = (accul * j) >> 17; -accur = 0; -accul = 0; -break; - -case 6: accul += sr + sl; /* 2-16-mono */ -if (numsmp & 1) continue; -*(short *) buf = (accul * j) >> 10; -accul = 0; -break; - -case 7: accur += sr; /* 2-16-stereo */ -accul += sl; -if (numsmp & 1) continue; -*(short *) buf = (accur * j) >> 9; -*(short *) buf2 = (accul * j) >> 9; -accur = 0; -accul = 0; -break; -} -#else -switch (writeselect & 7) -{ -case 0: *buf = ((sr + sl) >> 1) >> 8; /* 1-8-mono */ -break; - -case 1: *buf = (j * sr) >> 8; /* 1-8-stereo */ -*buf2 = (j * sl) >> 8; -break; - -case 2: *(short *) buf = (sr + sl) >> 1; /* 1-16-mono */ -break; - -case 3: *(short *) buf = sr; /* 1-16-stereo */ -*(short *) buf2 = sl; -break; - -case 4: accul += sr + sl; /* 2-8-mono */ -if (numsmp & 1) continue; -*buf = accul >> 10; -accul = 0; -break; - -case 5: accur += sr; /* 2-8-stereo */ -accul += sl; -if (numsmp & 1) continue; -*buf = accur >> 9; -*buf2 = accul >> 9; -accur = 0; -accul = 0; -break; - -case 6: accul += sr + sl; /* 2-16-mono */ -if (numsmp & 1) continue; -*(short *) buf = accul >> 2; -accul = 0; -break; - -case 7: accur += sr; /* 2-16-stereo */ -accul += sl; -if (numsmp & 1) continue; -*(short *) buf = accur >> 1; -*(short *) buf2 = accul >> 1; -accur = 0; -accul = 0; -break; -} -#endif - -buf += bufmodulo; -buf2 += bufmodulo; -} -} diff --git a/RetroCade_Sketch/ptplay.h b/RetroCade_Sketch/ptplay.h deleted file mode 100644 index 5d7b4ad..0000000 --- a/RetroCade_Sketch/ptplay.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef _PTREPLAY_H -#define _PTREPLAY_H - -/* -** protracker 2.3a player -** (C) 2001, 2003 Ronald Hof and Timm S. Mueller -*/ - -class SmallFSFile; -class RamFSFile; - -#define CONSTANT_FREQ -#define FREQ 17000 -#define EMBEDDED -#define PATTERN_OFFSET 1084 - -#define SKIP_NAMES - -//#define DO_LOWPASS /* emulate $E0 */ -#define DO_SONGEND /* handle song end */ -#define DO_MASTERVOLUME /* use mastervolume */ -#define DO_CLAMPING /* clamp output */ -#undef DO_PANNING /* use $8 for panning */ - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef NULL -#define NULL 0 -#endif - -#ifndef LIBAPI -#define LIBAPI -#endif - -#define MODF_DOSONGEND 0x0001 /* perform song-end detection */ -#define MODF_ALLOWPANNING 0x0002 /* allow mod to use command $8 for panning */ -#define MODF_ALLOWFILTER 0x0004 /* allow mod to set lowpass filter */ -#define MODF_SONGEND 0x0008 /* songend occured */ - -#define PT_STATE_PLAYSONG 1 -#define PT_STATE_STOP 2 -#define PT_STATE_PLAYPATTERN 3 - -typedef struct -{ -//char name[32]; -//signed char *data; - unsigned offset; -int length, repeat, replen, repend; /* <<14, includes oversampling precision */ -int ft; -int volume; -int pad; -}pt_sample_s; /* 32 bytes */ - -typedef struct -{ -int sample, prevsample, sp, per, freq, oldsp; -int dp, basevol,prevvol, vol, dvol, pan, ft; -unsigned int flags; -int dtp, tptarget, tpsrc; -int retrig, cutoff, delay; -int arp, arpbase; -int vibspeed, vibdepth, avibspeed, avibindex; -int trespeed, tredepth, atrespeed, atreindex; -int vibwave, tremwave, glissando, funkoffset,funkcnt; -int delaysample; -int loopstart, loopcount, loopflg; -} pt_channel_s; - -typedef struct -{ -int period, sample; -unsigned char effect, efd1, efd2, efboth; -int pad; -} pt_patterndata_s; /* 16 bytes */ - -typedef struct -{ -pt_patterndata_s data[64][4]; -}pt_pattern_s; - -typedef struct -{ -pt_sample_s sample[32]; -pt_channel_s chan[4]; -int pos[128]; -#ifndef SKIP_NAMES -char name[32]; -#endif -#ifndef EMBEDDED -pt_pattern_s *pattern; -#endif -unsigned int flags; -int numpat; -int length; -#ifndef CONSTANT_FREQ -int freq; -#endif -int vbllen; -int mastervolume; -int spos, ppos, speed, ciaspeed, bpos, tick; - -int cspos,cppos; -int patdelay, skiptopos, filter; -int songloopcount; -#ifdef DO_LOWPASS -float flta, fltb; -float fltpi[4]; -float fltpo[4]; -#endif -//char *buf; -int state; -} pt_mod_s; - -#ifdef __cplusplus -extern "C" { -#endif - -//LIBAPI unsigned int pt_init( pt_mod_s *pmod, unsigned char *buf, int bufsize, int freq); -LIBAPI void pt_render(RamFSFile&,pt_mod_s *pmod, char *buf, char *buf2, int bufmodulo, int numsmp, int scale, int depth, int channels); -pt_mod_s * pt_load(char *filename, int freq); -void pt_free(pt_mod_s * mod); -pt_mod_s *pt_init(unsigned char *buf, int bufsize, int freq); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/RetroCade_Sketch/ramFS.cpp b/RetroCade_Sketch/ramFS.cpp deleted file mode 100644 index 18bb195..0000000 --- a/RetroCade_Sketch/ramFS.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/*! - * @file ramFS.cpp - * Project RamFS Library - * @brief Allows SD or SmallFS files to be loaded into SDRAM. - * Version 1.0 - * @author Jack Gassett - * @date 11/10/12 - * License GPL - */ - -#include "ramFS.h" -#include -#ifdef __linux__ - -#include -#include -#include -#include -#include - -#define BE32(x) be32toh(x) - -#else - -#include "WProgram.h" - -#define BE32(x) x - -#endif - -#undef RAMFSDEBUG - -File modSDfile; - -extern void*__end__; -unsigned long *mbuf = (unsigned long*)&__end__+80000; - -RamFSFile::RamFSFile(){ - -} - -void *RamFSFile::zpuinomalloc(unsigned long size) -{ - void *ret = mbuf; - mbuf+=(size); - return ret; -} - -void RamFSFile::setInit(boolean active) -{ -// initState = active; -} -void RamFSFile::init() -{ -// Serial.println("Running malloc."); -// moddata = (unsigned char *)zpuinomalloc(500000*sizeof(unsigned char)); -// memset(moddata, 0, 500000*sizeof(unsigned char)); -// initState = true; -} - -int RamFS_class::begin() -{ - return 0; -} - -void RamFS_class::seek_if_needed(unsigned long address) -{ - -} - -unsigned RamFS_class::readByte(unsigned long address) -{ - return 0; - -} - - -void RamFS_class::read(unsigned long address, void *target, unsigned long size) -{ - -} - -RamFSFile RamFS_class::open(SmallFSFile *file) -{ - //Serial.println("In RamFS.open"); - return RamFSFile(file); -} - -RamFSFile::RamFSFile(SmallFSFile *file) -{ - filesize = file->size(); - file->seek(0x0, SEEK_SET); - moddata = (unsigned char *)malloc(filesize*sizeof(unsigned char)); - memset(moddata, 0, filesize*sizeof(unsigned char)); - file->read(&moddata[0], filesize); -} - -RamFSFile RamFS_class::open(File *file) -{ - return RamFSFile(file); -} - -RamFSFile::RamFSFile(File *file) -{ - unsigned long i = 0; - filesize = file->size(); - file->seek(0x0); - moddata = (unsigned char *)malloc(filesize*sizeof(unsigned char)); - memset(moddata, 0, filesize*sizeof(unsigned char)); - //file->read(&moddata[0], filesize); //TODO: Use this more efficient form when the SD library is fixed. - while (file->available()) { - moddata[i] = file->read(); - i++; - } -} - -int RamFSFile::read(void *buf, unsigned long s) -{ - - if (seekpos==filesize) - return 0; /* EOF */ - - if (s + seekpos > filesize) { - s = filesize-seekpos; - } - memcpy(buf, moddata+seekpos, s); - - seekpos+=s; - return s; -} - - -void RamFSFile::seek(unsigned long pos, int whence) -{ - unsigned long newpos; - - if (whence==SEEK_SET) - newpos = pos; - else if (whence==SEEK_CUR) - newpos = seekpos + pos; - else - newpos = filesize + pos; - - if (newpos>filesize) - newpos=filesize; - - if (newpos<0) - newpos=0; - - seekpos=newpos; -} - -RamFS_class RamFS; - diff --git a/RetroCade_Sketch/ramFS.h b/RetroCade_Sketch/ramFS.h deleted file mode 100644 index d49d804..0000000 --- a/RetroCade_Sketch/ramFS.h +++ /dev/null @@ -1,127 +0,0 @@ -/*! - * @file ramFS.h - * Project RamFS Library - * @brief Allows SD or SmallFS files to be loaded into SDRAM. - * Version 1.0 - * @author Jack Gassett - * @date 11/10/12 - * License GPL - */ - -#ifndef __RAMFS_H__ -#define __RAMFS_H__ - -#ifdef __linux__ - -#else -#include "zpuino.h" -#endif - -#include -#include "SmallFS.h" - -#ifndef SEEK_SET -# define SEEK_SET 0 -# define SEEK_CUR 1 -# define SEEK_END 2 -#endif - -/** - * @brief RAMFS File Class - */ -class RamFSFile -{ -public: - RamFSFile(); - RamFSFile(File *file); - RamFSFile(SmallFSFile *file); - static void setInit(boolean active); - //RamFSFile(unsigned o,unsigned size): flashoffset(o),filesize(size),seekpos(0) {} - /** - * @brief Check if file was successfuly opened. - * @return true on success, false otherwise - */ - //bool valid() { return flashoffset>=0;}//!=-1; } - - /** - * @brief Read a chunk of data from file. - * @param buf The buffer where to store data - * @param size The number of bytes to read from file. - * @return The number of bytes read, 0 for EOF. - */ - int read(void *buf, unsigned long size); - /** - * @brief Seek current file position - * @param pos The required position - * @param whence Where to perform seek. Either SEEK_SET, SEEK_CUR or SEEK_END - */ - void seek(unsigned long pos, int whence); - /** - * @brief Get the file size. - * @return The file size. - */ - inline unsigned long size() const { return filesize; } - /** - * @brief Read a chunk of data from file, using a callback function. - * The function will be called for every byte read. - * @param size The number of bytes to read from file. - * @param callback The callback function to call - * @param data The data parameter to pass to callback function. - * @return The number of bytes read, 0 for EOF. - */ - - //int readCallback(int size, void (*callback)(unsigned char, void*), void *data); - - /** - * @brief Read a single byte - */ - unsigned readByte(); - static void *zpuinomalloc(unsigned long size); - -private: - void init(); - int flashoffset; - unsigned long filesize; - unsigned long seekpos; - unsigned char *moddata; - static boolean initState; -}; - -/** - * @brief Main filesystem class - */ -class RamFS_class { - friend class RamFSFile; -public: - /** - * @brief Initialize the RamFS filesystem - * @return 0 on success, -1 otherwise - */ - int begin(); - -protected: - - -protected: - void read(unsigned long address, void *target, unsigned long size); - void seek(unsigned long address) { seek_if_needed(address); } - unsigned readByte(unsigned long address); -public: - /** - * @brief Open a file on the filesystem. - * @param name The file name - * @return A new RamFSFile object. You should call valid() to check - * if file was successfully open. - */ - RamFSFile open(File *file); - RamFSFile open(SmallFSFile *file); - -private: - void seek_if_needed(unsigned long address); - -}; - -extern RamFS_class RamFS; - -#endif - diff --git a/RetroCade_Sketch/retrocade_defs.h b/RetroCade_Sketch/retrocade_defs.h deleted file mode 100644 index fa14409..0000000 --- a/RetroCade_Sketch/retrocade_defs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef LIB_RETROCADEDEFS_H_ -#define LIB_RETROCADEDEFS_H_ - -enum kFileType { - SmallFSType = 0, - SDFSType = 1, -}; - -#endif // LIB_RETROCADEDEFS_H_ diff --git a/RetroCade_Sketch/sid.cpp b/RetroCade_Sketch/sid.cpp deleted file mode 100644 index 6aed58e..0000000 --- a/RetroCade_Sketch/sid.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/*! - * @file SID.cpp - * Project C64 SID Library - * @brief SID Library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ -#include "SID.h" - -const int SID::MIDI2freq[] = {//MIDI note number - 291, 291, 291, 291, 291, 291, 291, 291,//0-7 - 291, 291, 291, 291, 291, 291, 308, 326,//8-15 - 346, 366, 388, 411, 435, 461, 489, 518,//16-23 - 549, 581, 616, 652, 691, 732, 776, 822,//24-31 - 871, 923, 978, 1036, 1097, 1163, 1232, 1305,//32-39 - 1383, 1465, 1552, 1644, 1742, 1845, 1955, 2071,//40-47 - 2195, 2325, 2463, 2610, 2765, 2930, 3104, 3288,//48-55 - 3484, 3691, 3910, 4143, 4389, 4650, 4927, 5220,//56-63 - 5530, 5859, 6207, 6577, 6968, 7382, 7821, 8286,//64-71 - 8779, 9301, 9854, 10440, 11060, 11718, 12415, 13153,//72-79 - 13935, 14764, 15642, 16572, 17557, 18601, 19709, 20897,//80-87 - 22121, 23436, 24830, 26306, 27871, 29528, 31234, 33144,//88-95 - 35115, 37203, 39415, 41759, 44242, 46873, 49660, 52613,//96-103 - 55741, 59056, 62567, 66288, 66288, 66288, 66288, 66288,//104-111 - 66288, 66288, 66288, 66288, 66288, 66288, 66288, 66288,//112-119 - 66288, 66288, 66288, 66288, 66288, 66288, 66288, 66288,//120-127 - 0//off -}; - -#define SIDINSTRUMENTS 9 -int sidInstrument[SIDINSTRUMENTS][9]= - { {0,0,15,0,0,0,0,1,0}, - {0,5,5,0,1,0,0,0,0}, - {12,0,12,0,0,0,1,0,0}, - {0,9,2,1,0,0,1,0,0}, - {0,9,0,0,0,1,0,0,512}, - {0,9,9,0,0,1,0,0,2048}, - {8,9,4,1,0,1,0,0,512}, - {0,9,0,0,0,0,0,1,0}, - {9,4,4,0,0,0,0,1,0} }; - -//byte sidInstrumentName[SIDINSTRUMENTS][20]= //TODO: Goofy way to do this, change to struct or function when strcpy works. -// { "Calliope", -// "Accordian", -// "Harpsicord" }; - -/*! -@par Description - Contructor that creates an instance of the SID object that contains three SIDVoice objects. V1, V2, V3 -These objects are used to interact with and control the registers for the SID hardware implemented inside the Papilio FPGA board. -Calling this contructor will initialize the SID and SIDVoice objects to their default values. -@par Syntax - SID() -@par Parameters - none -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - sid.setVolume(15); - sid.V1.setInstrument("Calliope",0,0,15,0,0,0,0,1,0); //Calliope - sid.V2.setInstrument("Accordian",12,0,12,0,0,0,1,0,0); //Accordian - sid.V3.setInstrument("Harpsicord",0,9,0,0,0,1,0,0,512); //Harpsicord - sid.V1.setNote(51, 1); - sid.V2.setNote(51, 1); - sid.V3.setNote(51, 1); -} - -void loop() {} -~~~~~~~~ -\n -*/ -SID::SID(){ - V1.setBase(SID_ADDR_BASE_V1); - V2.setBase(SID_ADDR_BASE_V2); - V3.setBase(SID_ADDR_BASE_V3); - - //reset whole sid and initialize values. - reset(); -} - -/*! -@par Description -Use this public function to bypass the SID and SIDVoice functions and write directly to the registers of the SID hardware. Look at the SID datasheet for the registers (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#SID_Control_Registers) -@par Syntax -SID::writeData(address, data) -@param address the address from the SID datasheet for the register you want to write to. -@param data what you want to write to the SID register - -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - //This will set Voice 1 Freq Lo to 0 - SID::writeData(0, 0); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SID::writeData(unsigned char address, unsigned char data) -{ - SIDREG(address) = data; -} - -SIDVoice::SIDVoice() -{ - -} - -SIDVoice::SIDVoice(int address) //TODO: Remove this or make it work right. -{ - -} - -void SIDVoice::setBase(int address) -{ - baseAddress = address; - SID_ADDR_FREQ_LOW = baseAddress; - SID_ADDR_FREQ_HI = baseAddress + 1; - SID_ADDR_PW_LOW = baseAddress + 2; - SID_ADDR_PW_HI = baseAddress + 3; - SID_ADDR_CONTROLREG = baseAddress + 4; - SID_ADDR_ATTACK_DECAY = baseAddress + 5; - SID_ADDR_SUSTAIN_RELEASE = baseAddress + 6; -} - -/*! -@par Description -Reset a specific voice to zeroes. -@par Syntax -sid.V1.reset() -sid.V2.reset() -sid.V3.reset() -@par Parameters -none -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - sid.V1.reset(); - sid.V2.reset(); - sid.V3.reset(); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SIDVoice::reset() -{ - SIDREG(SID_ADDR_FREQ_LOW) = 0; - SIDREG(SID_ADDR_FREQ_HI) = 0; - SIDREG(SID_ADDR_PW_LOW) = 0; - SIDREG(SID_ADDR_PW_HI) = 0; - SID_REG_ATTACK_DECAY.ATTACK = 0; - SID_REG_ATTACK_DECAY.DECAY = 0; - SID_REG_SUSTAIN_RELEASE.SUSTAIN = 0; - SID_REG_SUSTAIN_RELEASE.RELEASE = 0; - SID_REG_CONTROLREG.NOISE_WAVE = 0; - SID_REG_CONTROLREG.SQUARE_WAVE = 0; - SID_REG_CONTROLREG.SAWTOOTH_WAVE = 0; - SID_REG_CONTROLREG.TRIANGLE_WAVE = 0; - SID_REG_CONTROLREG.TEST = 0; - SID_REG_CONTROLREG.RING_MOD = 0; - SID_REG_CONTROLREG.SYNC = 0; - SID_REG_CONTROLREG.GATE = 0; - SIDREG(SID_ADDR_ATTACK_DECAY) = *(char*)&SID_REG_ATTACK_DECAY; //TODO: Make this a static function to save space. - SIDREG(SID_ADDR_SUSTAIN_RELEASE) = *(char*)&SID_REG_SUSTAIN_RELEASE; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Set a voice to a MIDI Note -@par Syntax -sid.V1.setNote(note, active)\n -sid.V2.setNote(note, active)\n -sid.V3.setNote(note, active) - -@param note The MIDI note to use -@param active Whether to activate the gate and play the note. 1 plays the note 0 does not - -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - sid.V1.setNote(51, 1) - sid.V2.setNote(52, 1) - sid.V3.setNote(53, 1) -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SIDVoice::setNote(int note, boolean active) -{ - SID::writeData(SID_ADDR_FREQ_LOW, SID::MIDI2freq[note]); - SID::writeData(SID_ADDR_FREQ_HI, (SID::MIDI2freq[note] >> 8)); - setGate(active); - currentFreq = SID::MIDI2freq[note]; -} - -/*! -@par Description -Set the frequency of the SID voice -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Freq_Lo.2FFreq_Hi_.28Registers_00-01.29)\n -Together these registers form a 16-bit number which linearly controls the Frequency of Oscillator 1. The frequency is determined by the following equation: -Fout = (Fn * Fclk/16777216) Hz -Where Fn is the 16-bit number in the Frequency registers and Fclk is the system clock applied to the 2 input (pin 6). For a standard 1.0 Mhz clock, the frequency is given by: -Fout = (Fn * 0.0596) Hz -A complete table of values for generating 8 octaves of the equally-tempered musical scale with concert A (440 Hz) tuning is provided in Appendix A. It should be noted that the frequency resolution of SID is sufficient for any tuning scale and allows sweeping from note to note (portamento) with no discernible frequency steps. -@par Syntax -sid.V1.setFreq(freq)\n -sid.V2.setFreq(freq)\n -sid.V3.setFreq(freq) - -@param freq The frequency to use, refer to the [datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Appendix_A_-_Equal-Tempered_Musical_Scale_Values) for the note equivalent - -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - sid.V1.setFreq(6207) - sid.V2.setFreq(6577) - sid.V3.setFreq(6968) -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SIDVoice::setFreq(int freq) -{ - SID::writeData(SID_ADDR_FREQ_LOW, freq); - SID::writeData(SID_ADDR_FREQ_HI, (freq >> 8)); -} - -/*! -@par Description -Return what the current frequency is set to. -@par Syntax -int frequency = sid.V1.getCurrentFreq() -@par Returns -the frequency of the voice (int) - -\n -*/ -int SIDVoice::getCurrentFreq() -{ - return currentFreq; -} - -/*! -@par Description -Sets the low register PW Register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#PW_Lo.2FPW_Hi_.28Registers_02-03.29)\n -Together these registers form a 12-bit number (bits 4-7 of PW Hi are not used) which linearly controls the Pulse Width (duty cycle) of the Pulse waveform on Oscillator 1. The pulse width is determined by the following equation: -PWout = (PWn/40.95) % -Where PWn is the 12-bit number in the Pulse Width registers. -The pulse width resolution allows the width to be smoothly swept with no discernible stepping. Note that the Pulse waveform on Oscillator 1 must be selected in order for the Pulse Width registers to have any audible effect. A value of 0 or 4095 ($FFF) in the Pulse Width registers will produce a constant DC output, while a value of 2048 ($800) will produce a square wave. -@par Syntax -sid.V1.setPWLo(dutyCycle) - -@param dutyCycle Pulse Width - -\n -*/ -void SIDVoice::setPWLo(byte dutyCycle) -{ - SIDREG(SID_ADDR_PW_LOW) = (dutyCycle); -} - -/*! -@par Description -Sets the high register PW Register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#PW_Lo.2FPW_Hi_.28Registers_02-03.29)\n -Together these registers form a 12-bit number (bits 4-7 of PW Hi are not used) which linearly controls the Pulse Width (duty cycle) of the Pulse waveform on Oscillator 1. The pulse width is determined by the following equation: -PWout = (PWn/40.95) % -Where PWn is the 12-bit number in the Pulse Width registers. -The pulse width resolution allows the width to be smoothly swept with no discernible stepping. Note that the Pulse waveform on Oscillator 1 must be selected in order for the Pulse Width registers to have any audible effect. A value of 0 or 4095 ($FFF) in the Pulse Width registers will produce a constant DC output, while a value of 2048 ($800) will produce a square wave. -@par Syntax -sid.V1.setPWHi(dutyCycle) - -@param dutyCycle Pulse Width - -\n -*/ -void SIDVoice::setPWHi(byte dutyCycle) -{ - SIDREG(SID_ADDR_PW_HI) = (dutyCycle); -} - -/*! -@par Description -Control the voice gate -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -The GATE bit controls the Envelope Generator for the Voice. When this bit is set to a one, the Envelope Generator is Gated (triggered) and the ATTACK/DECAY/SUSTAIN cycle is initiated. When the bit is reset to a zero, the RELEASE cycle begins. The Envelope Generator controls the amplitude of Oscillator 1 appearing at the audio output, therefore, the GATE bit must be set (along with suitable envelope parameters) for the selected output of Oscillator 1 to be audible. A detailed discussion of the Envelope Generator can be found in Appendix B. -@par Syntax -sid.V1.setGate(active) - -@param active 1 to trigger the gate 0 to reset - -\n -*/ -void SIDVoice::setGate(boolean active) -{ - SID_REG_CONTROLREG.GATE = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Sync bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -The SYNC bit, when set to a one, Synchronizes the fundamental frequency of Oscillator 1 with the fundamental frequency of Oscillator 3, producing “Hard Sync” effects. Varying the frequency of Oscillator 1 with respect to Oscillator 3 produces a wide range of complex harmonic structures from Voice 1 at the frequency of Oscillator 3. In order for sync to occur Oscillator 3 must be set to some frequency other than zero but preferably lower than the frequency of Oscillator 1. No other parameters of Voice 3 have any effect on sync. -@par Syntax -sid.V1.setSync(active) - -@param active 1 syncs 0 turns sync off - -\n -*/ -void SIDVoice::setSync(boolean active) -{ - SID_REG_CONTROLREG.SYNC = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Ring Mod bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -The RING MOD bit, when set to a one, replaces the Triangle waveform output of Oscillator 1 with a “Ring Modulated” combination of Oscillators 1 and 3. Varying the frequency of Oscillator 1 with respect to Oscillator 3 produces a wide range of non-harmonic overtone structures for creating bell or gong sounds and for special effects. In order for ring modulation to be audible, the Triangle waveform of Oscillator 1 must be selected and Oscillator 3 must be set to some frequency other than zero. No other parameters of Voice 3 have any effect on ring modulation. -@par Syntax -sid.V1.setRingMod(active) - -@param active 1 Ring Mod on 0 turns Ring Mod off - -\n -*/ -void SIDVoice::setRingMod(boolean active) -{ - SID_REG_CONTROLREG.RING_MOD = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Test bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -The TEST bit, when set to a one, resets and locks Oscillator 1 at zero until the TEST bit is cleared. The Noise waveform output of Oscillator 1 is also reset and the Pulse waveform output is held at a DC level. Normally this bit is used for testing purposes, however, it can be used to synchronize Oscillator 1 to external events, allowing the generation of highly complex waveforms under real-time software control. -@par Syntax -sid.V1.setTest(active) - -@param active 1 Test on 0 turns Test off - -\n -*/ -void SIDVoice::setTest(boolean active) -{ - SID_REG_CONTROLREG.TEST = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Triangle bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -When set to a one, the Triangle waveform output of Oscillator 1 is selected. The Triangle waveform is low in harmonics and has a mellow, flute-like quality. -@par Syntax -sid.V1.setTriangle(active) - -@param active 1 on 0 turns off - -\n -*/ -void SIDVoice::setTriangle(boolean active) -{ - SID_REG_CONTROLREG.TRIANGLE_WAVE = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Sawtooth bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -When set to a one, the Sawtooth waveform of Oscillator 1 is selected. The sawtooth waveform is rich in even and odd harmonics and has a bright, brassy quality. -@par Syntax -sid.V1.setSawtooth(active) - -@param active 1 on 0 turns off - -\n -*/ -void SIDVoice::setSawtooth(boolean active) -{ - SID_REG_CONTROLREG.SAWTOOTH_WAVE = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Square bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -When set to a one, the Pulse waveform output of Oscillator 1 is selected. The harmonic content of this waveform can be adjusted by the Pulse Width registers, producing tone Qualities ranging from a bright, hollow square wave to a nasal, reedy pulse. Sweeping the pulse width in real-time produces a dynamic “phasing” effect which adds a sense of motion to the sound. Rapidly jumping between different pulse widths can produce interesting harmonic sequences. -@par Syntax -sid.V1.setSquare(active) - -@param active 1 on 0 turns off - -\n -*/ -void SIDVoice::setSquare(boolean active) -{ - SID_REG_CONTROLREG.SQUARE_WAVE = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Square bit of the control register and the PWM at the same time -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -When set to a one, the Pulse waveform output of Oscillator 1 is selected. The harmonic content of this waveform can be adjusted by the Pulse Width registers, producing tone Qualities ranging from a bright, hollow square wave to a nasal, reedy pulse. Sweeping the pulse width in real-time produces a dynamic “phasing” effect which adds a sense of motion to the sound. Rapidly jumping between different pulse widths can produce interesting harmonic sequences. -@par Syntax -sid.V1.setSquare(active, pwm) - -@param active 1 on 0 turns off -@param pwm set the pwm register for the voice - -\n -*/ -void SIDVoice::setSquare(boolean active, int pwm) -{ - SID_REG_CONTROLREG.SQUARE_WAVE = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; - setPWLo(pwm); - setPWHi(pwm >> 8); -} - -/*! -@par Description -Sets the Noise bit of the control register -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Control_Register_.28Register_04.29)\n -When set to a one, the Noise output waveform of Oscillator 1 is selected. This output is a random signal which changes at the frequency of Oscillator 1. The sound quality can be varied from a low rumbling to hissing white noise via the Oscillator 1 Frequency registers. Noise is useful in creating explosions, gunshots, jet engines, wind, surf and other un-pitched sounds, as well as snare drums and cymbals. Sweeping the Oscillator frequency with Noise selected produces a dramatic rushing effect. One of the output waveforms must be selected for Oscillator 1 to be audible, however it is NOT necessary to deselect waveforms to silence the output of Voice 1. The amplitude of Voice 1 at the final output is a function of the Envelope Generator only. -NOTE: The oscillator output waveforms are NOT additive. If more than one output waveform is selected simultaneously, the result will be a logical ANDing of the waveforms. Although this technique can be used to generate additional waveforms beyond the four listed above, it must be used with care. If any other waveform is selected while Noise is on, the Noise output can “lock up”. If this occurs, the Noise output will remain silent until reset by the TEST bit or by bringing /RES (pin 5) low. -@par Syntax -sid.V1.setNoise(active) - -@param active 1 on 0 turns off - -\n -*/ -void SIDVoice::setNoise(boolean active) -{ - SID_REG_CONTROLREG.NOISE_WAVE = active; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Sets the Attack bits -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Attack.2FDecay_.28Register_05.29)\n -Select 1 of 16 ATTACK rates for the Voice 1 Envelope Generator. The ATTACK rate determines how rapidly the output of Voice 1 rises from zero to peak amplitude when the Envelope Generator is Gated. The 16 ATTACK rates are listed in Table 2 in the datasheet. -@par Syntax -sid.V1.setEnvelopeAttack(rate) - -@param rate Attack Rate as defined in datasheet - -\n -*/ -void SIDVoice::setEnvelopeAttack(byte rate) -{ - SID_REG_ATTACK_DECAY.ATTACK = rate; - SIDREG(SID_ADDR_ATTACK_DECAY) = *(char*)&SID_REG_ATTACK_DECAY; -} - -/*! -@par Description -Sets the Decay bits -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Attack.2FDecay_.28Register_05.29)\n -Select 1 of 16 DECAY rates for the Envelope Generator. The DECAY cycle follows the ATTACK cycle and the DECAY rate determines how rapidly the output falls from the peak amplitude to the selected SUSTAIN level. The 16 DECAY rates are listed in Table 2 of the datasheet. -@par Syntax -sid.V1.setEnvelopeDecay(rate) - -@param rate Decay Rate as defined in datasheet - -\n -*/ -void SIDVoice::setEnvelopeDecay(byte rate) -{ - SID_REG_ATTACK_DECAY.DECAY = rate; - SIDREG(SID_ADDR_ATTACK_DECAY) = *(char*)&SID_REG_ATTACK_DECAY; -} - -/*! -@par Description -Sets the Sustain bits -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Sustain.2FRelease_.28Register_06.29)\n -Select 1 of 16 SUSTAIN levels for the Envelope Generator. The SUSTAIN cycle follows the DECAY cycle and the output of Voice 1 will remain at the selected SUSTAIN amplitude as long as the Gate bit remains set. The SUSTAIN levels range from zero to peak amplitude in 16 linear steps, with a SUSTAIN value of 0 selecting zero amplitude and a SUSTAIN value of 15 (#F) selecting the peak amplitude. -A SUSTAIN value of 8 would cause Voice 1 to SUSTAIN at an amplitude one-half the peak amplitude reached by the ATTACK cycle. -@par Syntax -sid.V1.setEnvelopeSustain(level) - -@param level Sustain Level as defined in datasheet - -\n -*/ -void SIDVoice::setEnvelopeSustain(byte level) -{ - SID_REG_SUSTAIN_RELEASE.SUSTAIN = level; - SIDREG(SID_ADDR_SUSTAIN_RELEASE) = *(char*)&SID_REG_SUSTAIN_RELEASE; -} - -/*! -@par Description -Sets the Release bits -@par Datasheet -[From Datasheet] (http://www.waitingforfriday.com/index.php/Commodore_SID_6581_Datasheet#Sustain.2FRelease_.28Register_06.29)\n -Select 1 of 16 RELEASE rates for the Envelope Generator. The RELEASE cycle follows the SUSTAIN cycle when the Gate bit is reset to zero. At this time, the output of Voice 1 will fall from the SUSTAIN amplitude to zero amplitude at the selected RELEASE rate. The 16 RELEASE rates are identical to the DECAY rates. -NOTE: The cycling of the Envelope Generator can be altered at any point via the Gate bit. The Envelope Generator can be Gated and Released without restriction. For example, if the Gate bit is reset before the envelope has finished the ATTACK cycle, the RELEASE cycle will immediately begin, starting from whatever amplitude had been reached. If the envelope is then Gated again (before the RELEASE cycle has reached zero amplitude), another ATTACK cycle will begin, starting from whatever amplitude had been reached. This technique can be used to generate complex amplitude envelopes via real-time software control. -@par Syntax -sid.V1.setEnvelopeRelease(rate) - -@param rate Release Rate as defined in datasheet - -\n -*/ -void SIDVoice::setEnvelopeRelease(byte rate) -{ - SID_REG_SUSTAIN_RELEASE.RELEASE = rate; - SIDREG(SID_ADDR_SUSTAIN_RELEASE) = *(char*)&SID_REG_SUSTAIN_RELEASE; -} - -void SIDVoice::handleCC(byte number, byte value) -{ - //Handle the Control Changes for SID - switch (number) { //TODO figure more efficient way to do this. Want to avoid case statements. - case 2: - setTriangle(value); - break; - case 3: - setSawtooth(value); - break; - case 4: - setSquare(value); - break; - case 5: - setNoise(value); - break; - case 6: - setRingMod(value); - break; - case 7: - setSync(value); - break; - case 71: - setEnvelopeDecay(value/8); - break; - case 74: - setEnvelopeAttack(value/8); - break; - case 75: - setPWLo(value << 1); - break; - case 76: - setPWHi(value); - break; - case 91: - setEnvelopeSustain(value/8); - break; - case 92: //This is for Ring Modulation Fine. - ringMod(0,1, value); - break; - case 93: - setEnvelopeRelease(value/8); - break; - case 95: //This is for Ring Modulation Coarse. - ringMod(1,0, value); - default: - return; - break; - } -} - -void SIDVoice::ringMod(byte baseOffset, byte valueOffset, byte value) -{ - switch (baseAddress) { - case SID_ADDR_BASE_V1: //When we are on Voice 1 we need to combine with Frequency of Voice 3 - SIDREG(SID_ADDR_BASE_V3 + baseOffset) = (value << valueOffset); - break; - case SID_ADDR_BASE_V2: //When we are on Voice 2 we need to combine with Frequency of Voice 1 - SIDREG(SID_ADDR_BASE_V1 + baseOffset) = (value << valueOffset); - break; - case SID_ADDR_BASE_V3: //When we are on Voice 3 we need to combine with Frequency of Voice 2 - SIDREG(SID_ADDR_BASE_V2 + baseOffset) = (value << valueOffset); - break; - default: - return; - break; - } -} - -/*! -@par Description -Define an instrument for the Voice -@par Syntax -setInstrument(name, attack, decay, sustain, rel, noise, square, sawtooth, triangle, pwm) - -@param name Name of Instrument to be shown on LCD -@param attack Attack for instrument -@param decay Decay for instrument -@param sustain Sustain for instrument -@param rel Release for instrument -@param noise Noise bit for instrument -@param square Square bit for instrument -@param sawtooth Sawtooth bit for instrument -@param triangle Triangle bit for instrument -@param pwm PWM value for instrument - - -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - sid.V1.setInstrument("Calliope",0,0,15,0,0,0,0,1,0); //Calliope - sid.V2.setInstrument("Accordian",12,0,12,0,0,0,1,0,0); //Accordian - sid.V3.setInstrument("Harpsicord",0,9,0,0,0,1,0,0,512); //Harpsicord -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SIDVoice::setInstrument(const char* name,byte attack, byte decay, byte sustain, byte rel, bool noise, bool square, bool sawtooth, bool triangle, int pwm) -{ - Serial.println("In setinstrument"); - Serial.println(name); - strcpy(instrumentName, name); - Serial.println(instrumentName); - SID_REG_ATTACK_DECAY.ATTACK = attack; - SID_REG_ATTACK_DECAY.DECAY = decay; - SID_REG_SUSTAIN_RELEASE.SUSTAIN = sustain; - SID_REG_SUSTAIN_RELEASE.RELEASE = rel; - SID_REG_CONTROLREG.NOISE_WAVE = noise; - SID_REG_CONTROLREG.SQUARE_WAVE = square; - SID_REG_CONTROLREG.SAWTOOTH_WAVE = sawtooth; - SID_REG_CONTROLREG.TRIANGLE_WAVE = triangle; - setPWLo(pwm); - setPWHi(pwm >> 8); - - SIDREG(SID_ADDR_ATTACK_DECAY) = *(char*)&SID_REG_ATTACK_DECAY; //TODO: Make this a static function to save space. - SIDREG(SID_ADDR_SUSTAIN_RELEASE) = *(char*)&SID_REG_SUSTAIN_RELEASE; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -void SIDVoice::loadInstrument(byte instrument) -{ -// Serial.println("In setinstrument"); -// Serial.println(name); -// strcpy(instrumentName, sidInstrumentName); -// Serial.println(instrumentName); - SID_REG_ATTACK_DECAY.ATTACK = sidInstrument[instrument][0]; - SID_REG_ATTACK_DECAY.DECAY = sidInstrument[instrument][1]; - SID_REG_SUSTAIN_RELEASE.SUSTAIN = sidInstrument[instrument][2]; - SID_REG_SUSTAIN_RELEASE.RELEASE = sidInstrument[instrument][3]; - SID_REG_CONTROLREG.NOISE_WAVE = sidInstrument[instrument][4]; - SID_REG_CONTROLREG.SQUARE_WAVE = sidInstrument[instrument][5]; - SID_REG_CONTROLREG.SAWTOOTH_WAVE = sidInstrument[instrument][6]; - SID_REG_CONTROLREG.TRIANGLE_WAVE = sidInstrument[instrument][7]; - setPWLo(sidInstrument[instrument][8]); - setPWHi((sidInstrument[instrument][8]) >> 8); - - SIDREG(SID_ADDR_ATTACK_DECAY) = *(char*)&SID_REG_ATTACK_DECAY; //TODO: Make this a static function to save space. - SIDREG(SID_ADDR_SUSTAIN_RELEASE) = *(char*)&SID_REG_SUSTAIN_RELEASE; - SIDREG(SID_ADDR_CONTROLREG) = *(char*)&SID_REG_CONTROLREG; -} - -/*! -@par Description -Set the SID master volume -@par Syntax -sid.setVolume(volume) -@param volume number between 0 and 15 - -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - //Turn volume to the max value - sid.setVolume(15); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SID::setVolume(byte volume) //TODO: get rid of voice -{ - SID_REG_MODE_VOLUME.VOLUME = volume; - SIDREG(SID_ADDR_FILTER_MODE_VOL) = *(char*)&SID_REG_MODE_VOLUME; -} - -/*! -@par Description -Set all SID registers to their default values. -@par Syntax -sid.reset() -@par Parameters -none -@par Example -~~~~~~~~{.c} -#include "SID.h" - -SID sid; - -void setup() -{ - sid.reset(); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SID::reset(){ - //Filter - SIDREG(SID_ADDR_FILTER_FC_LOW) = 0; - SIDREG(SID_ADDR_FILTER_FC_HI) = 0; - SIDREG(SID_ADDR_FILTER_RES_FILT) = 0; - SID_REG_MODE_VOLUME.OFF = 0; - SID_REG_MODE_VOLUME.HP = 0; - SID_REG_MODE_VOLUME.BP = 0; - SID_REG_MODE_VOLUME.LP = 0; - SID_REG_MODE_VOLUME.VOLUME = 0x0; - SIDREG(SID_ADDR_FILTER_MODE_VOL) = *(char*)&SID_REG_MODE_VOLUME; - V1.reset(); - V2.reset(); - V3.reset(); -} - - diff --git a/RetroCade_Sketch/sidplayer.cpp b/RetroCade_Sketch/sidplayer.cpp deleted file mode 100644 index 7f7b290..0000000 --- a/RetroCade_Sketch/sidplayer.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*! - * @file sidplayer.cpp - * Project sidplayer Library - * @brief sidplayer library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 9/24/13 - * License GPL - */ - -#include "sidplayer.h" -//#include "SID.h" -#include "tinysid.h" -#include "ramFS.h" - -#define DEBUG - -SIDPLAYER::SIDPLAYER(){ - -} - -/*! -@par Description -Initialize the SIDPLAYER -@par Syntax -sidplayer.setup(newsid) -@param SID Pointer to a SID object - -@par Example -~~~~~~~~{.c} -#include "SID.h" -#include "sidplayer.h" - -SID sid; - -void setup() -{ - sid.setup(&sid); -} - -void loop() {} -~~~~~~~~ -\n -*/ -//void SIDPLAYER::setup(SID* newsid){ -void SIDPLAYER::setup(){ - //underruns = 0; - // timerTicks = 0; - // sidTimeStamp = 0; - // resetSIDFlag = 0; - // counter = 0; - playing = false; - // sid = newsid; - // volumeAdjust = 4; -} - -/*! -@par Description -Load a sid file from smallfs or a SD card. The provided file name will be searched for in the smallfs filesystem first and the SD file system second. If the filename exists in both locations the SD version will override the smallfs version. -@par Syntax -sidplayer.loadFile(name) -@param name filename of the sid file to open. - -@par Example -~~~~~~~~{.c} -#include "SID.h" -#include "sidplayer.h" - -SID sid; - -void setup() -{ - sidplayer.setup(&sid); - sidplayer.loadFile("track1.sid"); - sidplayer.play(true); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SIDPLAYER::loadFile(const char* name) -{ - tinyLoadFile(name); -/* sidSDfile.close(); - sidTimeStamp = 0; - sidSmallFSfile = SmallFS.open(name); - if (!sidSmallFSfile.valid()) { - #ifdef DEBUG - Serial.println("There is no smallfs File."); - #endif - } - - sidSDfile = SD.open(name); //TODO: Should check for SD filesystem init first. - if (!sidSDfile){ - #ifdef DEBUG - Serial.println("There is no SD File."); - #endif - } */ -} - -/*! -@par Description -Play a sid file after it has been loaded. -@par Syntax -sidplayer.play(play) -@param play Will play the file if set to 1 or true. - -@par Example -~~~~~~~~{.c} -#include "SID.h" -#include "sidplayer.h" - -SID sid; - -void setup() -{ - sidplayer.setup(&sid); - sidplayer.loadFile("track1.sid"); - sidplayer.play(true); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void SIDPLAYER::play(boolean play) -{ - // boolean smallfscheck = sidSmallFSfile.valid(); - // if (!sidSDfile && !smallfscheck) { - // play = false; - // #ifdef DEBUG - // Serial.println("Error: No SD or SmallFS File Available"); - // #endif - // return; - // } - - // if (smallfscheck) - // fileType = SmallFSType; - // if (sidSDfile) - // fileType = SDFSType; - - playing = play; - if (play == true) - resetSIDFlag = 1; -} - -void SIDPLAYER::volume(int volume) -{ - volumeAdjust = volume; -} - -void SIDPLAYER::audiofill() -{ - if (playing == true) - tinyloop(); -} - -boolean SIDPLAYER::getPlaying() -{ - return playing; -} - -void SIDPLAYER::zpu_interrupt() -{ - tinysid_zpu_interrupt(); -} - diff --git a/RetroCade_Sketch/sidplayer.h b/RetroCade_Sketch/sidplayer.h deleted file mode 100644 index 5d18148..0000000 --- a/RetroCade_Sketch/sidplayer.h +++ /dev/null @@ -1,65 +0,0 @@ -/*! - * @file sidplayer.h - * Project sidplayer Library - * @brief sidplayer library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 9/24/13 - * License GPL - */ - -#ifndef LIB_SIDPLAYER_H_ -#define LIB_SIDPLAYER_H_ - -#include -#include -#include -#include "Arduino.h" - #include "SmallFS.h" -// #include "cbuffer.h" -// #include "SID.h" - #include - #include "ramFS.h" - //#include "retrocade_defs.h" - -// enum kFileType { - // SmallFSType = 0, - // SDFSType = 1, -// }; - -class SIDPLAYER -{ - public: - SIDPLAYER(); - //void setup(SID* newsid); - void setup(); - void loadFile(const char* name); - void play(boolean play); - boolean getPlaying(); - void audiofill(); - void zpu_interrupt(); - void volume(int volume); - private: - // struct ymframe { - // unsigned char regval[14]; - // }; - // CircularBuffer YMaudioBuffer; - unsigned int timerTicks; - int counter; - byte volumeAdjust; - int sidTimeStamp; - int resetSIDFlag; - //SID* sid; - SmallFSFile sidSmallFSfile; - File sidSDfile; - boolean playing; - boolean fileLoaded; - //kFileType fileType; - SmallFSFile modSmallFSfile; - File modSDfile; - RamFSFile modRAMfile; - -}; - - -#endif // LIB_SIDPLAYER_H_ diff --git a/RetroCade_Sketch/sidtune_Layla_Mix.h b/RetroCade_Sketch/sidtune_Layla_Mix.h deleted file mode 100644 index 72f45a9..0000000 --- a/RetroCade_Sketch/sidtune_Layla_Mix.h +++ /dev/null @@ -1,237 +0,0 @@ -const unsigned char sidtune_Layla_Mix[] = { -80, 83, 73, 68, 0, 2, 0, 124, // 0 -0, 0, 31, 144, 25, 0, 0, 1, // 1 -0, 1, 0, 0, 0, 0, 76, 97, // 2 -121, 108, 97, 32, 77, 105, 120, 0, // 3 -0, 0, 0, 0, 0, 0, 0, 0, // 4 -0, 0, 0, 0, 0, 0, 0, 0, // 5 -0, 0, 0, 0, 0, 0, 69, 100, // 6 -119, 105, 110, 32, 118, 97, 110, 32, // 7 -83, 97, 110, 116, 101, 110, 0, 0, // 8 -0, 0, 0, 0, 0, 0, 0, 0, // 9 -0, 0, 0, 0, 0, 0, 49, 57, // 10 -56, 56, 32, 50, 48, 116, 104, 32, // 11 -67, 101, 110, 116, 117, 114, 121, 32, // 12 -67, 111, 109, 112, 111, 115, 101, 114, // 13 -115, 0, 0, 0, 0, 0, 0, 0, // 14 -0, 0, 0, 0, 208, 24, 82, 73, // 15 -80, 80, 69, 68, 32, 66, 89, 32, // 16 -71, 46, 71, 79, 85, 87, 69, 76, // 17 -79, 79, 83, 32, 79, 78, 32, 50, // 18 -50, 45, 49, 49, 45, 49, 57, 57, // 19 -52, 32, 32, 32, 32, 32, 0, 0, // 20 -0, 0, 0, 0, 0, 0, 164, 103, // 21 -48, 9, 240, 3, 76, 28, 28, 140, // 22 -24, 212, 96, 162, 2, 32, 35, 25, // 23 -202, 16, 250, 165, 104, 141, 24, 212, // 24 -198, 5, 16, 4, 169, 2, 133, 5, // 25 -96, 165, 5, 208, 7, 214, 2, 208, // 26 -3, 76, 29, 27, 181, 9, 208, 51, // 27 -149, 94, 149, 97, 149, 24, 149, 72, // 28 -149, 69, 149, 81, 149, 84, 149, 88, // 29 -181, 18, 188, 96, 28, 134, 254, 170, // 30 -189, 151, 29, 153, 4, 212, 189, 153, // 31 -29, 153, 5, 212, 189, 154, 29, 153, // 32 -6, 212, 189, 155, 29, 166, 254, 41, // 33 -15, 149, 100, 246, 9, 181, 57, 16, // 34 -40, 180, 60, 185, 73, 29, 133, 254, // 35 -185, 76, 29, 133, 255, 180, 51, 177, // 36 -254, 201, 255, 240, 8, 246, 51, 188, // 37 -96, 28, 153, 4, 212, 180, 54, 177, // 38 -254, 201, 128, 240, 4, 246, 54, 149, // 39 -24, 181, 21, 24, 117, 27, 117, 24, // 40 -117, 72, 133, 255, 168, 185, 99, 28, // 41 -24, 117, 81, 72, 185, 195, 28, 117, // 42 -84, 188, 96, 28, 153, 1, 212, 104, // 43 -153, 0, 212, 181, 97, 153, 2, 212, // 44 -181, 100, 153, 3, 212, 181, 9, 201, // 45 -2, 208, 13, 181, 57, 41, 64, 240, // 46 -7, 169, 129, 153, 4, 212, 208, 33, // 47 -201, 3, 208, 9, 181, 57, 48, 5, // 48 -181, 48, 153, 4, 212, 181, 66, 240, // 49 -3, 32, 202, 26, 180, 75, 240, 9, // 50 -32, 175, 26, 181, 57, 41, 2, 240, // 51 -26, 181, 78, 240, 4, 32, 250, 26, // 52 -96, 181, 57, 41, 1, 240, 12, 181, // 53 -63, 41, 28, 10, 213, 9, 176, 3, // 54 -32, 14, 26, 96, 181, 63, 41, 224, // 55 -168, 181, 60, 41, 15, 133, 87, 70, // 56 -87, 180, 88, 16, 6, 214, 91, 208, // 57 -15, 240, 8, 246, 91, 213, 91, 176, // 58 -7, 149, 91, 152, 73, 255, 149, 88, // 59 -164, 255, 185, 99, 28, 133, 106, 185, // 60 -195, 28, 133, 105, 181, 63, 41, 3, // 61 -24, 101, 255, 168, 185, 100, 28, 56, // 62 -229, 106, 133, 254, 185, 196, 28, 229, // 63 -105, 180, 60, 16, 2, 117, 9, 133, // 64 -255, 181, 60, 41, 112, 74, 74, 74, // 65 -74, 168, 70, 255, 102, 254, 136, 16, // 66 -249, 165, 87, 56, 245, 91, 48, 20, // 67 -168, 136, 48, 38, 24, 165, 106, 101, // 68 -254, 133, 106, 165, 105, 101, 255, 133, // 69 -105, 76, 115, 26, 181, 91, 56, 229, // 70 -87, 168, 165, 106, 56, 229, 254, 133, // 71 -106, 165, 105, 229, 255, 133, 105, 136, // 72 -208, 240, 188, 96, 28, 181, 81, 24, // 73 -101, 106, 153, 0, 212, 181, 84, 101, // 74 -105, 153, 1, 212, 96, 185, 41, 29, // 75 -133, 254, 214, 69, 16, 6, 168, 185, // 76 -43, 29, 149, 69, 181, 69, 24, 101, // 77 -254, 168, 185, 44, 29, 149, 72, 96, // 78 -181, 94, 208, 23, 181, 97, 24, 117, // 79 -66, 168, 181, 100, 105, 0, 201, 16, // 80 -208, 3, 246, 94, 96, 149, 100, 152, // 81 -149, 97, 96, 181, 97, 56, 245, 66, // 82 -168, 181, 100, 233, 0, 16, 3, 214, // 83 -94, 96, 149, 100, 152, 149, 97, 96, // 84 -41, 127, 10, 180, 78, 48, 12, 24, // 85 -117, 81, 149, 81, 181, 84, 105, 0, // 86 -149, 84, 96, 133, 254, 181, 81, 56, // 87 -229, 254, 149, 81, 181, 84, 233, 0, // 88 -149, 84, 96, 180, 30, 185, 47, 29, // 89 -133, 254, 185, 60, 29, 133, 255, 180, // 90 -33, 177, 254, 201, 255, 208, 18, 181, // 91 -45, 240, 8, 214, 45, 169, 0, 149, // 92 -33, 240, 236, 32, 196, 27, 76, 29, // 93 -27, 169, 0, 149, 9, 149, 78, 177, // 94 -254, 48, 8, 149, 21, 200, 152, 149, // 95 -33, 208, 41, 201, 192, 144, 16, 201, // 96 -224, 144, 19, 201, 240, 144, 22, 200, // 97 -177, 254, 149, 78, 200, 208, 224, 41, // 98 -63, 149, 6, 200, 208, 217, 41, 31, // 99 -149, 15, 200, 208, 210, 41, 15, 149, // 100 -75, 200, 208, 203, 181, 6, 149, 2, // 101 -181, 12, 208, 2, 181, 15, 10, 10, // 102 -10, 149, 18, 168, 185, 155, 29, 41, // 103 -240, 149, 66, 185, 157, 29, 149, 60, // 104 -185, 158, 29, 149, 63, 185, 156, 29, // 105 -149, 57, 48, 6, 185, 152, 29, 149, // 106 -48, 96, 180, 60, 185, 73, 29, 133, // 107 -254, 185, 76, 29, 133, 255, 160, 0, // 108 -177, 254, 149, 51, 200, 177, 254, 149, // 109 -54, 96, 169, 0, 149, 33, 149, 75, // 110 -180, 36, 181, 39, 133, 254, 181, 42, // 111 -133, 255, 177, 254, 201, 64, 144, 59, // 112 -201, 255, 240, 51, 201, 128, 144, 20, // 113 -201, 192, 144, 23, 201, 208, 144, 26, // 114 -201, 254, 240, 29, 56, 233, 208, 149, // 115 -12, 200, 208, 222, 41, 63, 149, 45, // 116 -200, 208, 215, 41, 63, 149, 27, 200, // 117 -208, 208, 41, 15, 133, 104, 200, 208, // 118 -201, 160, 0, 132, 103, 240, 195, 160, // 119 -0, 240, 191, 149, 30, 200, 152, 149, // 120 -36, 96, 169, 0, 162, 104, 149, 2, // 121 -202, 16, 251, 162, 24, 157, 0, 212, // 122 -202, 16, 250, 134, 103, 169, 15, 133, // 123 -104, 141, 24, 212, 136, 152, 10, 133, // 124 -106, 10, 24, 101, 106, 168, 162, 0, // 125 -185, 35, 29, 149, 39, 200, 185, 35, // 126 -29, 149, 42, 200, 232, 224, 3, 208, // 127 -239, 162, 2, 32, 196, 27, 169, 1, // 128 -149, 2, 202, 16, 246, 96, 0, 7, // 129 -14, 12, 28, 45, 62, 81, 102, 123, // 130 -145, 169, 195, 221, 250, 24, 56, 90, // 131 -125, 163, 204, 246, 35, 83, 134, 187, // 132 -244, 48, 112, 180, 251, 71, 152, 237, // 133 -71, 176, 12, 119, 233, 97, 225, 104, // 134 -247, 143, 48, 218, 143, 78, 24, 239, // 135 -210, 195, 195, 209, 239, 31, 96, 181, // 136 -30, 156, 49, 223, 165, 135, 134, 162, // 137 -223, 62, 193, 107, 60, 57, 99, 190, // 138 -75, 15, 12, 69, 191, 125, 131, 214, // 139 -121, 115, 199, 124, 151, 30, 24, 139, // 140 -126, 250, 6, 172, 243, 230, 143, 248, // 141 -46, 1, 1, 1, 1, 1, 1, 1, // 142 -1, 1, 1, 1, 1, 2, 2, 2, // 143 -2, 2, 2, 2, 3, 3, 3, 3, // 144 -3, 4, 4, 4, 4, 5, 5, 5, // 145 -6, 6, 7, 7, 7, 8, 8, 9, // 146 -9, 10, 11, 11, 12, 13, 14, 14, // 147 -15, 16, 17, 18, 19, 21, 22, 23, // 148 -25, 26, 28, 29, 31, 33, 35, 37, // 149 -39, 42, 44, 47, 50, 53, 56, 59, // 150 -63, 67, 71, 75, 79, 84, 89, 94, // 151 -100, 106, 112, 119, 126, 134, 142, 150, // 152 -159, 168, 179, 189, 200, 212, 225, 238, // 153 -253, 223, 29, 3, 30, 21, 30, 0, // 154 -0, 2, 0, 12, 0, 46, 50, 95, // 155 -192, 159, 86, 4, 14, 29, 38, 93, // 156 -97, 101, 30, 30, 30, 30, 30, 30, // 157 -31, 31, 31, 31, 31, 31, 31, 79, // 158 -93, 131, 29, 29, 29, 2, 7, 17, // 159 -129, 65, 64, 255, 0, 79, 24, 15, // 160 -7, 0, 128, 2, 20, 129, 129, 65, // 161 -64, 128, 128, 64, 64, 128, 128, 64, // 162 -64, 128, 128, 64, 64, 128, 255, 32, // 163 -32, 0, 255, 32, 32, 0, 255, 32, // 164 -32, 0, 255, 32, 32, 0, 255, 32, // 165 -128, 2, 6, 129, 21, 20, 255, 32, // 166 -20, 19, 18, 17, 16, 15, 14, 13, // 167 -12, 13, 14, 15, 128, 0, 0, 0, // 168 -0, 0, 0, 0, 0, 0, 0, 0, // 169 -247, 8, 128, 0, 0, 0, 0, 0, // 170 -246, 8, 128, 1, 0, 69, 68, 0, // 171 -169, 8, 0, 0, 0, 65, 64, 0, // 172 -205, 100, 1, 212, 0, 81, 64, 0, // 173 -252, 72, 0, 0, 0, 81, 64, 0, // 174 -204, 136, 1, 196, 4, 0, 0, 0, // 175 -153, 8, 128, 2, 0, 65, 64, 0, // 176 -205, 244, 1, 212, 0, 141, 0, 75, // 177 -4, 143, 6, 6, 141, 6, 6, 143, // 178 -6, 6, 139, 6, 6, 139, 6, 141, // 179 -6, 146, 6, 143, 6, 139, 6, 141, // 180 -6, 146, 6, 6, 141, 75, 4, 11, // 181 -255, 208, 141, 0, 67, 2, 79, 7, // 182 -67, 2, 79, 7, 71, 2, 11, 216, // 183 -1, 12, 255, 208, 141, 8, 5, 1, // 184 -12, 9, 10, 9, 5, 1, 12, 3, // 185 -10, 9, 10, 9, 5, 1, 1, 216, // 186 -1, 12, 11, 255, 192, 160, 0, 255, // 187 -196, 140, 50, 134, 240, 56, 53, 130, // 188 -55, 136, 53, 136, 52, 48, 50, 130, // 189 -45, 48, 50, 53, 50, 48, 140, 50, // 190 -134, 240, 56, 55, 130, 57, 136, 55, // 191 -136, 52, 48, 50, 196, 130, 45, 48, // 192 -50, 53, 50, 48, 255, 193, 132, 0, // 193 -130, 195, 225, 62, 50, 224, 194, 132, // 194 -30, 193, 132, 0, 130, 195, 225, 62, // 195 -50, 224, 193, 132, 0, 194, 132, 30, // 196 -130, 195, 225, 50, 62, 224, 193, 132, // 197 -0, 130, 195, 225, 50, 62, 224, 194, // 198 -132, 30, 193, 132, 0, 130, 195, 225, // 199 -62, 50, 224, 193, 132, 0, 194, 132, // 200 -30, 130, 30, 30, 255, 197, 132, 14, // 201 -130, 26, 14, 132, 14, 136, 10, 130, // 202 -22, 10, 132, 10, 10, 12, 130, 24, // 203 -12, 132, 12, 136, 14, 130, 26, 14, // 204 -14, 14, 130, 26, 14, 255, 192, 136, // 205 -0, 198, 130, 57, 132, 57, 134, 57, // 206 -132, 55, 53, 130, 53, 134, 55, 156, // 207 -57, 192, 136, 0, 198, 130, 57, 132, // 208 -57, 134, 57, 132, 55, 53, 130, 55, // 209 -170, 53, 130, 53, 132, 53, 55, 142, // 210 -57, 132, 57, 55, 130, 53, 134, 55, // 211 -132, 53, 148, 50, 132, 50, 53, 130, // 212 -55, 132, 55, 134, 57, 132, 53, 148, // 213 -53, 255, 132, 197, 12, 130, 24, 134, // 214 -12, 132, 12, 255, 193, 132, 0, 199, // 215 -130, 48, 48, 194, 132, 30, 199, 130, // 216 -48, 48, 255, 194, 134, 30, 134, 30, // 217 -132, 30, 30, 255, 198, 136, 53, 132, // 218 -52, 53, 134, 52, 130, 50, 192, 134, // 219 -0, 132, 198, 55, 130, 55, 132, 53, // 220 -52, 53, 134, 52, 130, 50, 192, 136, // 221 -0, 198, 136, 53, 132, 52, 53, 134, // 222 -52, 130, 50, 192, 134, 0, 132, 198, // 223 -55, 130, 55, 132, 53, 55, 130, 60, // 224 -134, 57, 255, 192, 140, 0, 255, 192, // 225 -129, 0, 255, 196, 140, 50, 134, 240, // 226 -56, 53, 130, 55, 136, 53, 136, 52, // 227 -48, 50, 130, 45, 48, 50, 53, 50, // 228 -48, 140, 50, 134, 240, 56, 55, 130, // 229 -57, 136, 55, 136, 52, 48, 148, 50, // 230 -255, 0, 0, 0, 0, 0, 169, 1, // 231 -133, 103, 96, 36, 82, 73, 80, 58, // 232 -71, 117, 105, 100, 111, 32, 71, 111, // 233 -117, 119, 101, 108, 111, 111, 115, 0, // 234 -}; diff --git a/RetroCade_Sketch/tinysid.cpp b/RetroCade_Sketch/tinysid.cpp deleted file mode 100644 index 778bcd0..0000000 --- a/RetroCade_Sketch/tinysid.cpp +++ /dev/null @@ -1,933 +0,0 @@ -/*! - * @file tinysid.cpp - * Project tinysid Library - * @brief tinysid library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 9/24/13 - * License GPL-Unknown? - -TinySID library is the work of: -Tammo Hinrichs - 6510 and SID routines -Rainer Sinsch - PSP TinySID -Alvaro Lopes - Made work with ZPUino Soft Processor - -See -http://www.informatik.uni-frankfurt.de/~sinsch/TinySid.htm -http://www.syntheticsw.com/~sinsch/?id=7298b&s=k2 -http://www.syntheticsw.com/~sinsch - - */ - -#include "tinysid.h" -#include "SID.h" -#include -#include "ramFS.h" - -SID sid; - -unsigned short play_addr; -volatile int tick = 0; - -static uint8_t getmem(uint16_t addr) -{ - if (addr == 0xdd0d) memory[addr]=0; - //printf("READ %04x = %04x\n", addr, memory[addr]); - return memory[addr]; -} - -static void writeSIDreg(int reg, int value) -{ - //sidregs[reg] = value; - sid.writeData(reg, value); -} - -static void setmem(uint16_t addr, uint8_t value) -{ -// printf("WRITE %04x <- %02x\n", addr, value); - - if ((addr&0xfc00)==0xd400) { - //printf("SID WRITE %04x <- %02x cycle %d\n",addr,value,cycles); - writeSIDreg(addr & 31, value); - } - - if ((addr==0xdc04) || (addr==0xdc05)) { - // printf("CIA WRITE %04x <- %02x cycle %d\n",addr,value,cycles); - } - memory[addr]=value; -} - -static uint8_t getaddr(int mode) -{ - uint16_t ad,ad2; - switch(mode) - { - case imp: - cycles+=2; - return 0; - case imm: - cycles+=2; - return getmem(pc++); - case abs: - cycles+=4; - ad=getmem(pc++); - ad|=getmem(pc++)<<8; - return getmem(ad); - case absx: - cycles+=4; - ad=getmem(pc++); - ad|=256*getmem(pc++); - ad2=ad+x; - if ((ad2&0xff00)!=(ad&0xff00)) - cycles++; - return getmem(ad2); - case absy: - cycles+=4; - ad=getmem(pc++); - ad|=256*getmem(pc++); - ad2=ad+y; - if ((ad2&0xff00)!=(ad&0xff00)) - cycles++; - return getmem(ad2); - case zp: - cycles+=3; - ad=getmem(pc++); - return getmem(ad); - case zpx: - cycles+=4; - ad=getmem(pc++); - ad+=x; - return getmem(ad&0xff); - case zpy: - cycles+=4; - ad=getmem(pc++); - ad+=y; - return getmem(ad&0xff); - case indx: - cycles+=6; - ad=getmem(pc++); - ad+=x; - ad2=getmem(ad&0xff); - ad++; - ad2|=getmem(ad&0xff)<<8; - return getmem(ad2); - case indy: - cycles+=5; - ad=getmem(pc++); - ad2=getmem(ad); - ad2|=getmem((ad+1)&0xff)<<8; - ad=ad2+y; - if ((ad2&0xff00)!=(ad&0xff00)) - cycles++; - return getmem(ad); - case acc: - cycles+=2; - return a; - } - return 0; -} - - -static void setaddr(int mode, uint8_t val) -{ - uint16_t ad,ad2; - switch(mode) - { - case abs: - cycles+=2; - ad=getmem(pc-2); - ad|=256*getmem(pc-1); - setmem(ad,val); - return; - case absx: - cycles+=3; - ad=getmem(pc-2); - ad|=256*getmem(pc-1); - ad2=ad+x; - if ((ad2&0xff00)!=(ad&0xff00)) - cycles--; - setmem(ad2,val); - return; - case zp: - cycles+=2; - ad=getmem(pc-1); - setmem(ad,val); - return; - case zpx: - cycles+=2; - ad=getmem(pc-1); - ad+=x; - setmem(ad&0xff,val); - return; - case acc: - a=val; - return; - } -} - - -static void putaddr(int mode, uint8_t val) -{ - uint16_t ad,ad2; - switch(mode) - { - case abs: - cycles+=4; - ad=getmem(pc++); - ad|=getmem(pc++)<<8; - setmem(ad,val); - return; - case absx: - cycles+=4; - ad=getmem(pc++); - ad|=getmem(pc++)<<8; - ad2=ad+x; - setmem(ad2,val); - return; - case absy: - cycles+=4; - ad=getmem(pc++); - ad|=getmem(pc++)<<8; - ad2=ad+y; - if ((ad2&0xff00)!=(ad&0xff00)) - cycles++; - setmem(ad2,val); - return; - case zp: - cycles+=3; - ad=getmem(pc++); - setmem(ad,val); - return; - case zpx: - cycles+=4; - ad=getmem(pc++); - ad+=x; - setmem(ad&0xff,val); - return; - case zpy: - cycles+=4; - ad=getmem(pc++); - ad+=y; - setmem(ad&0xff,val); - return; - case indx: - cycles+=6; - ad=getmem(pc++); - ad+=x; - ad2=getmem(ad&0xff); - ad++; - ad2|=getmem(ad&0xff)<<8; - setmem(ad2,val); - return; - case indy: - cycles+=5; - ad=getmem(pc++); - ad2=getmem(ad); - ad2|=getmem((ad+1)&0xff)<<8; - ad=ad2+y; - setmem(ad,val); - return; - case acc: - cycles+=2; - a=val; - return; - } -} - - -static inline void setflags(int flag, int cond) -{ - // cond?p|=flag:p&=~flag; - if (cond) p|=flag; - else p&=~flag; -} - - -static inline void push(uint8_t val) -{ - setmem(0x100+s,val); - if (s) s--; -} - -static inline uint8_t pop() -{ - if (s<0xff) s++; - return getmem(0x100+s); -} - -static void branch(int flag) -{ - signed char dist; - dist=(signed char)getaddr(imm); - wval=pc+dist; - if (flag) - { - cycles+=((pc&0x100)!=(wval&0x100))?2:1; - pc=wval; - } -} - -// ----------------------------------------------------- ffentliche Routinen - -static void cpuReset() -{ - a=x=y=0; - p=0; - s=255; - pc=getaddr(0xfffc); -} - -static void cpuResetTo(uint16_t npc) -{ - a=0; - x=0; - y=0; - p=0; - s=255; - pc=npc; -} - -#define OP(x...) -//do { fprintf(stderr,x); fprintf(stderr,"\n"); } while(0) - -static int cpuParse() -{ - uint8_t opc; - int cmd, addr, c; - cycles=0; - - //#ifdef TRACE - // cpuStatus(); - // if (opcodes[getmem(pc)]==xxx) getch(); - //#endif - - opc=getmem(pc++); - cmd=opcodes[opc]; - addr=modes[opc]; -// fprintf(stderr,"$%04x [%02x]: ", pc-1, opc); - switch (cmd) - { - case OPadc: - OP("adc"); - wval=(uint16_t)a+getaddr(addr)+((p&FLAG_C)?1:0); - setflags(FLAG_C, wval&0x100); - a=(uint8_t)wval; - setflags(FLAG_Z, !a); - setflags(FLAG_N, a&0x80); - setflags(FLAG_V, (!!(p&FLAG_C)) ^ (!!(p&FLAG_N))); - break; - case OPand: - OP("and"); - bval=getaddr(addr); - a&=bval; - setflags(FLAG_Z, !a); - setflags(FLAG_N, a&0x80); - break; - case OPasl: - OP("asl"); - wval=getaddr(addr); - wval<<=1; - setaddr(addr,(uint8_t)wval); - setflags(FLAG_Z,!wval); - setflags(FLAG_N,wval&0x80); - setflags(FLAG_C,wval&0x100); - break; - case OPbcc: - OP("bcc"); - branch(!(p&FLAG_C)); - break; - case OPbcs: - OP("bcs"); - branch(p&FLAG_C); - break; - case OPbne: - OP("bne"); - branch(!(p&FLAG_Z)); - break; - case OPbeq: - OP("beq"); - branch(p&FLAG_Z); - break; - case OPbpl: - OP("bpl"); - branch(!(p&FLAG_N)); - break; - case OPbmi: - OP("bmi"); - branch(p&FLAG_N); - break; - case OPbvc: - OP("bvc"); - branch(!(p&FLAG_V)); - break; - case OPbvs: - OP("bvs"); - branch(p&FLAG_V); - break; - case OPbit: - OP("bit"); - bval=getaddr(addr); - setflags(FLAG_Z,!(a&bval)); - setflags(FLAG_N,bval&0x80); - setflags(FLAG_V,bval&0x40); - break; - case OPbrk: - OP("brk"); - push(pc&0xff); - push(pc>>8); - push(p); - setflags(FLAG_B,1); - pc=getmem(0xfffe); - cycles+=7; - break; - case OPclc: - OP("clc"); - cycles+=2; - setflags(FLAG_C,0); - break; - case OPcld: - OP("cld"); - cycles+=2; - setflags(FLAG_D,0); - break; - case OPcli: - OP("cli"); - cycles+=2; - setflags(FLAG_I,0); - break; - case OPclv: - OP("clv"); - cycles+=2; - setflags(FLAG_V,0); - break; - case OPcmp: - OP("cmp"); - bval=getaddr(addr); - wval=(uint16_t)a-bval; - setflags(FLAG_Z,!wval); - setflags(FLAG_N,wval&0x80); - setflags(FLAG_C,a>=bval); - break; - case OPcpx: - OP("cpx"); - bval=getaddr(addr); - wval=(uint16_t)x-bval; - setflags(FLAG_Z,!wval); - setflags(FLAG_N,wval&0x80); - setflags(FLAG_C,a>=bval); - break; - case OPcpy: - OP("cpy"); - bval=getaddr(addr); - wval=(uint16_t)y-bval; - setflags(FLAG_Z,!wval); - setflags(FLAG_N,wval&0x80); - setflags(FLAG_C,a>=bval); - break; - case OPdec: - OP("dec"); - bval=getaddr(addr); - bval--; - setaddr(addr,bval); - setflags(FLAG_Z,!bval); - setflags(FLAG_N,bval&0x80); - break; - case OPdex: - OP("dex"); - cycles+=2; - x--; - setflags(FLAG_Z,!x); - setflags(FLAG_N,x&0x80); - break; - case OPdey: - OP("dey"); - cycles+=2; - y--; - setflags(FLAG_Z,!y); - setflags(FLAG_N,y&0x80); - break; - case OPeor: - OP("eor"); - bval=getaddr(addr); - a^=bval; - setflags(FLAG_Z,!a); - setflags(FLAG_N,a&0x80); - break; - case OPinc: - OP("inc"); - bval=getaddr(addr); - bval++; - setaddr(addr,bval); - setflags(FLAG_Z,!bval); - setflags(FLAG_N,bval&0x80); - break; - case OPinx: - OP("inx"); - cycles+=2; - x++; - setflags(FLAG_Z,!x); - setflags(FLAG_N,x&0x80); - break; - case OPiny: - OP("iny"); - cycles+=2; - y++; - setflags(FLAG_Z,!y); - setflags(FLAG_N,y&0x80); - break; - case OPjmp: - cycles+=3; - wval=getmem(pc++); - wval|=256*getmem(pc++); - switch (addr) - { - case abs: - OP("jmp $%04x",wval); - pc=wval; - break; - case ind: - pc=getmem(wval); - pc|=256*getmem(wval+1); - OP("jmpr $%04x",pc); - cycles+=2; - break; - } - break; - case OPjsr: - OP("jsr"); - cycles+=6; - push((pc+2)); - push((pc+2)>>8); - wval=getmem(pc++); - wval|=256*getmem(pc++); - pc=wval; - break; - case OPlda: - OP("lda"); - a=getaddr(addr); - setflags(FLAG_Z,!a); - setflags(FLAG_N,a&0x80); - break; - case OPldx: - OP("ldx"); - x=getaddr(addr); - setflags(FLAG_Z,!x); - setflags(FLAG_N,x&0x80); - break; - case OPldy: - OP("ldy"); - y=getaddr(addr); - setflags(FLAG_Z,!y); - setflags(FLAG_N,y&0x80); - break; - case OPlsr: - OP("lsr"); - //bval=wval=getaddr(addr); - bval=getaddr(addr); wval=(uint8_t)bval; - wval>>=1; - setaddr(addr,(uint8_t)wval); - setflags(FLAG_Z,!wval); - setflags(FLAG_N,wval&0x80); - setflags(FLAG_C,bval&1); - break; - case OPnop: - OP("nop"); - cycles+=2; - break; - case OPora: - OP("ora"); - bval=getaddr(addr); - a|=bval; - setflags(FLAG_Z,!a); - setflags(FLAG_N,a&0x80); - break; - case OPpha: - OP("pha"); - push(a); - cycles+=3; - break; - case OPphp: - OP("php"); - push(p); - cycles+=3; - break; - case OPpla: - OP("pla"); - a=pop(); - setflags(FLAG_Z,!a); - setflags(FLAG_N,a&0x80); - cycles+=4; - break; - case OPplp: - OP("plp"); - p=pop(); - cycles+=4; - break; - case OProl: - OP("rol"); - bval=getaddr(addr); - c=!!(p&FLAG_C); - setflags(FLAG_C,bval&0x80); - bval<<=1; - bval|=c; - setaddr(addr,bval); - setflags(FLAG_N,bval&0x80); - setflags(FLAG_Z,!bval); - break; - case OPror: - OP("ror"); - bval=getaddr(addr); - c=!!(p&FLAG_C); - setflags(FLAG_C,bval&1); - bval>>=1; - bval|=128*c; - setaddr(addr,bval); - setflags(FLAG_N,bval&0x80); - setflags(FLAG_Z,!bval); - break; - case OPrti: - OP("rti"); - // NEU, rti wie rts, au�r das alle register wieder vom stack kommen - //p=pop(); - p=pop(); - y=pop(); - x=pop(); - a=pop(); - // in_nmi = false; - //write_console("NMI EXIT!"); - case OPrts: - OP("rts"); - wval=256*pop(); - wval|=pop(); - pc=wval; - cycles+=6; - break; - case OPsbc: - OP("sbc"); - bval=getaddr(addr)^0xff; - wval=(uint16_t)a+bval+((p&FLAG_C)?1:0); - setflags(FLAG_C, wval&0x100); - a=(uint8_t)wval; - setflags(FLAG_Z, !a); - setflags(FLAG_N, a>127); - setflags(FLAG_V, (!!(p&FLAG_C)) ^ (!!(p&FLAG_N))); - break; - case OPsec: - OP("sec"); - cycles+=2; - setflags(FLAG_C,1); - break; - case OPsed: - OP("sec"); - cycles+=2; - setflags(FLAG_D,1); - break; - case OPsei: - OP("sei"); - cycles+=2; - setflags(FLAG_I,1); - break; - case OPsta: - OP("sta"); - putaddr(addr,a); - break; - case OPstx: - OP("stx"); - putaddr(addr,x); - break; - case OPsty: - OP("sty"); - putaddr(addr,y); - break; - case OPtax: - OP("tax"); - cycles+=2; - x=a; - setflags(FLAG_Z, !x); - setflags(FLAG_N, x&0x80); - break; - case OPtay: - OP("tay"); - cycles+=2; - y=a; - setflags(FLAG_Z, !y); - setflags(FLAG_N, y&0x80); - break; - case OPtsx: - OP("tsx"); - cycles+=2; - x=s; - setflags(FLAG_Z, !x); - setflags(FLAG_N, x&0x80); - break; - case OPtxa: - OP("txa"); - cycles+=2; - a=x; - setflags(FLAG_Z, !a); - setflags(FLAG_N, a&0x80); - break; - case OPtxs: - OP("txs"); - cycles+=2; - s=x; - break; - case OPtya: - OP("tya"); - cycles+=2; - a=y; - setflags(FLAG_Z, !a); - setflags(FLAG_N, a&0x80); - break; - } - - return cycles; -} - -int cpuJSR(uint16_t npc, uint8_t na) -{ - int ccl; - - a=na; - x=0; - y=0; - p=0; - s=255; - pc=npc; - push(0); - push(0); - ccl=0; - while (pc) - { - ccl+=cpuParse(); - } - return ccl; -} - -static unsigned short LoadSIDFromMemory(const void *pSidData, unsigned short *load_addr, - unsigned short *init_addr, unsigned short *play_addr, - unsigned char *subsongs, unsigned char *startsong, - unsigned char *speed, unsigned short size) -{ - unsigned char *pData; - unsigned char data_file_offset; - - pData = (unsigned char*)pSidData; - data_file_offset = pData[7]; - - *load_addr = pData[8]<<8; - *load_addr|= pData[9]; - - *init_addr = pData[10]<<8; - *init_addr|= pData[11]; - - *play_addr = pData[12]<<8; - *play_addr|= pData[13]; - - *subsongs = pData[0xf]-1; - *startsong = pData[0x11]-1; - - *load_addr = pData[data_file_offset]; - *load_addr|= pData[data_file_offset+1]<<8; - - *speed = pData[0x15]; - - memset(memory, 0, sizeof(memory)); - memcpy(&memory[*load_addr], &pData[data_file_offset+2], size-(data_file_offset+2)); - - if (*play_addr == 0) - { - cpuJSR(*init_addr, 0); - *play_addr = (memory[0x0315]<<8)+memory[0x0314]; - } - - return *load_addr; -} - -static void dumpregs() -{ - int i; - Serial.print("R: "); - for (i=0;i<25;i++) { - Serial.print(sidregs[i], HEX); - Serial.print(" "); - } - Serial.println(""); -} - -void tinysid_zpu_interrupt() { - tick=1; - TMR0CTL &= ~(BIT(TCTLIF)); -} -static unsigned short init_addr; -//void tinysetup() -void tinyLoadFile(const char* name) -{ - unsigned short load_addr; - unsigned char subsongs,startsong,speed; - SmallFSFile sidSmallFSfile; - File sidSDfile; - - //fileLoaded = false; - if (SmallFS.begin()==0) - sidSmallFSfile = SmallFS.open(name); - sidSDfile = SD.open(name); //TODO begin SD? - boolean smallFsCheck = sidSmallFSfile.valid(); - boolean sdFsCheck = sidSDfile; - if (sdFsCheck){ - Serial.println("Opening SID File from SD Card."); - //modRAMfile = RamFS.open(&sidSDfile); - unsigned size = sidSDfile.size(); - unsigned char *buf = (unsigned char*)malloc(size); - /* Allocate */ - sidSDfile.read(buf,size); - LoadSIDFromMemory(buf, - &load_addr, - &init_addr, - &play_addr, - &subsongs, - &startsong, - &speed, - size); - sidSDfile.close(); - //fileLoaded = true; - } - else if (smallFsCheck){ - Serial.println("Opening SID File from SmallFS."); - //modRAMfile = RamFS.open(&sidSmallFSfile); - //fileLoaded = true; - unsigned size = sidSmallFSfile.size(); - unsigned char *buf = (unsigned char*)malloc(size); - /* Allocate */ - sidSmallFSfile.read(buf,size); - LoadSIDFromMemory(buf, - &load_addr, - &init_addr, - &play_addr, - &subsongs, - &startsong, - &speed, - size); - } - else { - Serial.println("No sid files to play in SmallFS or on SD card."); - //fileLoaded = false; - } - - //SmallFSFile file; - - //Serial.begin(115200); - //Serial.println("Starting"); - // if (SmallFS.begin()==0) { - // file = SmallFS.open(name); - //if (file.valid()) { -/* unsigned size = file->size(); - Serial.print("Size: "); - Serial.println(size); - unsigned char *buf = (unsigned char*)malloc(size); - /* Allocate */ - //file->read(buf,size); */ - - // LoadSIDFromMemory(buf, - // &load_addr, - // &init_addr, - // &play_addr, - // &subsongs, - // &startsong, - // &speed, - // size); - - //} - // } - // else { - // LoadSIDFromMemory( SIDTUNE, - // &load_addr, - // &init_addr, - // &play_addr, - // &subsongs, - // &startsong, - // &speed, - // sizeof(SIDTUNE)); - // } - - cpuReset(); - memset(sidregs,0,sizeof(sidregs)); - -/* #ifdef RETROCADE - //Move the audio output to the appropriate pins on the Papilio Hardware - pinMode(AUDIO_J1_L,OUTPUT); - digitalWrite(AUDIO_J1_L,HIGH); - //outputPinForFunction(AUDIO_J1_L, IOPIN_SIGMADELTA0); - outputPinForFunction(AUDIO_J1_L, 8); - pinModePPS(AUDIO_J1_L, HIGH); - - pinMode(AUDIO_J1_R,OUTPUT); - digitalWrite(AUDIO_J1_R,HIGH); - outputPinForFunction(AUDIO_J1_R, 8); - //outputPinForFunction(AUDIO_J1_R, IOPIN_SIGMADELTA1); - pinModePPS(AUDIO_J1_R, HIGH); - - pinMode(AUDIO_J2_L,OUTPUT); - digitalWrite(AUDIO_J2_L,HIGH); - outputPinForFunction(AUDIO_J2_L, 8); - pinModePPS(AUDIO_J2_L, HIGH); - - pinMode(AUDIO_J2_R,OUTPUT); - digitalWrite(AUDIO_J2_R,HIGH); - outputPinForFunction(AUDIO_J2_R, 8); - pinModePPS(AUDIO_J2_R, HIGH); -#else - - pinMode(WING_C_0,OUTPUT); - digitalWrite(WING_C_0,HIGH); - outputPinForFunction(WING_C_0, 8); - pinModePPS(WING_C_0, HIGH); - - pinMode(WING_C_1,OUTPUT); - digitalWrite(WING_C_1,HIGH); - outputPinForFunction(WING_C_1, 8); - pinModePPS(WING_C_1, HIGH); - -#endif */ - - cpuJSR(init_addr, 0); - // Prescale 64 (101b), generate 50Hz tick - -/* TMR0CMP = (CLK_FREQ/(50*64))-1; - TMR0CNT = 0x0; - TMR0CTL = BIT(TCTLENA)|BIT(TCTLCCM)|BIT(TCTLDIR)|BIT(TCTLCP2)|BIT(TCTLCP0)|BIT(TCTLIEN); - INTRMASK = BIT(INTRLINE_TIMER0); // Enable Timer0 interrupt - INTRCTL=1; */ -} - -void tinyloop() -{ - //while (1) { - if (tick == 1) { - int clocks = cpuJSR(play_addr,0); - tick=0; - } - //while (!tick); - /* Write SID regs here */ - //dumpregs(); - -/* if (Serial.available()) { - int r=Serial.read(); - if (r=='e') { - Serial.println("Enable"); - sid.writeData(25,1); - } - if (r=='d') { - Serial.println("Disable"); - sid.writeData(25,0); - } - if (r=='r') { - // Restart - Serial.println("Restart"); - cpuReset(); - memset(sidregs,0,sizeof(sidregs)); - cpuJSR(init_addr, 0); - } - } */ - //} -} diff --git a/RetroCade_Sketch/tinysid.h b/RetroCade_Sketch/tinysid.h deleted file mode 100644 index 51b8b3f..0000000 --- a/RetroCade_Sketch/tinysid.h +++ /dev/null @@ -1,135 +0,0 @@ -/*! - * @file tinysid.cpp - * Project tinysid Library - * @brief tinysid library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 9/24/13 - * License GPL-Unknown? - -TinySID library is the work of: -Tammo Hinrichs - 6510 and SID routines -Rainer Sinsch - PSP TinySID -Alvaro Lopes - Made work with ZPUino Soft Processor - -See -http://www.informatik.uni-frankfurt.de/~sinsch/TinySid.htm -http://www.syntheticsw.com/~sinsch/?id=7298b&s=k2 -http://www.syntheticsw.com/~sinsch - - */ - -#ifndef _TINYSID_H -#define _TINYSID_H - -#include "sidtune_Layla_Mix.h" -#include "SID.h" -#include -#include "ramFS.h" - -#define AUDIO_J1_L WING_B_1 -#define AUDIO_J1_R WING_B_0 - -#define AUDIO_J2_L WING_B_3 -#define AUDIO_J2_R WING_B_2 - -#define SIDBASE IO_SLOT(14) -#define SIDREG(x) REGISTER(SIDBASE,x) - -#define SIDTUNE sidtune_Layla_Mix -#define RETROCADE // Define this if you have a retrocade hw - - -// -- do not touch this below, it's a C64 emulator. - -#define FLAG_N 128 -#define FLAG_V 64 -#define FLAG_B 16 -#define FLAG_D 8 -#define FLAG_I 4 -#define FLAG_Z 2 -#define FLAG_C 1 - - -static unsigned char memory[65536]; - -typedef enum {OPadc, OPand, OPasl, OPbcc, OPbcs, OPbeq, OPbit, OPbmi, OPbne, OPbpl, OPbrk, OPbvc, OPbvs, OPclc, - OPcld, OPcli, OPclv, OPcmp, OPcpx, OPcpy, OPdec, OPdex, OPdey, OPeor, OPinc, OPinx, OPiny, OPjmp, - OPjsr, OPlda, OPldx, OPldy, OPlsr, OPnop, OPora, OPpha, OPphp, OPpla, OPplp, OProl, OPror, OPrti, - OPrts, OPsbc, OPsec, OPsed, OPsei, OPsta, OPstx, OPsty, OPtax, OPtay, OPtsx, OPtxa, OPtxs, OPtya, - OPxxx} insts; - -#define imp 0 -#define imm 1 -#define abs 2 -#define absx 3 -#define absy 4 -#define zp 6 -#define zpx 7 -#define zpy 8 -#define ind 9 -#define indx 10 -#define indy 11 -#define acc 12 -#define rel 13 -#define xxx 14 - -static uint8_t opcodes[256]= { - OPbrk,OPora,OPxxx,OPxxx,OPxxx,OPora,OPasl,OPxxx,OPphp,OPora,OPasl,OPxxx,OPxxx,OPora,OPasl,OPxxx, - OPbpl,OPora,OPxxx,OPxxx,OPxxx,OPora,OPasl,OPxxx,OPclc,OPora,OPxxx,OPxxx,OPxxx,OPora,OPasl,OPxxx, - OPjsr,OPand,OPxxx,OPxxx,OPbit,OPand,OProl,OPxxx,OPplp,OPand,OProl,OPxxx,OPbit,OPand,OProl,OPxxx, - OPbmi,OPand,OPxxx,OPxxx,OPxxx,OPand,OProl,OPxxx,OPsec,OPand,OPxxx,OPxxx,OPxxx,OPand,OProl,OPxxx, - OPrti,OPeor,OPxxx,OPxxx,OPxxx,OPeor,OPlsr,OPxxx,OPpha,OPeor,OPlsr,OPxxx,OPjmp,OPeor,OPlsr,OPxxx, - OPbvc,OPeor,OPxxx,OPxxx,OPxxx,OPeor,OPlsr,OPxxx,OPcli,OPeor,OPxxx,OPxxx,OPxxx,OPeor,OPlsr,OPxxx, - OPrts,OPadc,OPxxx,OPxxx,OPxxx,OPadc,OPror,OPxxx,OPpla,OPadc,OPror,OPxxx,OPjmp,OPadc,OPror,OPxxx, - OPbvs,OPadc,OPxxx,OPxxx,OPxxx,OPadc,OPror,OPxxx,OPsei,OPadc,OPxxx,OPxxx,OPxxx,OPadc,OPror,OPxxx, - OPxxx,OPsta,OPxxx,OPxxx,OPsty,OPsta,OPstx,OPxxx,OPdey,OPxxx,OPtxa,OPxxx,OPsty,OPsta,OPstx,OPxxx, - OPbcc,OPsta,OPxxx,OPxxx,OPsty,OPsta,OPstx,OPxxx,OPtya,OPsta,OPtxs,OPxxx,OPxxx,OPsta,OPxxx,OPxxx, - OPldy,OPlda,OPldx,OPxxx,OPldy,OPlda,OPldx,OPxxx,OPtay,OPlda,OPtax,OPxxx,OPldy,OPlda,OPldx,OPxxx, - OPbcs,OPlda,OPxxx,OPxxx,OPldy,OPlda,OPldx,OPxxx,OPclv,OPlda,OPtsx,OPxxx,OPldy,OPlda,OPldx,OPxxx, - OPcpy,OPcmp,OPxxx,OPxxx,OPcpy,OPcmp,OPdec,OPxxx,OPiny,OPcmp,OPdex,OPxxx,OPcpy,OPcmp,OPdec,OPxxx, - OPbne,OPcmp,OPxxx,OPxxx,OPxxx,OPcmp,OPdec,OPxxx,OPcld,OPcmp,OPxxx,OPxxx,OPxxx,OPcmp,OPdec,OPxxx, - OPcpx,OPsbc,OPxxx,OPxxx,OPcpx,OPsbc,OPinc,OPxxx,OPinx,OPsbc,OPnop,OPxxx,OPcpx,OPsbc,OPinc,OPxxx, - OPbeq,OPsbc,OPxxx,OPxxx,OPxxx,OPsbc,OPinc,OPxxx,OPsed,OPsbc,OPxxx,OPxxx,OPxxx,OPsbc,OPinc,OPxxx -}; - -static uint8_t modes[256]= { - imp,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,xxx,zpx,zpx,xxx,imp,absy,xxx,xxx,xxx,absx,absx,xxx, - abs,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,xxx,zpx,zpx,xxx,imp,absy,xxx,xxx,xxx,absx,absx,xxx, - imp,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,xxx,zpx,zpx,xxx,imp,absy,xxx,xxx,xxx,absx,absx,xxx, - imp,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,ind,abs,abs,xxx, - rel,indy,xxx,xxx,xxx,zpx,zpx,xxx,imp,absy,xxx,xxx,xxx,absx,absx,xxx, - imm,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,zpx,zpx,zpy,xxx,imp,absy,acc,xxx,xxx,absx,absx,xxx, - imm,indx,imm,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,zpx,zpx,zpy,xxx,imp,absy,acc,xxx,absx,absx,absy,xxx, - imm,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,zpx,zpx,zpx,xxx,imp,absy,acc,xxx,xxx,absx,absx,xxx, - imm,indx,xxx,xxx,zp,zp,zp,xxx,imp,imm,acc,xxx,abs,abs,abs,xxx, - rel,indy,xxx,xxx,zpx,zpx,zpx,xxx,imp,absy,acc,xxx,xxx,absx,absx,xxx -}; - -// ----------------------------------------------- globale Faulheitsvariablen - -static int cycles; -static uint8_t bval; -static uint16_t wval; - -// ----------------------------------------------------------------- Register - -static uint8_t a,x,y,s,p; -static uint16_t pc; - -// ----------------------------------------------------------- DER HARTE KERN - -static uint8_t sidregs[32]; - -//void tinysetup(); -void tinyLoadFile(const char* name); -void tinyloop(); -void tinysid_zpu_interrupt(); - -#endif diff --git a/RetroCade_Sketch/ymplayer.cpp b/RetroCade_Sketch/ymplayer.cpp deleted file mode 100644 index 30d5cc0..0000000 --- a/RetroCade_Sketch/ymplayer.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/*! - * @file ymplayer.cpp - * Project ymplayer Library - * @brief ymplayer library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ - -#include "ymplayer.h" -#include "YM2149.h" - -#define DEBUG -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) - -YMPLAYER::YMPLAYER(){ - -} - -/*! -@par Description -Initialize the YMPlayer -@par Syntax -ymplayer.setup(ym) -@param YM2149 Pointer to a YM2149 object - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" -#include "ymplayer.h" - -YM2149 ym2149; - -void setup() -{ - ymplayer.setup(&ym2149); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMPLAYER::setup(YM2149* ym){ - //underruns = 0; - timerTicks = 0; - ymTimeStamp = 0; - resetYMFlag = 0; - counter = 0; - playing = false; - ym2149 = ym; - volumeAdjust = 4; -} - -/*! -@par Description -Load a ym file from smallfs or a SD card. The provided file name will be searched for in the smallfs filesystem first and the SD file system second. If the filename exists in both locations the SD version will override the smallfs version. -@par Syntax -ymplayer.loadFile(name) -@param name filename of the ym file to open. - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" -#include "ymplayer.h" - -YM2149 ym2149; - -void setup() -{ - ymplayer.setup(&ym2149); - ymplayer.loadFile("track1.ymd"); - ymplayer.play(true); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMPLAYER::loadFile(const char* name) -{ - ymSDfile.close(); - ymTimeStamp = 0; - ymSmallFSfile = SmallFS.open(name); - if (!ymSmallFSfile.valid()) { - #ifdef DEBUG - Serial.println("There is no smallfs File."); - #endif - } - - ymSDfile = SD.open(name); //TODO: Should check for SD filesystem init first. - if (!ymSDfile){ - #ifdef DEBUG - Serial.println("There is no SD File."); - #endif - } -} - -/*! -@par Description -Play a ym file after it has been loaded. -@par Syntax -ymplayer.play(play) -@param play Will play the file if set to 1 or true. - -@par Example -~~~~~~~~{.c} -#include "YM2149.h" -#include "ymplayer.h" - -YM2149 ym2149; - -void setup() -{ - ymplayer.setup(&ym2149); - ymplayer.loadFile("track1.ymd"); - ymplayer.play(true); -} - -void loop() {} -~~~~~~~~ -\n -*/ -void YMPLAYER::play(boolean play) -{ - boolean smallfscheck = ymSmallFSfile.valid(); - if (!ymSDfile && !smallfscheck) { - play = false; - #ifdef DEBUG - Serial.println("Error: No SD or SmallFS File Available"); - #endif - return; - } - - if (smallfscheck) - fileType = SmallFSType; - if (ymSDfile) - fileType = SDFSType; - - playing = play; - if (play == true) - resetYMFlag = 1; -} - -void YMPLAYER::volume(int volume) -{ - volumeAdjust = volume; -} - -void YMPLAYER::audiofill() -{ - int r; - ymframe f; - while (!YMaudioBuffer.isFull()) { - switch (fileType) { - case SmallFSType: - r = ymSmallFSfile.read(&f.regval[0], 16); - break; - case SDFSType: - r = ymSDfile.read(&f.regval[0], 16); - break; - default: - return; - break; - } - - if (r==0) { - switch (fileType) { - case SmallFSType: - ymSmallFSfile.seek(0,SEEK_SET); - ymSmallFSfile.read(&f.regval[0], 16); - break; - case SDFSType: - ymSDfile.seek(0); - ymSDfile.read(&f.regval[0], 16); - break; - default: - return; - break; - } - } - //Adjust the volume level -// f.regval[8] = constrain(f.regval[8] - volumeAdjust, 0, 15); -// f.regval[9] = constrain(f.regval[9] - volumeAdjust, 0, 15); -// f.regval[10] = constrain(f.regval[10] - volumeAdjust, 0, 15); - //Adjust the volume level individually - f.regval[8] = constrain((f.regval[8] - (15-ym2149->V1.getVolume())), 0, 15); - f.regval[9] = constrain((f.regval[9] - (15-ym2149->V2.getVolume())), 0, 15); - f.regval[10] = constrain((f.regval[10] - (15-ym2149->V3.getVolume())), 0, 15); - YMaudioBuffer.push(f); - } -} - -boolean YMPLAYER::getPlaying() -{ - return playing; -} - -void YMPLAYER::zpu_interrupt() -{ - counter++; - if ( counter == 340 ) { - counter = 1; - ymTimeStamp++; - // Play YM file - if (YMaudioBuffer.hasData()) { - int i; - ymframe f = YMaudioBuffer.pop(); - for (i=0;i<14; i++) { - YM2149::writeData(i, f.regval[i]); - //YM2149REG(i) = f.regval[i]; - } - } - else{ - if (resetYMFlag == 1){ - ym2149->reset(); - ym2149->V1.setVolume(11); - ym2149->V2.setVolume(11); - ym2149->V3.setVolume(11); - resetYMFlag = 0; - ymTimeStamp = 1; - } - } - } -} - diff --git a/RetroCade_Sketch/ymplayer.h b/RetroCade_Sketch/ymplayer.h deleted file mode 100644 index 3114f73..0000000 --- a/RetroCade_Sketch/ymplayer.h +++ /dev/null @@ -1,55 +0,0 @@ -/*! - * @file ymplayer.h - * Project ymplayer Library - * @brief ymplayer library for the ZPUino - * Version 1.0 - * @author Jack Gassett - * @date 4/10/12 - * License GPL - */ - -#ifndef LIB_YMPLAYER_H_ -#define LIB_YMPLAYER_H_ - -#include -#include -#include -#include "Arduino.h" -#include "SmallFS.h" -#include "cbuffer.h" -#include "YM2149.h" -#include -//#include "RetroCade.h" -#include "retrocade_defs.h" - -class YMPLAYER -{ - public: - YMPLAYER(); - void setup(YM2149* ym); - void loadFile(const char* name); - void play(boolean play); - boolean getPlaying(); - void audiofill(); - void zpu_interrupt(); - void volume(int volume); - private: - struct ymframe { - unsigned char regval[14]; - }; - CircularBuffer YMaudioBuffer; - unsigned int timerTicks; - int counter; - byte volumeAdjust; - int ymTimeStamp; - int resetYMFlag; - YM2149* ym2149; - SmallFSFile ymSmallFSfile; - File ymSDfile; - boolean playing; - kFileType fileType; - -}; - - -#endif // LIB_YMPLAYER_H_ diff --git a/ZPUino_SOC/RetroCade-1.1-zpuino-1.0-PapilioPro-S6LX9-RetroCade-1.1.bit b/ZPUino_SOC/RetroCade-1.1-zpuino-1.0-PapilioPro-S6LX9-RetroCade-1.1.bit new file mode 100644 index 0000000..63f18d5 Binary files /dev/null and b/ZPUino_SOC/RetroCade-1.1-zpuino-1.0-PapilioPro-S6LX9-RetroCade-1.1.bit differ diff --git a/ZPUino_SOC/readme.txt b/ZPUino_SOC/readme.txt index ef66bb4..63268e9 100644 --- a/ZPUino_SOC/readme.txt +++ b/ZPUino_SOC/readme.txt @@ -2,6 +2,8 @@ This is a snapshot of the ZPUino RetroCade Variant. The Gadget Factory branch of the ZPUino RetroCade Source code is located at: https://github.com/GadgetFactory/ZPUino-HDL +or +https://github.com/GadgetFactory/Papilio-SOC Alvaro's official ZPUino repository is at: https://github.com/alvieboy/ZPUino-HDL diff --git a/readme.txt b/readme.txt index 25ef3c8..cff2782 100644 --- a/readme.txt +++ b/readme.txt @@ -8,6 +8,10 @@ Requirements: *You must have FlowStone installed to modify the Dashboard. The free version can be downloaded from: http://www.dsprobotics.com/download.php ChangeLog: +9/26/2013 Version 1.1 + -Added SID Analog Filters!!!!!!!! Thanks to Alvie for writing the VHDL code. + -Added SidPlayer library to process SID files from smallFS and SD Cards. Thanks to Alvie for porting to the ZPUino. + 1/9/2013 Version 1.02 -NoteOff fix from Lee O'D