Example #1
0
static void XGC_extractMusic(XGM* xgc, XGM* xgm)
{
    LList* vgmCommands;
    LList* frameCommands = NULL;
    LList* ymCommands = NULL;
    LList* ymKeyCommands = NULL;
    LList* psgCommands = NULL;
    LList* otherCommands = NULL;
    LList* newCommands = NULL;
    LList* stateChange = NULL;
    LList* xgcCommands;
    LList* com;
    LList* tmpCom;

    XGMCommand* sizeCommand;
    YM2612* ymOldState;
    YM2612* ymState;
    int j, size;

    ymOldState = YM2612_create();
    ymState = YM2612_create();

    // reset frame
    xgcCommands = createElement(XGCCommand_createFrameSizeCommand(0));

    // TL / D1L / RR set to max
    vgmCommands = NULL;
    vgmCommands = insertAllAfterLList(vgmCommands, VGMCommand_createYMCommands(0, 0x40, 0x7F));
    vgmCommands = insertAllAfterLList(vgmCommands, VGMCommand_createYMCommands(0, 0x80, 0xFF));
    vgmCommands = getHeadLList(vgmCommands);

    xgcCommands = insertAllAfterLList(xgcCommands, XGCCommand_convert(XGMCommand_createYMPort0Commands(vgmCommands)));

    // set ym state
    com = vgmCommands;
    while(com != NULL)
    {
        VGMCommand* command = com->element;
        YM2612_set(ymState, VGMCommand_getYM2612Port(command), VGMCommand_getYM2612Register(command), VGMCommand_getYM2612Value(command));
        com = com->next;
    }

    deleteLList(vgmCommands);
    vgmCommands = NULL;
    vgmCommands = insertAllAfterLList(vgmCommands, VGMCommand_createYMCommands(1, 0x40, 0x7F));
    vgmCommands = insertAllAfterLList(vgmCommands, VGMCommand_createYMCommands(1, 0x80, 0xFF));
    vgmCommands = getHeadLList(vgmCommands);

    xgcCommands = insertAllAfterLList(xgcCommands, XGCCommand_convert(XGMCommand_createYMPort1Commands(vgmCommands)));

    // set ym state
    com = vgmCommands;
    while(com != NULL)
    {
        VGMCommand* command = com->element;
        YM2612_set(ymState, VGMCommand_getYM2612Port(command), VGMCommand_getYM2612Register(command), VGMCommand_getYM2612Value(command));
        com = com->next;
    }

    // key off for all channels
    deleteLList(vgmCommands);
    vgmCommands = NULL;
    vgmCommands = insertAfterLList(vgmCommands, VGMCommand_createYMCommand(0, 0x28, 0x00));
    vgmCommands = insertAfterLList(vgmCommands, VGMCommand_createYMCommand(0, 0x28, 0x01));
    vgmCommands = insertAfterLList(vgmCommands, VGMCommand_createYMCommand(0, 0x28, 0x02));
    vgmCommands = insertAfterLList(vgmCommands, VGMCommand_createYMCommand(0, 0x28, 0x04));
    vgmCommands = insertAfterLList(vgmCommands, VGMCommand_createYMCommand(0, 0x28, 0x05));
    vgmCommands = insertAfterLList(vgmCommands, VGMCommand_createYMCommand(0, 0x28, 0x06));
    vgmCommands = getHeadLList(vgmCommands);

    xgcCommands = insertAllAfterLList(xgcCommands, XGCCommand_convert(XGMCommand_createYMKeyCommands(vgmCommands)));

    // set ym state
    com = vgmCommands;
    while(com != NULL)
    {
        VGMCommand* command = com->element;
        YM2612_set(ymState, VGMCommand_getYM2612Port(command), VGMCommand_getYM2612Register(command), VGMCommand_getYM2612Value(command));
        com = com->next;
    }

    stateChange = XGC_getStateChange(ymState, ymOldState);
    // add the state commands if no empty
    if (stateChange != NULL)
        xgcCommands = insertAllAfterLList(xgcCommands, XGCCommand_createStateCommands(stateChange));

    // add 3 dummy frames (reserve frame space for PCM shift)
    xgcCommands = insertAfterLList(xgcCommands, XGCCommand_createFrameSizeCommand(0));
    xgcCommands = insertAfterLList(xgcCommands, XGCCommand_createFrameSizeCommand(0));
    xgcCommands = insertAfterLList(xgcCommands, XGCCommand_createFrameSizeCommand(0));

    XGMCommand* loopCommand = XGM_getLoopPointedCommand(xgm);
    int loopOffset = -1;

    com = xgm->commands;
    while(com != NULL)
    {
        // build frame commands
        deleteLList(frameCommands);
        frameCommands = NULL;

        while(com != NULL)
        {
            // get command and pass to next one
            XGMCommand* command = com->element;
            com = com->next;

            // this is the command where we loop
            if (command == loopCommand)
            {
                if (loopOffset == -1)
                    loopOffset = XGM_getMusicDataSizeOf(getHeadLList(xgcCommands));
            }

            // loop information --> ignore
            if (XGMCommand_isLoop(command) || XGMCommand_isEnd(command))
                continue;
            // stop here
            if (XGMCommand_isFrame(command))
                break;

            // add command
            frameCommands = insertAfterLList(frameCommands, command);
        }

        // get back to head
        frameCommands = getHeadLList(frameCommands);

        // update state
        ymOldState = ymState;
        ymState = YM2612_copy(ymOldState);

        // prepare new commands for this frame
        deleteLList(newCommands);
        // add size command
        sizeCommand = XGCCommand_createFrameSizeCommand(0);
        newCommands = createElement(sizeCommand);

        // group commands
        deleteLList(ymCommands);
        deleteLList(ymKeyCommands);
        deleteLList(psgCommands);
        deleteLList(otherCommands);
        ymCommands = NULL;
        ymKeyCommands = NULL;
        psgCommands = NULL;
        otherCommands = NULL;

        tmpCom = frameCommands;
        while(tmpCom != NULL)
        {
            XGMCommand* command = tmpCom->element;

            if (XGMCommand_isPSGWrite(command))
                psgCommands = insertAfterLList(psgCommands, command);
            else if (XGMCommand_isYM2612RegKeyWrite(command))
                ymKeyCommands = insertAfterLList(ymKeyCommands, command);
            else if (XGMCommand_isYM2612Write(command))
            {
                // update YM state
                for (j = 0; j < XGMCommand_getYM2612WriteCount(command); j++)
                {
                    if (XGMCommand_isYM2612Port0Write(command))
                        YM2612_set(ymState, 0, command->data[(j * 2) + 1] & 0xFF, command->data[(j * 2) + 2] & 0xFF);
                    else
                        YM2612_set(ymState, 1, command->data[(j * 2) + 1] & 0xFF, command->data[(j * 2) + 2] & 0xFF);
                }

                // remove all $2B register writes (DAC enable is done automatically)
                if (XGMCommand_removeYM2612RegWrite(command, 0, 0x2B))
                    ymCommands = insertAfterLList(ymCommands, command);
            }
            else
                otherCommands = insertAfterLList(otherCommands, command);

            tmpCom = tmpCom->next;
        }

        XGMCommand* pcmComCH[4];
        pcmComCH[0] = NULL;
        pcmComCH[1] = NULL;
        pcmComCH[2] = NULL;
        pcmComCH[3] = NULL;

        // discard multi PCM command in a single frame
        tmpCom = otherCommands;
        while(tmpCom != NULL)
        {
            XGMCommand* command = tmpCom->element;

            if (XGMCommand_isPCM(command))
            {
                // get channel
                int ch = XGMCommand_getPCMChannel(command);

                // already have a PCM command for this channel ?
                if (pcmComCH[ch] != NULL)
                {
                    // remove current PCM command
                    removeFromLList(tmpCom);
                    // we removed the last command --> update pointer
                    if (tmpCom == otherCommands)
                        otherCommands = tmpCom->prev;

                    if (!silent)
                    {
                        int frameInd = XGC_computeLenInFrameOf(getHeadLList(xgcCommands));
                        int id = XGMCommand_getPCMId(command);

                        // we are ignoring a real play command --> display it
                        if (id != 0)
                            printf("Warning: multiple PCM command on %d --> play %2X removed\n", frameInd, id);
                    }
                }
                else
                    pcmComCH[ch] = command;
            }

            tmpCom = tmpCom->prev;
        }

        psgCommands = getHeadLList(psgCommands);
        ymCommands = getHeadLList(ymCommands);
        ymKeyCommands = getHeadLList(ymKeyCommands);
        otherCommands = getHeadLList(otherCommands);

        // PSG commands first as PSG require main BUS access (DMA contention)
        if (psgCommands != NULL)
            newCommands = insertAllAfterLList(newCommands, XGCCommand_convert(psgCommands));
        // then general YM commands
        if (ymCommands != NULL)
            newCommands = insertAllAfterLList(newCommands, XGCCommand_convert(ymCommands));
        // then key commands
        if (ymKeyCommands != NULL)
            newCommands = insertAllAfterLList(newCommands, XGCCommand_convert(ymKeyCommands));
        // and finally others commands
        if (otherCommands != NULL)
            newCommands = insertAllAfterLList(newCommands, XGCCommand_convert(otherCommands));

        // state change
        stateChange = XGC_getStateChange(ymState, ymOldState);
        // add the state command if no empty
        if (stateChange != NULL)
            newCommands = insertAllAfterLList(newCommands, XGCCommand_createStateCommands(stateChange));

        // is it the last frame ?
        if (com == NULL)
        {
            // loop point ?
            if (loopOffset != -1)
                newCommands = insertAfterLList(newCommands, XGMCommand_createLoopCommand(loopOffset));
            else
                // add end command
                newCommands = insertAfterLList(newCommands, XGMCommand_createEndCommand());
        }

        // get back to head
        newCommands = getHeadLList(newCommands);

        // limit frame commands to 255 bytes max
        size = 0;
        tmpCom = newCommands;
        while(tmpCom != NULL)
        {
            XGMCommand* command = tmpCom->element;

            // limit reached ?
            if ((size + command->size) >= 256)
            {
//                if ((frameInd > 10) && (!silent))
                if (!silent)
                {
                    int frameInd = XGC_computeLenInFrameOf(getHeadLList(xgcCommands)) + (XGC_computeLenInFrameOf(newCommands) - 1);
                    printf("Warning: frame > 256 at frame %4X (need to split frame)\n", frameInd);
                }

                // end previous frame
                XGCCommand_setFrameSizeSize(sizeCommand, size);

                // insert new frame size info
                sizeCommand = XGCCommand_createFrameSizeCommand(0);
                insertBeforeLList(tmpCom, sizeCommand);

                // reset size and pass to next element
                size = 1;
            }

            size += command->size;
            tmpCom = tmpCom->next;
        }

        // set frame size
        XGCCommand_setFrameSizeSize(sizeCommand, size);

        // finally add the new commands
        xgcCommands = insertAllAfterLList(xgcCommands, newCommands);
    }

    xgc->commands = getHeadLList(xgcCommands);

    // compute offset & frame size
    XGC_computeAllOffset(xgc);
    XGC_computeAllFrameSize(xgc);

    if (!silent)
        printf("Number of command: %d\n", getSizeLList(xgc->commands));
}
Example #2
0
File: xgm.c Project: clbr/SGDK
static void XGM_extractMusic(XGM* xgm, VGM* vgm)
{
    LList* frameCommands = NULL;
    LList* ymKeyCommands = NULL;
    LList* ymPort0Commands = NULL;
    LList* ymPort1Commands = NULL;
    LList* psgCommands = NULL;
    LList* sampleCommands = NULL;

    LList* xgmCommands = NULL;

    int loopOffset = -1;
    int frame = 0;
    bool loopEnd;
    bool hasKeyCom;

    LList* vgmCom = vgm->commands;
    while (vgmCom != NULL)
    {
        // get frame commands
        deleteLList(frameCommands);
        frameCommands = NULL;
        loopEnd = false;

        while (vgmCom != NULL)
        {
            VGMCommand* command = vgmCom->element;
            vgmCom = vgmCom->next;

            // ignore data block
            if (VGMCommand_isDataBlock(command))
                continue;

            // save loop start
            if (VGMCommand_isLoopStart(command))
            {
                if (loopOffset == -1)
                    loopOffset = XGM_getMusicDataSizeOf(getHeadLList(xgm->commands));
                continue;
            }
            // save loop end
            if (VGMCommand_isLoopEnd(command))
            {
                loopEnd = true;
                continue;
            }
            // stop here
            if (VGMCommand_isWait(command))
            {
                // set PAL flag if not already set
                if (xgm->pal == -1)
                {
                    if (VGMCommand_isWaitPAL(command))
                        xgm->pal = 1;
                    else if (VGMCommand_isWaitNTSC(command))
                        xgm->pal = 0;
                }

                break;
            }

            if (VGMCommand_isEnd(command))
                break;

            // add command
            frameCommands = insertAfterLList(frameCommands, command);
        }

        // prepare new commands for this frame
        deleteLList(xgmCommands);
        xgmCommands = NULL;

        // group commands
        deleteLList(ymKeyCommands);
        deleteLList(ymPort0Commands);
        deleteLList(ymPort1Commands);
        deleteLList(psgCommands);
        deleteLList(sampleCommands);
        ymKeyCommands = NULL;
        ymPort0Commands = NULL;
        ymPort1Commands = NULL;
        psgCommands = NULL;
        sampleCommands = NULL;

        hasKeyCom = false;

        LList* com = getHeadLList(frameCommands);
        while(com != NULL)
        {
            VGMCommand* command = com->element;

            if (VGMCommand_isStream(command))
                sampleCommands = insertAfterLList(sampleCommands, command);
            else if (VGMCommand_isPSGWrite(command))
                psgCommands = insertAfterLList(psgCommands, command);
            else if (VGMCommand_isYM2612KeyWrite(command))
            {
                // keep all key commands
                ymKeyCommands = insertAfterLList(ymKeyCommands, command);
                hasKeyCom = true;
            }
            else if (VGMCommand_isYM2612Write(command))
            {
                // need accurate order of key event / register write so we transfer commands now
                if (hasKeyCom)
                {
                    ymPort0Commands = getHeadLList(ymPort0Commands);
                    ymPort1Commands = getHeadLList(ymPort1Commands);
                    ymKeyCommands = getHeadLList(ymKeyCommands);

                    // general YM commands first as key event were just done
                    if (ymPort0Commands != NULL)
                        xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createYMPort0Commands(ymPort0Commands));
                    if (ymPort1Commands != NULL)
                        xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createYMPort1Commands(ymPort1Commands));
                    // then key commands
                    if (ymKeyCommands != NULL)
                        xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createYMKeyCommands(ymKeyCommands));

                    deleteLList(ymPort0Commands);
                    deleteLList(ymPort1Commands);
                    deleteLList(ymKeyCommands);
                    ymPort0Commands = NULL;
                    ymPort1Commands = NULL;
                    ymKeyCommands = NULL;

                    hasKeyCom = false;
                }

                if (VGMCommand_isYM2612Port0Write(command))
                    ymPort0Commands = insertAfterLList(ymPort0Commands, command);
                else
                    ymPort1Commands = insertAfterLList(ymPort1Commands, command);
            }
            else
            {
                if (verbose)
                    printf("Command %d ignored at frame %d\n", command->command, frame);
            }

            com = com->next;
        }

        ymPort0Commands = getHeadLList(ymPort0Commands);
        ymPort1Commands = getHeadLList(ymPort1Commands);
        ymKeyCommands = getHeadLList(ymKeyCommands);
        psgCommands = getHeadLList(psgCommands);
        sampleCommands = getHeadLList(sampleCommands);

        // general YM commands first as key event were just done
        if (ymPort0Commands != NULL)
            xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createYMPort0Commands(ymPort0Commands));
        if (ymPort1Commands != NULL)
            xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createYMPort1Commands(ymPort1Commands));
        // then key commands
        if (ymKeyCommands != NULL)
            xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createYMKeyCommands(ymKeyCommands));
        // then PSG commands
        if (psgCommands != NULL)
            xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createPSGCommands(psgCommands));
        // and finally PCM commands
        if (sampleCommands != NULL)
            xgmCommands = insertAllAfterLList(xgmCommands, XGMCommand_createPCMCommands(xgm, vgm, sampleCommands));

        // loop point ?
        if (loopEnd)
        {
            if (loopOffset != -1)
            {
                xgmCommands = insertAfterLList(xgmCommands, XGMCommand_createLoopCommand(loopOffset));
                loopOffset = -1;
            }
        }

        // last frame ?
        if (vgmCom == NULL)
        {
            // loop point not yet defined (should not arrive) ?
            if (loopOffset != -1)
            {
                loopEnd = true;
                xgmCommands = insertAfterLList(xgmCommands, XGMCommand_createLoopCommand(loopOffset));
                loopOffset = -1;
            }

            // add end command
            xgmCommands = insertAfterLList(xgmCommands, XGMCommand_createEndCommand());
        }
        // end frame
        else xgmCommands = insertAfterLList(xgmCommands, XGMCommand_createFrameCommand());

        // get back to head of frame commands
        xgmCommands = getHeadLList(xgmCommands);
        int numCom = getSizeLList(xgmCommands);

        // heavy frame warning, probably something wrong here...
        if (numCom > 200)
        {
            // show warning
            if (!silent)
                printf("Warning: Heavy frame at position %d (%d commands), playback may be altered !\n", frame, numCom);

            // verbose enable --> log frame command into a file
//            if (verbose)
//            {
//                char filename[32];
//
//                sprintf(filename, "frame_%.4X.log", frame);
//                XGMCommand_logCommands(filename, xgmCommands);
//            }
        }

        // finally add the new commands
        xgm->commands = insertAllAfterLList(xgm->commands, xgmCommands);
        // next frame
        frame++;
    }

    // get back to head
    xgm->commands = getHeadLList(xgm->commands);

    // recompute all offset
    XGM_computeAllOffset(xgm);

    if (!silent)
        printf("Number of command: %d\n", getSizeLList(xgm->commands));
}