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)); }
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)); }