예제 #1
0
bool SidTuneWrite::setInfo (const SidTuneInfo &tuneInfo)
{
    SidTuneInfo info = tuneInfo;

    // Lets verify some of the data
    if ((info.currentSong > info.songs)  || (info.currentSong == 0) ||
        (info.songs > SIDTUNE_MAX_SONGS) || (info.startSong == 0))
    {
        m_info.statusString = txt_songNumberExceed;
        return false;
    }

    if (info.loadAddr == 0)
    {
        m_info.statusString = txt_badAddr;
        return false;
    }

    if (info.sidModel1 > SIDTUNE_COMPATIBILITY_BASIC)
    {
        m_info.statusString = txt_invalidCompatibility;
        return false;
    }

    if (info.clockSpeed > SIDTUNE_CLOCK_ANY)
    {
        m_info.statusString = txt_invalidClockSpeed;
        return false;
    }

    if (info.sidModel1 > SIDTUNE_SIDMODEL_ANY)
    {
        m_info.statusString = txt_invalidSidModel;
        return false;
    }

    if (info.sidModel2 > SIDTUNE_SIDMODEL_ANY)
    {
        m_info.statusString = txt_invalidSidModel;
        return false;
    }

    switch (info.songSpeed)
    {
    case SIDTUNE_SPEED_CIA_1A:
        switch (info.compatibility)
        {
        case SIDTUNE_COMPATIBILITY_R64:
        case SIDTUNE_COMPATIBILITY_BASIC:
            m_info.statusString = txt_vbiClockSpeed;
            return false;
        }
        break;
    case SIDTUNE_SPEED_VBI:
        break;
    default:
        m_info.statusString = txt_invalidSongSpeed;
        return false;
    }

    if (!resolveAddrs(info, 0))
    {
        m_info.statusString = info.statusString;
        return false;
    }

    if (!checkRelocInfo(info))
    {
        m_info.statusString = info.statusString;
        return false;
    }

    if (!checkCompatibility(info))
    {
        m_info.statusString = info.statusString;
        return false;
    }

    m_info = info;

    for ( uint_least16_t sNum = 0; sNum < m_info.numberOfInfoStrings; sNum++ )
    {
        m_info.infoString[sNum] = infoString[sNum];
        for ( uint_least16_t sPos = 0; sPos < SIDTUNE_MAX_CREDIT_STRLEN; sPos++ )
            infoString[sNum][sPos] = info.infoString[sNum][sPos];
    }

    for ( uint_least16_t sNum = m_info.numberOfInfoStrings; sNum < SIDTUNE_MAX_CREDIT_STRINGS; sNum++ )
    {
        m_info.infoString[sNum] = infoString[sNum];
        for ( uint_least16_t sPos = 0; sPos < SIDTUNE_MAX_CREDIT_STRLEN; sPos++ )
            infoString[sNum][sPos] = '\0';
    }

    songSpeed[m_info.currentSong-1] = m_info.songSpeed;
    return true;
}
예제 #2
0
void SidTuneBase::acceptSidTune(const char* dataFileName, const char* infoFileName,
                            buffer_t& buf, bool isSlashedFileName)
{
    // Make a copy of the data file name and path, if available.
    if (dataFileName != nullptr)
    {
        const size_t fileNamePos = isSlashedFileName ?
            SidTuneTools::slashedFileNameWithoutPath(dataFileName) :
            SidTuneTools::fileNameWithoutPath(dataFileName);
        info->m_path = std::string(dataFileName, fileNamePos);
        info->m_dataFileName = std::string(dataFileName + fileNamePos);
    }

    // Make a copy of the info file name, if available.
    if (infoFileName != nullptr)
    {
        const size_t fileNamePos = isSlashedFileName ?
            SidTuneTools::slashedFileNameWithoutPath(infoFileName) :
            SidTuneTools::fileNameWithoutPath(infoFileName);
        info->m_infoFileName = std::string(infoFileName + fileNamePos);
    }

    // Fix bad sidtune set up.
    if (info->m_songs > MAX_SONGS)
    {
        info->m_songs = MAX_SONGS;
    }
    else if (info->m_songs == 0)
    {
        info->m_songs = 1;
    }

    if (info->m_startSong == 0
        || info->m_startSong > info->m_songs)
    {
        info->m_startSong = 1;
    }

    info->m_dataFileLen = buf.size();
    info->m_c64dataLen = buf.size() - fileOffset;

    // Calculate any remaining addresses and then
    // confirm all the file details are correct
    resolveAddrs(&buf[fileOffset]);

    if (checkRelocInfo() == false)
    {
        throw loadError(ERR_BAD_RELOC);
    }
    if (checkCompatibility() == false)
    {
         throw loadError(ERR_BAD_ADDR);
    }

    if (info->m_dataFileLen >= 2)
    {
        // We only detect an offset of two. Some position independent
        // sidtunes contain a load address of 0xE000, but are loaded
        // to 0x0FFE and call player at 0x1000.
        info->m_fixLoad = (endian_little16(&buf[fileOffset])==(info->m_loadAddr+2));
    }

    // Check the size of the data.
    if (info->m_c64dataLen > MAX_MEMORY)
    {
        throw loadError(ERR_DATA_TOO_LONG);
    }
    else if (info->m_c64dataLen == 0)
    {
        throw loadError(ERR_EMPTY);
    }

    cache.swap(buf);
}